diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index e5066fac19185..a0af38ceab74c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -315,8 +315,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return getConstantInt(loc, getUInt32Ty(), c); } cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc) { - cir::IntType sInt64Ty = getSInt64Ty(); - return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(sInt64Ty, c)); + return getConstantInt(loc, getSInt64Ty(), c); + } + cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc) { + return getConstantInt(loc, getUInt64Ty(), c); } mlir::Value createNeg(mlir::Value value) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index eec4d10bb49b8..77f19343653db 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -630,6 +630,22 @@ CIRGenFunction::emitTargetBuiltinExpr(unsigned builtinID, const CallExpr *e, getTarget().getTriple().getArch()); } +mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg( + const unsigned iceArguments, const unsigned idx, const Expr *argExpr) { + mlir::Value arg = {}; + if ((iceArguments & (1 << idx)) == 0) { + arg = emitScalarExpr(argExpr); + } else { + // If this is required to be a constant, constant fold it so that we + // know that the generated intrinsic gets a ConstantInt. + const std::optional result = + argExpr->getIntegerConstantExpr(getContext()); + assert(result && "Expected argument to be a constant"); + arg = builder.getConstInt(getLoc(argExpr->getSourceRange()), *result); + } + return arg; +} + /// Given a builtin id for a function like "__builtin_fabsf", return a Function* /// for "fabsf". cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd, diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 2d6cf30fa2ded..ba160373ec77e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -16,7 +16,6 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/CIR/MissingFeatures.h" -#include "llvm/IR/IntrinsicsX86.h" using namespace clang; using namespace clang::CIRGen; @@ -66,9 +65,8 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, getContext().GetBuiltinType(builtinID, error, &iceArguments); assert(error == ASTContext::GE_None && "Error while getting builtin type."); - for (auto [idx, arg] : llvm::enumerate(e->arguments())) { + for (auto [idx, arg] : llvm::enumerate(e->arguments())) ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg)); - } CIRGenBuilderTy &builder = getBuilder(); mlir::Type voidTy = builder.getVoidTy(); @@ -98,6 +96,10 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, case X86::BI__builtin_ia32_undef128: case X86::BI__builtin_ia32_undef256: case X86::BI__builtin_ia32_undef512: + cgm.errorNYI(e->getSourceRange(), + std::string("unimplemented X86 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return {}; case X86::BI__builtin_ia32_vec_ext_v4hi: case X86::BI__builtin_ia32_vec_ext_v16qi: case X86::BI__builtin_ia32_vec_ext_v8hi: @@ -107,7 +109,22 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, case X86::BI__builtin_ia32_vec_ext_v32qi: case X86::BI__builtin_ia32_vec_ext_v16hi: case X86::BI__builtin_ia32_vec_ext_v8si: - case X86::BI__builtin_ia32_vec_ext_v4di: + case X86::BI__builtin_ia32_vec_ext_v4di: { + unsigned numElts = cast(ops[0].getType()).getSize(); + + uint64_t index = + ops[1].getDefiningOp().getIntValue().getZExtValue(); + + index &= numElts - 1; + + cir::ConstantOp indexVal = + builder.getUInt64(index, getLoc(e->getExprLoc())); + + // These builtins exist so we can ensure the index is an ICE and in range. + // Otherwise we could just do this in the header file. + return cir::VecExtractOp::create(builder, getLoc(e->getExprLoc()), ops[0], + indexVal); + } case X86::BI__builtin_ia32_vec_set_v4hi: case X86::BI__builtin_ia32_vec_set_v16qi: case X86::BI__builtin_ia32_vec_set_v8hi: diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 15d96c0a340ff..5d9188777741d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1442,28 +1442,6 @@ mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e, return ScalarExprEmitter(*this, builder).Visit(const_cast(e)); } -mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned iceArguments, - unsigned index, - const Expr *arg) { - mlir::Value result{}; - - // The bit at the specified index indicates whether the argument is required - // to be a constant integer expression. - bool isArgRequiredToBeConstant = (iceArguments & (1 << index)); - - if (!isArgRequiredToBeConstant) { - result = emitScalarExpr(arg); - } else { - // If this is required to be a constant, constant fold it so that we - // know that the generated intrinsic gets a ConstantInt. - std::optional iceOpt = - arg->getIntegerConstantExpr(getContext()); - assert(iceOpt && "Expected argument to be a constant"); - result = builder.getConstInt(getLoc(arg->getSourceRange()), *iceOpt); - } - return result; -} - [[maybe_unused]] static bool mustVisitNullValue(const Expr *e) { // If a null pointer expression's type is the C++0x nullptr_t and // the expression is not a simple literal, it must be evaluated diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index b81706668b431..00f289bcd1bb2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1546,9 +1546,6 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign = false); - mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned index, - const Expr *arg); - mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre); @@ -1721,6 +1718,9 @@ class CIRGenFunction : public CIRGenTypeCache { void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit = false); + mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx, + const Expr *argExpr); + void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage); void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, diff --git a/clang/test/CIR/CodeGen/X86/sse2-builtins.c b/clang/test/CIR/CodeGen/X86/sse2-builtins.c index 144ca143fbf15..9ec8f7a9bf4fe 100644 --- a/clang/test/CIR/CodeGen/X86/sse2-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse2-builtins.c @@ -16,6 +16,21 @@ #include +// Lowering to pextrw requires optimization. +int test_mm_extract_epi16(__m128i A) { + // CIR-LABEL: test_mm_extract_epi16 + // CIR %{{.*}} = cir.vec.extract %{{.*}}[%{{.*}} : {{!u32i|!u64i}}] : !cir.vector + // CIR %{{.*}} = cir.cast integral %{{.*}} : !u16i -> !s32i + + // LLVM-LABEL: test_mm_extract_epi16 + // LLVM: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1 + // LLVM: zext i16 %{{.*}} to i32 + + // OGCG-LABEL: test_mm_extract_epi16 + // OGCG: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1 + // OGCG: zext i16 %{{.*}} to i32 + return _mm_extract_epi16(A, 1); +} void test_mm_clflush(void* A) { // CIR-LABEL: test_mm_clflush