From 539eebe34fb2184e20525078df8f6413b66625ce Mon Sep 17 00:00:00 2001 From: hhuebner Date: Mon, 10 Nov 2025 23:04:51 +0100 Subject: [PATCH 1/9] [CIR] Upstream X86 builtin _mm_prefetch and _mm_clflush --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 45 ++++++++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 60 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 22 +++++++ clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 ++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 14 +++++ clang/test/CIR/CodeGen/X86/sse-builtins.c | 23 +++++++ clang/test/CIR/CodeGen/X86/sse2-builtins.c | 23 +++++++ 7 files changed, 191 insertions(+) create mode 100644 clang/test/CIR/CodeGen/X86/sse-builtins.c create mode 100644 clang/test/CIR/CodeGen/X86/sse2-builtins.c diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 16258513239d9..902b1fa64fb5b 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -413,6 +413,18 @@ def CIR_ConstantOp : CIR_Op<"const", [ template T getValueAttr() { return mlir::dyn_cast(getValue()); } + + llvm::APInt getIntValue() { + if (const auto intAttr = getValueAttr()) + return intAttr.getValue(); + llvm_unreachable("Expected an IntAttr in ConstantOp"); + } + + bool getBoolValue() { + if (const auto boolAttr = getValueAttr()) + return boolAttr.getValue(); + llvm_unreachable("Expected a BoolAttr in ConstantOp"); + } }]; let hasFolder = 1; @@ -2579,6 +2591,39 @@ def CIR_FuncOp : CIR_Op<"func", [ }]; } +//===----------------------------------------------------------------------===// +// LLVMIntrinsicCallOp +//===----------------------------------------------------------------------===// + +def CIR_LLVMIntrinsicCallOp : CIR_Op<"llvm.intrinsic"> { + let summary = "Call to llvm intrinsic functions that is not defined in CIR"; + let description = [{ + `cir.llvm.intrinsic` operation represents a call-like expression which has + return type and arguments that maps directly to a llvm intrinsic. + It only records intrinsic `intrinsic_name`. + }]; + + let results = (outs Optional:$result); + let arguments = (ins + StrAttr:$intrinsic_name, Variadic:$arg_ops); + + let skipDefaultBuilders = 1; + + let assemblyFormat = [{ + $intrinsic_name $arg_ops `:` functional-type($arg_ops, $result) attr-dict + }]; + + let builders = [ + OpBuilder<(ins "mlir::StringAttr":$intrinsic_name, "mlir::Type":$resType, + CArg<"mlir::ValueRange", "{}">:$operands), [{ + $_state.addAttribute("intrinsic_name", intrinsic_name); + $_state.addOperands(operands); + if (resType) + $_state.addTypes(resType); + }]>, + ]; +} + //===----------------------------------------------------------------------===// // CallOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 0198a9d4eb192..2f02dd0319cd0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -21,6 +21,49 @@ using namespace clang; using namespace clang::CIRGen; +/// Get integer from a mlir::Value that is an int constant or a constant op. +static int64_t getIntValueFromConstOp(mlir::Value val) { + return val.getDefiningOp().getIntValue().getSExtValue(); +} + +static mlir::Value emitClFlush(CIRGenFunction& cgf, + const CallExpr* e, + mlir::Value& op) { + mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); + mlir::Location location = cgf.getLoc(e->getExprLoc()); + return cgf.getBuilder() + .create( + location, cgf.getBuilder().getStringAttr("x86.sse2.clflush"), + voidTy, op) + .getResult(); +} + +static mlir::Value emitPrefetch(CIRGenFunction& cgf, + const CallExpr* e, + mlir::Value& addr, + int64_t hint) { + CIRGenBuilderTy& builder = cgf.getBuilder(); + mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); + mlir::Type sInt32Ty = cir::IntType::get(&cgf.getMLIRContext(), 32, true); + mlir::Value address = builder.createPtrBitcast(addr, voidTy); + mlir::Location location = cgf.getLoc(e->getExprLoc()); + mlir::Value rw = + cir::ConstantOp::create(builder, location, + cir::IntAttr::get(sInt32Ty, (hint >> 2) & 0x1)); + mlir::Value locality = + cir::ConstantOp::create(builder, location, + cir::IntAttr::get(sInt32Ty, hint & 0x3)); + mlir::Value data = cir::ConstantOp::create(builder, location, + cir::IntAttr::get(sInt32Ty, 1)); + + return cir::LLVMIntrinsicCallOp::create( + builder, location, + builder.getStringAttr("prefetch"), voidTy, + mlir::ValueRange{address, rw, locality, data}) + .getResult(); +} + + mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *e) { if (builtinID == Builtin::BI__builtin_cpu_is) { @@ -43,11 +86,28 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, // Find out if any arguments are required to be integer constant expressions. assert(!cir::MissingFeatures::handleBuiltinICEArguments()); + // The operands of the builtin call + llvm::SmallVector ops; + + // `ICEArguments` is a bitmap indicating whether the argument at the i-th bit + // is required to be a constant integer expression. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError error; + getContext().GetBuiltinType(builtinID, error, &ICEArguments); + assert(error == ASTContext::GE_None && "Error while getting builtin type."); + + const unsigned numArgs = e->getNumArgs(); + for (unsigned i = 0; i != numArgs; i++) { + ops.push_back(emitScalarOrConstFoldImmArg(ICEArguments, i, e)); + } + switch (builtinID) { default: return {}; case X86::BI_mm_prefetch: + return emitPrefetch(*this, e, ops[0], getIntValueFromConstOp(ops[1])); case X86::BI_mm_clflush: + return emitClFlush(*this, e, ops[0]); case X86::BI_mm_lfence: case X86::BI_mm_pause: case X86::BI_mm_mfence: diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 5eba5ba6c3df1..236f487afd9ba 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1430,6 +1430,28 @@ mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e, return ScalarExprEmitter(*this, builder).Visit(const_cast(e)); } +mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned ICEArguments, + unsigned index, + const CallExpr *e) { + mlir::Value arg{}; + + // 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) { + arg = emitScalarExpr(e->getArg(index)); + } 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 result = + e->getArg(index)->getIntegerConstantExpr(getContext()); + assert(result && "Expected argument to be a constant"); + arg = builder.getConstInt(getLoc(e->getSourceRange()), *result); + } + return arg; +} + [[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 f879e580989f7..0ce8714b23e82 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1529,6 +1529,10 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign = false); + mlir::Value emitScalarOrConstFoldImmArg(unsigned ICEArguments, + unsigned index, + const CallExpr *e); + mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b4afed7019417..f4379b402fe13 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -320,6 +320,20 @@ static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp( return callIntrinOp; } +mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite( + cir::LLVMIntrinsicCallOp op, + OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type llvmResTy = + getTypeConverter()->convertType(op->getResultTypes()[0]); + if (!llvmResTy) + return op.emitError("expected LLVM result type"); + StringRef name = op.getIntrinsicName(); + replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm." + name, llvmResTy, + adaptor.getOperands()); + return mlir::success(); +} + /// IntAttr visitor. mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) { mlir::Location loc = parentOp->getLoc(); diff --git a/clang/test/CIR/CodeGen/X86/sse-builtins.c b/clang/test/CIR/CodeGen/X86/sse-builtins.c new file mode 100644 index 0000000000000..4dd141168ba66 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-cir -o %t.cir -Wall -Werror +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// This test mimics clang/test/CodeGen/X86/sse-builtins.c, which eventually +// CIR shall be able to support fully. + +#include + + +void test_mm_prefetch(char const* p) { + // CIR-LABEL: test_mm_prefetch + // LLVM-LABEL: test_mm_prefetch + _mm_prefetch(p, 0); + // CIR: cir.prefetch read locality(0) %{{.*}} : !cir.ptr + // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1) +} diff --git a/clang/test/CIR/CodeGen/X86/sse2-builtins.c b/clang/test/CIR/CodeGen/X86/sse2-builtins.c new file mode 100644 index 0000000000000..0c275fa089262 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/sse2-builtins.c @@ -0,0 +1,23 @@ +// 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 +// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s +// 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 +// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s + +// 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 +// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s +// 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 +// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s + +// This test mimics clang/test/CodeGen/X86/sse2-builtins.c, which eventually +// CIR shall be able to support fully. + +#include + + +void test_mm_clflush(void* A) { + // CIR-LABEL: test_mm_clflush + // LLVM-LABEL: teh + _mm_clflush(A); + // CIR-CHECK: {{%.*}} = cir.llvm.intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void + // LLVM-CHECK: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) +} From de4743272c246c35ddcc3123a2ecfdd5a5d4a938 Mon Sep 17 00:00:00 2001 From: hhuebner Date: Mon, 10 Nov 2025 23:18:23 +0100 Subject: [PATCH 2/9] fix warning --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 2f02dd0319cd0..0c168d86ccde5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -31,11 +31,10 @@ static mlir::Value emitClFlush(CIRGenFunction& cgf, mlir::Value& op) { mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); mlir::Location location = cgf.getLoc(e->getExprLoc()); - return cgf.getBuilder() - .create( - location, cgf.getBuilder().getStringAttr("x86.sse2.clflush"), - voidTy, op) - .getResult(); + return cir::LLVMIntrinsicCallOp::create( + cgf.getBuilder(), location, + cgf.getBuilder().getStringAttr("x86.sse2.clflush"), voidTy, op) + .getResult(); } static mlir::Value emitPrefetch(CIRGenFunction& cgf, From 26d8914b8c9ee4e01ea8fa55464e8ab0cb17225f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20H=C3=BCbner?= <117831077+HendrikHuebner@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:56:49 +0100 Subject: [PATCH 3/9] Update clang/include/clang/CIR/Dialect/IR/CIROps.td Co-authored-by: Andy Kaylor --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 902b1fa64fb5b..d40466610fc13 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2595,7 +2595,7 @@ def CIR_FuncOp : CIR_Op<"func", [ // LLVMIntrinsicCallOp //===----------------------------------------------------------------------===// -def CIR_LLVMIntrinsicCallOp : CIR_Op<"llvm.intrinsic"> { +def CIR_LLVMIntrinsicCallOp : CIR_Op<"call_llvm_intrinsic"> { let summary = "Call to llvm intrinsic functions that is not defined in CIR"; let description = [{ `cir.llvm.intrinsic` operation represents a call-like expression which has From 93c0ded976ab0c45df326bec9c3c3aa517e4133e Mon Sep 17 00:00:00 2001 From: hhuebner Date: Tue, 11 Nov 2025 12:50:22 +0100 Subject: [PATCH 4/9] feedback --- clang/include/clang/CIR/MissingFeatures.h | 1 + clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 49 +++++++------------ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 14 +++++- clang/test/CIR/CodeGen/X86/sse2-builtins.c | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index af1ffffcf54c0..460bd69f69c35 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -271,6 +271,7 @@ struct MissingFeatures { static bool insertBuiltinUnpredictable() { return false; } static bool instrumentation() { return false; } static bool intrinsics() { return false; } + static bool intrinsicElementTypeSupport() {return false; } static bool isMemcpyEquivalentSpecialMember() { return false; } static bool isTrivialCtorOrDtor() { return false; } static bool lambdaCaptures() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 0c168d86ccde5..546fef7ccb1a0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -26,43 +26,32 @@ static int64_t getIntValueFromConstOp(mlir::Value val) { return val.getDefiningOp().getIntValue().getSExtValue(); } -static mlir::Value emitClFlush(CIRGenFunction& cgf, - const CallExpr* e, - mlir::Value& op) { - mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); - mlir::Location location = cgf.getLoc(e->getExprLoc()); - return cir::LLVMIntrinsicCallOp::create( - cgf.getBuilder(), location, - cgf.getBuilder().getStringAttr("x86.sse2.clflush"), voidTy, op) +static mlir::Value emitClFlush(CIRGenFunction &cgf, const CallExpr *e, + mlir::Value &op) { + mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); + mlir::Location location = cgf.getLoc(e->getExprLoc()); + return cir::LLVMIntrinsicCallOp::create( + cgf.getBuilder(), location, + cgf.getBuilder().getStringAttr("x86.sse2.clflush"), voidTy, op) .getResult(); } -static mlir::Value emitPrefetch(CIRGenFunction& cgf, - const CallExpr* e, - mlir::Value& addr, - int64_t hint) { - CIRGenBuilderTy& builder = cgf.getBuilder(); - mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); - mlir::Type sInt32Ty = cir::IntType::get(&cgf.getMLIRContext(), 32, true); - mlir::Value address = builder.createPtrBitcast(addr, voidTy); +static mlir::Value emitPrefetch(CIRGenFunction &cgf, const CallExpr *e, + mlir::Value &addr, int64_t hint) { + CIRGenBuilderTy &builder = cgf.getBuilder(); mlir::Location location = cgf.getLoc(e->getExprLoc()); - mlir::Value rw = - cir::ConstantOp::create(builder, location, - cir::IntAttr::get(sInt32Ty, (hint >> 2) & 0x1)); - mlir::Value locality = - cir::ConstantOp::create(builder, location, - cir::IntAttr::get(sInt32Ty, hint & 0x3)); - mlir::Value data = cir::ConstantOp::create(builder, location, - cir::IntAttr::get(sInt32Ty, 1)); + mlir::Type voidTy = builder.getVoidTy(); + mlir::Value address = builder.createPtrBitcast(addr, voidTy); + mlir::Value rw = builder.getSignedInt(location, (hint >> 2) & 0x1, 32); + mlir::Value locality = builder.getSignedInt(location, hint & 0x3, 32); + mlir::Value data = builder.getSignedInt(location, 1, 32); return cir::LLVMIntrinsicCallOp::create( - builder, location, - builder.getStringAttr("prefetch"), voidTy, + builder, location, builder.getStringAttr("prefetch"), voidTy, mlir::ValueRange{address, rw, locality, data}) .getResult(); } - mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *e) { if (builtinID == Builtin::BI__builtin_cpu_is) { @@ -90,14 +79,14 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, // `ICEArguments` is a bitmap indicating whether the argument at the i-th bit // is required to be a constant integer expression. - unsigned ICEArguments = 0; + unsigned iceArguments = 0; ASTContext::GetBuiltinTypeError error; - getContext().GetBuiltinType(builtinID, error, &ICEArguments); + getContext().GetBuiltinType(builtinID, error, &iceArguments); assert(error == ASTContext::GE_None && "Error while getting builtin type."); const unsigned numArgs = e->getNumArgs(); for (unsigned i = 0; i != numArgs; i++) { - ops.push_back(emitScalarOrConstFoldImmArg(ICEArguments, i, e)); + ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, i, e)); } switch (builtinID) { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index f4379b402fe13..db00dff582401 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -321,14 +321,24 @@ static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp( } mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite( - cir::LLVMIntrinsicCallOp op, - OpAdaptor adaptor, + cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::Type llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]); if (!llvmResTy) return op.emitError("expected LLVM result type"); StringRef name = op.getIntrinsicName(); + + // Some LLVM intrinsics require ElementType attribute to be attached to + // the argument of pointer type. That prevents us from generating LLVM IR + // because from LLVM dialect, we have LLVM IR like the below which fails + // LLVM IR verification. + // %3 = call i64 @llvm.aarch64.ldxr.p0(ptr %2) + // The expected LLVM IR should be like + // %3 = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i32) %2) + // TODO(cir): MLIR LLVM dialect should handle this part as CIR has no way + // to set LLVM IR attribute. + assert(!cir::MissingFeatures::intrinsicElementTypeSupport()); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm." + name, llvmResTy, adaptor.getOperands()); return mlir::success(); diff --git a/clang/test/CIR/CodeGen/X86/sse2-builtins.c b/clang/test/CIR/CodeGen/X86/sse2-builtins.c index 0c275fa089262..c74597e1735b6 100644 --- a/clang/test/CIR/CodeGen/X86/sse2-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse2-builtins.c @@ -18,6 +18,6 @@ void test_mm_clflush(void* A) { // CIR-LABEL: test_mm_clflush // LLVM-LABEL: teh _mm_clflush(A); - // CIR-CHECK: {{%.*}} = cir.llvm.intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void + // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void // LLVM-CHECK: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) } From 9eb51990ae153968e7856dad51c1fb39242f84a6 Mon Sep 17 00:00:00 2001 From: hhuebner Date: Tue, 11 Nov 2025 12:54:05 +0100 Subject: [PATCH 5/9] formatting --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 4 ++-- clang/lib/CIR/CodeGen/CIRGenFunction.h | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index d40466610fc13..2124b1dc62a81 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2598,7 +2598,7 @@ def CIR_FuncOp : CIR_Op<"func", [ def CIR_LLVMIntrinsicCallOp : CIR_Op<"call_llvm_intrinsic"> { let summary = "Call to llvm intrinsic functions that is not defined in CIR"; let description = [{ - `cir.llvm.intrinsic` operation represents a call-like expression which has + `cir.call_llvm_intrinsic` operation represents a call-like expression which has return type and arguments that maps directly to a llvm intrinsic. It only records intrinsic `intrinsic_name`. }]; diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 236f487afd9ba..bb64b2ba710f1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1430,14 +1430,14 @@ mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e, return ScalarExprEmitter(*this, builder).Visit(const_cast(e)); } -mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned ICEArguments, +mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned index, const CallExpr *e) { mlir::Value arg{}; // The bit at the specified index indicates whether the argument is required // to be a constant integer expression. - bool isArgRequiredToBeConstant = (ICEArguments & (1 << index)); + bool isArgRequiredToBeConstant = (iceArguments & (1 << index)); if (!isArgRequiredToBeConstant) { arg = emitScalarExpr(e->getArg(index)); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 0ce8714b23e82..885b6d69bd806 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1529,8 +1529,7 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign = false); - mlir::Value emitScalarOrConstFoldImmArg(unsigned ICEArguments, - unsigned index, + mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned index, const CallExpr *e); mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, From 776f5c1d3b6ef7dceec51b60be5ac08f16651e73 Mon Sep 17 00:00:00 2001 From: hhuebner Date: Tue, 11 Nov 2025 16:28:09 +0100 Subject: [PATCH 6/9] formatting + refactor --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 30 ++++++++++++++-------- clang/test/CIR/CodeGen/X86/sse-builtins.c | 8 ++++++ clang/test/CIR/CodeGen/X86/sse2-builtins.c | 24 +++++++++++++++++ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 546fef7ccb1a0..e204f1fd1de84 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -26,13 +26,16 @@ static int64_t getIntValueFromConstOp(mlir::Value val) { return val.getDefiningOp().getIntValue().getSExtValue(); } -static mlir::Value emitClFlush(CIRGenFunction &cgf, const CallExpr *e, - mlir::Value &op) { - mlir::Type voidTy = cir::VoidType::get(&cgf.getMLIRContext()); +template +static mlir::Value emitIntrinsicCallOp(CIRGenFunction &cgf, const CallExpr *e, + const std::string &str, + const mlir::Type &resTy, + Operands &&...op) { + CIRGenBuilderTy &builder = cgf.getBuilder(); mlir::Location location = cgf.getLoc(e->getExprLoc()); - return cir::LLVMIntrinsicCallOp::create( - cgf.getBuilder(), location, - cgf.getBuilder().getStringAttr("x86.sse2.clflush"), voidTy, op) + return cir::LLVMIntrinsicCallOp::create(builder, location, + builder.getStringAttr(str), resTy, + std::forward(op)...) .getResult(); } @@ -46,10 +49,8 @@ static mlir::Value emitPrefetch(CIRGenFunction &cgf, const CallExpr *e, mlir::Value locality = builder.getSignedInt(location, hint & 0x3, 32); mlir::Value data = builder.getSignedInt(location, 1, 32); - return cir::LLVMIntrinsicCallOp::create( - builder, location, builder.getStringAttr("prefetch"), voidTy, - mlir::ValueRange{address, rw, locality, data}) - .getResult(); + return emitIntrinsicCallOp(cgf, e, "prefetch", voidTy, + mlir::ValueRange{address, rw, locality, data}); } mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, @@ -89,17 +90,24 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, i, e)); } + CIRGenBuilderTy &builder = getBuilder(); + mlir::Type voidTy = builder.getVoidTy(); + switch (builtinID) { default: return {}; case X86::BI_mm_prefetch: return emitPrefetch(*this, e, ops[0], getIntValueFromConstOp(ops[1])); case X86::BI_mm_clflush: - return emitClFlush(*this, e, ops[0]); + return emitIntrinsicCallOp(*this, e, "x86.sse2.clflush", voidTy, ops[0]); case X86::BI_mm_lfence: + return emitIntrinsicCallOp(*this, e, "x86.sse2.lfence", voidTy); case X86::BI_mm_pause: + return emitIntrinsicCallOp(*this, e, "x86.sse2.pause", voidTy); case X86::BI_mm_mfence: + return emitIntrinsicCallOp(*this, e, "x86.sse2.mfence", voidTy); case X86::BI_mm_sfence: + return emitIntrinsicCallOp(*this, e, "x86.sse.sfence", voidTy); case X86::BI__rdtsc: case X86::BI__builtin_ia32_rdtscp: case X86::BI__builtin_ia32_lzcnt_u16: diff --git a/clang/test/CIR/CodeGen/X86/sse-builtins.c b/clang/test/CIR/CodeGen/X86/sse-builtins.c index 4dd141168ba66..8a5095f907b57 100644 --- a/clang/test/CIR/CodeGen/X86/sse-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c @@ -21,3 +21,11 @@ void test_mm_prefetch(char const* p) { // CIR: cir.prefetch read locality(0) %{{.*}} : !cir.ptr // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1) } + +void test_mm_sfence(void) { + // CIR-LABEL: test_mm_sfence + // LLVM-LABEL: test_mm_sfence + _mm_sfence(); + // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse.sfence" : () -> !void + // LLVM: call void @llvm.x86.sse.sfence() +} diff --git a/clang/test/CIR/CodeGen/X86/sse2-builtins.c b/clang/test/CIR/CodeGen/X86/sse2-builtins.c index c74597e1735b6..392cf948965bf 100644 --- a/clang/test/CIR/CodeGen/X86/sse2-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse2-builtins.c @@ -21,3 +21,27 @@ void test_mm_clflush(void* A) { // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void // LLVM-CHECK: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) } + +void test_mm_lfence(void) { + // CIR-CHECK-LABEL: test_mm_lfence + // LLVM-CHECK-LABEL: test_mm_lfence + _mm_lfence(); + // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.lfence" : () -> !void + // LLVM-CHECK: call void @llvm.x86.sse2.lfence() +} + +void test_mm_mfence(void) { + // CIR-CHECK-LABEL: test_mm_mfence + // LLVM-CHECK-LABEL: test_mm_mfence + _mm_mfence(); + // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.mfence" : () -> !void + // LLVM-CHECK: call void @llvm.x86.sse2.mfence() +} + +void test_mm_pause(void) { + // CIR-LABEL: test_mm_pause + // LLVM-LABEL: test_mm_pause + _mm_pause(); + // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.pause" : () -> !void + // LLVM: call void @llvm.x86.sse2.pause() +} From 8a07992b75209cbbff7704cf74df5c67447a1362 Mon Sep 17 00:00:00 2001 From: hhuebner Date: Wed, 12 Nov 2025 21:46:13 +0100 Subject: [PATCH 7/9] Remove prefetch builtin and address feedback --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 28 ++++------------------ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 16 ++++++------- clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 +- clang/test/CIR/CodeGen/X86/sse-builtins.c | 8 ------- 4 files changed, 13 insertions(+), 41 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index e204f1fd1de84..3baf4a75387b7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -21,10 +21,6 @@ using namespace clang; using namespace clang::CIRGen; -/// Get integer from a mlir::Value that is an int constant or a constant op. -static int64_t getIntValueFromConstOp(mlir::Value val) { - return val.getDefiningOp().getIntValue().getSExtValue(); -} template static mlir::Value emitIntrinsicCallOp(CIRGenFunction &cgf, const CallExpr *e, @@ -39,20 +35,6 @@ static mlir::Value emitIntrinsicCallOp(CIRGenFunction &cgf, const CallExpr *e, .getResult(); } -static mlir::Value emitPrefetch(CIRGenFunction &cgf, const CallExpr *e, - mlir::Value &addr, int64_t hint) { - CIRGenBuilderTy &builder = cgf.getBuilder(); - mlir::Location location = cgf.getLoc(e->getExprLoc()); - mlir::Type voidTy = builder.getVoidTy(); - mlir::Value address = builder.createPtrBitcast(addr, voidTy); - mlir::Value rw = builder.getSignedInt(location, (hint >> 2) & 0x1, 32); - mlir::Value locality = builder.getSignedInt(location, hint & 0x3, 32); - mlir::Value data = builder.getSignedInt(location, 1, 32); - - return emitIntrinsicCallOp(cgf, e, "prefetch", voidTy, - mlir::ValueRange{address, rw, locality, data}); -} - mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *e) { if (builtinID == Builtin::BI__builtin_cpu_is) { @@ -76,7 +58,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, assert(!cir::MissingFeatures::handleBuiltinICEArguments()); // The operands of the builtin call - llvm::SmallVector ops; + llvm::SmallVector ops; // `ICEArguments` is a bitmap indicating whether the argument at the i-th bit // is required to be a constant integer expression. @@ -85,9 +67,8 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, getContext().GetBuiltinType(builtinID, error, &iceArguments); assert(error == ASTContext::GE_None && "Error while getting builtin type."); - const unsigned numArgs = e->getNumArgs(); - for (unsigned i = 0; i != numArgs; i++) { - ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, i, e)); + for (auto [idx, arg] : llvm::enumerate(e->arguments())) { + ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg)); } CIRGenBuilderTy &builder = getBuilder(); @@ -96,8 +77,6 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, switch (builtinID) { default: return {}; - case X86::BI_mm_prefetch: - return emitPrefetch(*this, e, ops[0], getIntValueFromConstOp(ops[1])); case X86::BI_mm_clflush: return emitIntrinsicCallOp(*this, e, "x86.sse2.clflush", voidTy, ops[0]); case X86::BI_mm_lfence: @@ -108,6 +87,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, return emitIntrinsicCallOp(*this, e, "x86.sse2.mfence", voidTy); case X86::BI_mm_sfence: return emitIntrinsicCallOp(*this, e, "x86.sse.sfence", voidTy); + case X86::BI_mm_prefetch: case X86::BI__rdtsc: case X86::BI__builtin_ia32_rdtscp: case X86::BI__builtin_ia32_lzcnt_u16: diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index bb64b2ba710f1..93aacba15f0b4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1432,24 +1432,24 @@ mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e, mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned index, - const CallExpr *e) { - mlir::Value arg{}; + 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) { - arg = emitScalarExpr(e->getArg(index)); + 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 result = - e->getArg(index)->getIntegerConstantExpr(getContext()); - assert(result && "Expected argument to be a constant"); - arg = builder.getConstInt(getLoc(e->getSourceRange()), *result); + std::optional iceOpt = + arg->getIntegerConstantExpr(getContext()); + assert(iceOpt && "Expected argument to be a constant"); + result = builder.getConstInt(getLoc(arg->getSourceRange()), *iceOpt); } - return arg; + return result; } [[maybe_unused]] static bool mustVisitNullValue(const Expr *e) { diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 885b6d69bd806..5c8f7bb5c2cb6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1530,7 +1530,7 @@ class CIRGenFunction : public CIRGenTypeCache { bool ignoreResultAssign = false); mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned index, - const CallExpr *e); + const Expr *e); mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre); diff --git a/clang/test/CIR/CodeGen/X86/sse-builtins.c b/clang/test/CIR/CodeGen/X86/sse-builtins.c index 8a5095f907b57..e16e9e11ff506 100644 --- a/clang/test/CIR/CodeGen/X86/sse-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c @@ -14,14 +14,6 @@ #include -void test_mm_prefetch(char const* p) { - // CIR-LABEL: test_mm_prefetch - // LLVM-LABEL: test_mm_prefetch - _mm_prefetch(p, 0); - // CIR: cir.prefetch read locality(0) %{{.*}} : !cir.ptr - // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1) -} - void test_mm_sfence(void) { // CIR-LABEL: test_mm_sfence // LLVM-LABEL: test_mm_sfence From e481360a6c6978da30dc38dd4f894842363f8d95 Mon Sep 17 00:00:00 2001 From: hhuebner Date: Wed, 12 Nov 2025 21:57:50 +0100 Subject: [PATCH 8/9] formatting --- clang/include/clang/CIR/MissingFeatures.h | 2 +- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 1 - clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 460bd69f69c35..9cb069bfec626 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -270,8 +270,8 @@ struct MissingFeatures { static bool innermostEHScope() { return false; } static bool insertBuiltinUnpredictable() { return false; } static bool instrumentation() { return false; } + static bool intrinsicElementTypeSupport() { return false; } static bool intrinsics() { return false; } - static bool intrinsicElementTypeSupport() {return false; } static bool isMemcpyEquivalentSpecialMember() { return false; } static bool isTrivialCtorOrDtor() { return false; } static bool lambdaCaptures() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 3baf4a75387b7..02390cabcee35 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -21,7 +21,6 @@ using namespace clang; using namespace clang::CIRGen; - template static mlir::Value emitIntrinsicCallOp(CIRGenFunction &cgf, const CallExpr *e, const std::string &str, diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index db00dff582401..d88a4ad76f27b 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -328,7 +328,7 @@ mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite( if (!llvmResTy) return op.emitError("expected LLVM result type"); StringRef name = op.getIntrinsicName(); - + // Some LLVM intrinsics require ElementType attribute to be attached to // the argument of pointer type. That prevents us from generating LLVM IR // because from LLVM dialect, we have LLVM IR like the below which fails From a665f70daf9a3c3e70c2f7719b92052aa6d56149 Mon Sep 17 00:00:00 2001 From: hhuebner Date: Thu, 13 Nov 2025 09:57:37 +0100 Subject: [PATCH 9/9] Improve tests --- clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 +- clang/test/CIR/CodeGen/X86/sse-builtins.c | 5 +++ clang/test/CIR/CodeGen/X86/sse2-builtins.c | 41 ++++++++++++++-------- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 5c8f7bb5c2cb6..f413bf88c4e8e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1530,7 +1530,7 @@ class CIRGenFunction : public CIRGenTypeCache { bool ignoreResultAssign = false); mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned index, - const Expr *e); + const Expr *arg); mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre); diff --git a/clang/test/CIR/CodeGen/X86/sse-builtins.c b/clang/test/CIR/CodeGen/X86/sse-builtins.c index e16e9e11ff506..3a61018741958 100644 --- a/clang/test/CIR/CodeGen/X86/sse-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c @@ -8,6 +8,9 @@ // RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror // RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG + // This test mimics clang/test/CodeGen/X86/sse-builtins.c, which eventually // CIR shall be able to support fully. @@ -17,7 +20,9 @@ void test_mm_sfence(void) { // CIR-LABEL: test_mm_sfence // LLVM-LABEL: test_mm_sfence + // OGCG-LABEL: test_mm_sfence _mm_sfence(); // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse.sfence" : () -> !void // LLVM: call void @llvm.x86.sse.sfence() + // OGCG: call void @llvm.x86.sse.sfence() } diff --git a/clang/test/CIR/CodeGen/X86/sse2-builtins.c b/clang/test/CIR/CodeGen/X86/sse2-builtins.c index 392cf948965bf..144ca143fbf15 100644 --- a/clang/test/CIR/CodeGen/X86/sse2-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse2-builtins.c @@ -1,12 +1,15 @@ // 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 -// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s +// RUN: FileCheck --check-prefixes=CIR --input-file=%t.cir %s // 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 -// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s +// RUN: FileCheck --check-prefixes=CIR --input-file=%t.cir %s // 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 -// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s // 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 -// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG // This test mimics clang/test/CodeGen/X86/sse2-builtins.c, which eventually // CIR shall be able to support fully. @@ -16,32 +19,40 @@ void test_mm_clflush(void* A) { // CIR-LABEL: test_mm_clflush - // LLVM-LABEL: teh + // LLVM-LABEL: test_mm_clflush + // OGCG-LABEL: test_mm_clflush _mm_clflush(A); - // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void - // LLVM-CHECK: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) + // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void + // LLVM: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) + // OGCG: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) } void test_mm_lfence(void) { - // CIR-CHECK-LABEL: test_mm_lfence - // LLVM-CHECK-LABEL: test_mm_lfence + // CIR-LABEL: test_mm_lfence + // LLVM-LABEL: test_mm_lfence + // OGCG-LABEL: test_mm_lfence _mm_lfence(); - // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.lfence" : () -> !void - // LLVM-CHECK: call void @llvm.x86.sse2.lfence() + // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.lfence" : () -> !void + // LLVM: call void @llvm.x86.sse2.lfence() + // OGCG: call void @llvm.x86.sse2.lfence() } void test_mm_mfence(void) { - // CIR-CHECK-LABEL: test_mm_mfence - // LLVM-CHECK-LABEL: test_mm_mfence + // CIR-LABEL: test_mm_mfence + // LLVM-LABEL: test_mm_mfence + // OGCG-LABEL: test_mm_mfence _mm_mfence(); - // CIR-CHECK: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.mfence" : () -> !void - // LLVM-CHECK: call void @llvm.x86.sse2.mfence() + // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.mfence" : () -> !void + // LLVM: call void @llvm.x86.sse2.mfence() + // OGCG: call void @llvm.x86.sse2.mfence() } void test_mm_pause(void) { // CIR-LABEL: test_mm_pause // LLVM-LABEL: test_mm_pause + // OGCG-LABEL: test_mm_pause _mm_pause(); // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.sse2.pause" : () -> !void // LLVM: call void @llvm.x86.sse2.pause() + // OGCG: call void @llvm.x86.sse2.pause() }