Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 80677dc

Browse files
authored
[CIR][NEON] Add lowering support for vceqzd_s64 (llvm#179779)
Rather than creating a dedicated ClangIR test file, the original test file for this intrinsic is effectively reused: * clang/test/CodeGen/AArch64/neon-intrinsics.c “Effectively” meaning that the corresponding test is moved (rather than literally reused) to a new file within the original AArch64 builtins test directory: * clang/test/CodeGen/AArch64/neon/intrinsics.c This is necessary to avoid lowering unsupported examples from intrinsics.c with `-fclangir`. The new file will eventually replace the original one once all builtins from it can be lowered via ClangIR. To facilitate test re-use, new LIT "feature" is added so that CIR tests can be run conditionally, e.g. the following will only run when `CLANG_ENABLE_CIR` is set: ```C // RUN: %if cir %{%clang_cc1 ... %} ``` This sort of substitutions are documented in [2]. REFERENCES: [1] https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon]&q=vceqzd_s64 [2] https://llvm.org/docs/TestingGuide.html#substitutions
1 parent 48f5342 commit 80677dc

7 files changed

Lines changed: 89 additions & 15 deletions

File tree

clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
//===---- CIRGenBuiltinAArch64.cpp - Emit CIR for AArch64 builtins --------===//
2-
//
32
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43
// See https://llvm.org/LICENSE.txt for license information.
54
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -88,6 +87,42 @@ findARMVectorIntrinsicInMap(ArrayRef<AArch64BuiltinInfo> intrinsicMap,
8887
return nullptr;
8988
}
9089

90+
//===----------------------------------------------------------------------===//
91+
// Emit-helpers
92+
//===----------------------------------------------------------------------===//
93+
static mlir::Value
94+
emitAArch64CompareBuiltinExpr(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
95+
mlir::Location loc, mlir::Value src,
96+
mlir::Type retTy, const cir::CmpOpKind kind) {
97+
98+
bool scalarCmp = !isa<cir::VectorType>(src.getType());
99+
if (!scalarCmp) {
100+
assert(cast<cir::VectorType>(retTy).getIsScalable() &&
101+
"This is only intended for fixed-width vectors");
102+
// Vector retTypes are cast to i8 vectors. Recover original retType.
103+
cgf.cgm.errorNYI(loc, std::string("unimplemented vector compare"));
104+
}
105+
106+
mlir::Value zero = builder.getNullValue(src.getType(), loc);
107+
mlir::Value cmp;
108+
if (cir::isFPOrVectorOfFPType(src.getType())) {
109+
cgf.cgm.errorNYI(loc, std::string("unimplemented FP compare"));
110+
} else {
111+
if (scalarCmp)
112+
// For scalars, cast !cir.bool to !cir.int<s, 1> so that the compare
113+
// result is sign- rather zero-extended when casting to the output
114+
// retType.
115+
cmp = builder.createCast(
116+
loc, cir::CastKind::bool_to_int,
117+
builder.createCompare(loc, cir::CmpOpKind::eq, src, zero),
118+
builder.getSIntNTy(1));
119+
else
120+
cgf.cgm.errorNYI(loc, std::string("unimplemented vector compare"));
121+
}
122+
123+
return builder.createCast(loc, cir::CastKind::integral, cmp, retTy);
124+
}
125+
91126
bool CIRGenFunction::getAArch64SVEProcessedOperands(
92127
unsigned builtinID, const CallExpr *expr, SmallVectorImpl<mlir::Value> &ops,
93128
SVETypeFlags typeFlags) {
@@ -1357,7 +1392,15 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
13571392
case NEON::BI__builtin_neon_vpaddd_s64:
13581393
case NEON::BI__builtin_neon_vpaddd_f64:
13591394
case NEON::BI__builtin_neon_vpadds_f32:
1395+
cgm.errorNYI(expr->getSourceRange(),
1396+
std::string("unimplemented AArch64 builtin call: ") +
1397+
getContext().BuiltinInfo.getName(builtinID));
1398+
return mlir::Value{};
13601399
case NEON::BI__builtin_neon_vceqzd_s64:
1400+
ops.push_back(emitScalarExpr(expr->getArg(0)));
1401+
return emitAArch64CompareBuiltinExpr(
1402+
*this, builder, loc, ops[0],
1403+
convertType(expr->getCallReturnType(getContext())), cir::CmpOpKind::eq);
13611404
case NEON::BI__builtin_neon_vceqzd_f64:
13621405
case NEON::BI__builtin_neon_vceqzs_f32:
13631406
case NEON::BI__builtin_neon_vceqzh_f16:

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "clang/CIR/MissingFeatures.h"
3737
#include "clang/CIR/TypeEvaluationKind.h"
3838
#include "llvm/ADT/ScopedHashTable.h"
39+
#include "llvm/IR/Instructions.h"
3940

4041
namespace {
4142
class ScalarExprEmitter;

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,7 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
12931293
auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
12941294
auto llvmDstTy =
12951295
mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1296+
12961297
if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
12971298
rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
12981299
llvmSrcVal);

clang/lib/CodeGen/TargetBuiltins/ARM.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,9 @@ Function *CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
17211721
return CGM.getIntrinsic(IntrinsicID, Tys);
17221722
}
17231723

1724+
//===----------------------------------------------------------------------===//
1725+
// Emit-helpers
1726+
//===----------------------------------------------------------------------===//
17241727
static Value *EmitCommonNeonSISDBuiltinExpr(
17251728
CodeGenFunction &CGF, const ARMVectorIntrinsicInfo &SISDInfo,
17261729
SmallVectorImpl<Value *> &Ops, const CallExpr *E) {
@@ -2494,13 +2497,15 @@ CodeGenFunction::EmitAArch64CompareBuiltinExpr(Value *Op, llvm::Type *Ty,
24942497
Op = Builder.CreateBitCast(Op, Ty);
24952498
}
24962499

2500+
Constant *zero = Constant::getNullValue(Op->getType());
2501+
24972502
if (CmpInst::isFPPredicate(Pred)) {
24982503
if (Pred == CmpInst::FCMP_OEQ)
2499-
Op = Builder.CreateFCmp(Pred, Op, Constant::getNullValue(Op->getType()));
2504+
Op = Builder.CreateFCmp(Pred, Op, zero);
25002505
else
2501-
Op = Builder.CreateFCmpS(Pred, Op, Constant::getNullValue(Op->getType()));
2506+
Op = Builder.CreateFCmpS(Pred, Op, zero);
25022507
} else {
2503-
Op = Builder.CreateICmp(Pred, Op, Constant::getNullValue(Op->getType()));
2508+
Op = Builder.CreateICmp(Pred, Op, zero);
25042509
}
25052510

25062511
llvm::Type *ResTy = Ty;

clang/test/CodeGen/AArch64/neon-intrinsics.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17242,17 +17242,6 @@ uint64_t test_vceqd_u64(uint64_t a, uint64_t b) {
1724217242
return (int64_t)vceqd_u64(a, b);
1724317243
}
1724417244

17245-
// CHECK-LABEL: define dso_local i64 @test_vceqzd_s64(
17246-
// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
17247-
// CHECK-NEXT: [[ENTRY:.*:]]
17248-
// CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[A]], 0
17249-
// CHECK-NEXT: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i64
17250-
// CHECK-NEXT: ret i64 [[VCEQZ_I]]
17251-
//
17252-
uint64_t test_vceqzd_s64(int64_t a) {
17253-
return (uint64_t)vceqzd_s64(a);
17254-
}
17255-
1725617245
// CHECK-LABEL: define dso_local i64 @test_vceqzd_u64(
1725717246
// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
1725817247
// CHECK-NEXT: [[ENTRY:.*:]]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// REQUIRES: aarch64-registered-target || arm-registered-target
2+
3+
// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM
4+
// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM %}
5+
// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-cir -o - %s | FileCheck %s --check-prefixes=CIR %}
6+
7+
//=============================================================================
8+
// NOTES
9+
//
10+
// Minor differences between RUNs (e.g. presence of `noundef` attached to
11+
// argumens, `align` attribute attached to pointers), are matched using
12+
// catch-alls like {{.*}}.
13+
//
14+
// Different labels for CIR stem from an additional function call that is
15+
// present at the AST and CIR levels, but is inlined at the LLVM IR level.
16+
//=============================================================================
17+
18+
#include <arm_neon.h>
19+
20+
// LLVM-LABEL: @test_vceqzd_s64
21+
// CIR-LABEL: @vceqzd_s64
22+
uint64_t test_vceqzd_s64(int64_t a) {
23+
// CIR: [[C_0:%.*]] = cir.const #cir.int<0>
24+
// CIR: [[CMP:%.*]] = cir.cmp(eq, %{{.*}}, [[C_0]]) : !s64i, !cir.bool
25+
// CIR: [[RES:%.*]] = cir.cast bool_to_int [[CMP]] : !cir.bool -> !cir.int<s, 1>
26+
// CIR: cir.cast integral [[RES]] : !cir.int<s, 1> -> !u64i
27+
28+
// LLVM-SAME: i64{{.*}} [[A:%.*]])
29+
// LLVM: [[TMP0:%.*]] = icmp eq i64 [[A]], 0
30+
// LLVM-NEXT: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i64
31+
// LLVM-NEXT: ret i64 [[VCEQZ_I]]
32+
return (uint64_t)vceqzd_s64(a);
33+
}

clang/test/lit.cfg.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ def calculate_arch_features(arch_string):
406406
if config.have_llvm_driver:
407407
config.available_features.add("llvm-driver")
408408

409+
if config.clang_enable_cir:
410+
config.available_features.add("cir-enabled")
409411

410412
# Some tests perform deep recursion, which requires a larger pthread stack size
411413
# than the relatively low default of 192 KiB for 64-bit processes on AIX. The

0 commit comments

Comments
 (0)