Skip to content

Commit 36c1203

Browse files
Upstream CIR codegen for vec_ext x86 builtins
1 parent 938f521 commit 36c1203

File tree

6 files changed

+96
-4
lines changed

6 files changed

+96
-4
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,12 @@ def CIR_ConstantOp : CIR_Op<"const", [
413413

414414
template <typename T>
415415
T getValueAttr() { return mlir::dyn_cast<T>(getValue()); }
416+
417+
llvm::APInt getIntValue() {
418+
if (const auto intAttr = getValueAttr<cir::IntAttr>())
419+
return intAttr.getValue();
420+
llvm_unreachable("Expected an IntAttr in ConstantOp");
421+
}
416422
}];
417423

418424
let hasFolder = 1;

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
315315
return getConstantInt(loc, getUInt32Ty(), c);
316316
}
317317
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc) {
318-
cir::IntType sInt64Ty = getSInt64Ty();
319-
return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(sInt64Ty, c));
318+
return getConstantInt(loc, getSInt64Ty(), c);
319+
}
320+
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc) {
321+
return getConstantInt(loc, getUInt64Ty(), c);
320322
}
321323

322324
mlir::Value createNeg(mlir::Value value) {

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,22 @@ CIRGenFunction::emitTargetBuiltinExpr(unsigned builtinID, const CallExpr *e,
625625
getTarget().getTriple().getArch());
626626
}
627627

628+
mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(
629+
const unsigned iceArguments, const unsigned idx, const Expr *argExpr) {
630+
mlir::Value arg = {};
631+
if ((iceArguments & (1 << idx)) == 0) {
632+
arg = emitScalarExpr(argExpr);
633+
} else {
634+
// If this is required to be a constant, constant fold it so that we
635+
// know that the generated intrinsic gets a ConstantInt.
636+
const std::optional<llvm::APSInt> result =
637+
argExpr->getIntegerConstantExpr(getContext());
638+
assert(result && "Expected argument to be a constant");
639+
arg = builder.getConstInt(getLoc(argExpr->getSourceRange()), *result);
640+
}
641+
return arg;
642+
}
643+
628644
/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
629645
/// for "fabsf".
630646
cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,

clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "clang/Basic/Builtins.h"
1717
#include "clang/Basic/TargetBuiltins.h"
1818
#include "clang/CIR/MissingFeatures.h"
19-
#include "llvm/IR/IntrinsicsX86.h"
2019

2120
using namespace clang;
2221
using namespace clang::CIRGen;
@@ -43,6 +42,17 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
4342
// Find out if any arguments are required to be integer constant expressions.
4443
assert(!cir::MissingFeatures::handleBuiltinICEArguments());
4544

45+
llvm::SmallVector<mlir::Value> ops;
46+
47+
// Find out if any arguments are required to be integer constant expressions.
48+
unsigned iceArguments = 0;
49+
ASTContext::GetBuiltinTypeError error;
50+
getContext().GetBuiltinType(builtinID, error, &iceArguments);
51+
assert(error == ASTContext::GE_None && "Should not codegen an error");
52+
53+
for (auto [idx, arg] : llvm::enumerate(e->arguments()))
54+
ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
55+
4656
switch (builtinID) {
4757
default:
4858
return {};
@@ -63,6 +73,10 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
6373
case X86::BI__builtin_ia32_undef128:
6474
case X86::BI__builtin_ia32_undef256:
6575
case X86::BI__builtin_ia32_undef512:
76+
cgm.errorNYI(e->getSourceRange(),
77+
std::string("unimplemented X86 builtin call: ") +
78+
getContext().BuiltinInfo.getName(builtinID));
79+
return {};
6680
case X86::BI__builtin_ia32_vec_ext_v4hi:
6781
case X86::BI__builtin_ia32_vec_ext_v16qi:
6882
case X86::BI__builtin_ia32_vec_ext_v8hi:
@@ -72,7 +86,22 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
7286
case X86::BI__builtin_ia32_vec_ext_v32qi:
7387
case X86::BI__builtin_ia32_vec_ext_v16hi:
7488
case X86::BI__builtin_ia32_vec_ext_v8si:
75-
case X86::BI__builtin_ia32_vec_ext_v4di:
89+
case X86::BI__builtin_ia32_vec_ext_v4di: {
90+
unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
91+
92+
uint64_t index =
93+
ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
94+
95+
index &= numElts - 1;
96+
97+
cir::ConstantOp indexVal =
98+
builder.getUInt64(index, getLoc(e->getExprLoc()));
99+
100+
// These builtins exist so we can ensure the index is an ICE and in range.
101+
// Otherwise we could just do this in the header file.
102+
return cir::VecExtractOp::create(builder, getLoc(e->getExprLoc()), ops[0],
103+
indexVal);
104+
}
76105
case X86::BI__builtin_ia32_vec_set_v4hi:
77106
case X86::BI__builtin_ia32_vec_set_v16qi:
78107
case X86::BI__builtin_ia32_vec_set_v8hi:

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,9 @@ class CIRGenFunction : public CIRGenTypeCache {
16991699
void emitScalarInit(const clang::Expr *init, mlir::Location loc,
17001700
LValue lvalue, bool capturedByInit = false);
17011701

1702+
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
1703+
const Expr *argExpr);
1704+
17021705
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
17031706

17041707
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fclangir -emit-cir -o %t.cir -Wall -Werror
2+
// RUN: FileCheck --check-prefixes=CIR --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror
4+
// RUN: FileCheck --check-prefixes=CIR --input-file=%t.cir %s
5+
6+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fclangir -emit-llvm -o %t.ll -Wall -Werror
7+
// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
8+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror
9+
// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
10+
11+
// RUN: FileCheck --check-prefixes=OGCG --input-file=%t.ll %s
12+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fno-signed-char -emit-llvm -o %t.ll -Wall -Werror
13+
// RUN: FileCheck --check-prefixes=OGCG --input-file=%t.ll %s
14+
15+
// This test mimics clang/test/CodeGen/X86/sse2-builtins.c, which eventually
16+
// CIR shall be able to support fully.
17+
18+
#include <immintrin.h>
19+
20+
// Lowering to pextrw requires optimization.
21+
int test_mm_extract_epi16(__m128i A) {
22+
23+
// CIR-LABEL: test_mm_extract_epi16
24+
// CIR %{{.*}} = cir.vec.extract %{{.*}}[%{{.*}} : {{!u32i|!u64i}}] : !cir.vector<!s16i x 8>
25+
// CIR %{{.*}} = cir.cast integral %{{.*}} : !u16i -> !s32i
26+
27+
// LLVM-LABEL: test_mm_extract_epi16
28+
// LLVM: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
29+
// LLVM: zext i16 %{{.*}} to i32
30+
31+
// OGCG-LABEL: test_mm_extract_epi16
32+
// OGCG: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
33+
// OGCG: zext i16 %{{.*}} to i32
34+
35+
return _mm_extract_epi16(A, 1);
36+
}

0 commit comments

Comments
 (0)