-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Upstream CIR codegen for mxcsr x86 builtins #167948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@llvm/pr-subscribers-clangir Author: Thibault Monnier (Thibault-Monnier) Changes... It is part of #167752. Full diff: https://github.com/llvm/llvm-project/pull/167948.diff 6 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 16258513239d9..0d639cb7b0b53 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2579,6 +2579,40 @@ def CIR_FuncOp : CIR_Op<"func", [
}];
}
+//===----------------------------------------------------------------------===//
+// LLVMIntrinsicCallOp
+//===----------------------------------------------------------------------===//
+
+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
+ return type and arguments that maps directly to a llvm intrinsic.
+ It only records intrinsic `intrinsic_name`.
+ }];
+
+ let results = (outs Optional<CIR_AnyType>:$result);
+ let arguments = (ins
+ StrAttr:$intrinsic_name, Variadic<CIR_AnyType>:$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/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 4e6a5ee7ee210..b54256715be96 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -625,6 +625,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<llvm::APSInt> 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 0198a9d4eb192..9c5ae38d8e0fa 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;
@@ -43,6 +42,18 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
// Find out if any arguments are required to be integer constant expressions.
assert(!cir::MissingFeatures::handleBuiltinICEArguments());
+ llvm::SmallVector<mlir::Value> ops;
+
+ // Find out if any arguments are required to be integer constant expressions.
+ unsigned iceArguments = 0;
+ ASTContext::GetBuiltinTypeError error;
+ getContext().GetBuiltinType(builtinID, error, &iceArguments);
+ assert(error == ASTContext::GE_None && "Should not codegen an error");
+
+ for (auto [idx, arg] : llvm::enumerate(e->arguments())) {
+ ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
+ }
+
switch (builtinID) {
default:
return {};
@@ -82,10 +93,30 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
case X86::BI__builtin_ia32_vec_set_v16hi:
case X86::BI__builtin_ia32_vec_set_v8si:
case X86::BI__builtin_ia32_vec_set_v4di:
+ cgm.errorNYI(e->getSourceRange(),
+ std::string("unimplemented X86 builtin call: ") +
+ getContext().BuiltinInfo.getName(builtinID));
+ return {};
case X86::BI_mm_setcsr:
- case X86::BI__builtin_ia32_ldmxcsr:
+ case X86::BI__builtin_ia32_ldmxcsr: {
+ Address tmp =
+ createMemTemp(e->getArg(0)->getType(), getLoc(e->getExprLoc()));
+ builder.createStore(getLoc(e->getExprLoc()), ops[0], tmp);
+ return cir::LLVMIntrinsicCallOp::create(
+ builder, getLoc(e->getExprLoc()),
+ builder.getStringAttr("x86.sse.ldmxcsr"), builder.getVoidTy(),
+ tmp.getPointer())
+ .getResult();
+ }
case X86::BI_mm_getcsr:
- case X86::BI__builtin_ia32_stmxcsr:
+ case X86::BI__builtin_ia32_stmxcsr: {
+ Address tmp = createMemTemp(e->getType(), getLoc(e->getExprLoc()));
+ cir::LLVMIntrinsicCallOp::create(builder, getLoc(e->getExprLoc()),
+ builder.getStringAttr("x86.sse.stmxcsr"),
+ builder.getVoidTy(), tmp.getPointer())
+ .getResult();
+ return builder.createLoad(getLoc(e->getExprLoc()), tmp);
+ }
case X86::BI__builtin_ia32_xsave:
case X86::BI__builtin_ia32_xsave64:
case X86::BI__builtin_ia32_xrstor:
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index f879e580989f7..c2ef98d2b25d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1699,6 +1699,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/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index b4afed7019417..6415160efa901 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -646,6 +646,29 @@ mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
return mlir::success();
}
+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();
+ // 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::llvmIntrinsicElementTypeSupport());
+ replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm." + name, llvmResTy,
+ adaptor.getOperands());
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
cir::AssumeOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
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..45d522b60a811
--- /dev/null
+++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c
@@ -0,0 +1,36 @@
+// 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 <immintrin.h>
+
+void test_mm_setcsr(unsigned int A) {
+ // CIR-LABEL: test_mm_setcsr
+ // CIR: cir.store {{.*}}, {{.*}} : !u32i
+ // CIR: cir.call_llvm_intrinsic "x86.sse.ldmxcsr" {{.*}} : (!cir.ptr<!u32i>) -> !void
+
+ // LLVM-LABEL: test_mm_setcsr
+ // LLVM: store i32
+ // LLVM: call void @llvm.x86.sse.ldmxcsr(ptr {{.*}})
+ _mm_setcsr(A);
+}
+
+unsigned int test_mm_getcsr(void) {
+ // CIR-LABEL: test_mm_getcsr
+ // CIR: cir.call_llvm_intrinsic "x86.sse.stmxcsr" %{{.*}} : (!cir.ptr<!u32i>) -> !void
+ // CIR: cir.load {{.*}} : !cir.ptr<!u32i>, !u32i
+
+ // LLVM-LABEL: test_mm_getcsr
+ // LLVM: call void @llvm.x86.sse.stmxcsr(ptr %{{.*}})
+ // LLVM: load i32
+ return _mm_getcsr();
+}
|
|
@llvm/pr-subscribers-clang Author: Thibault Monnier (Thibault-Monnier) Changes... It is part of #167752. Full diff: https://github.com/llvm/llvm-project/pull/167948.diff 6 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 16258513239d9..0d639cb7b0b53 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2579,6 +2579,40 @@ def CIR_FuncOp : CIR_Op<"func", [
}];
}
+//===----------------------------------------------------------------------===//
+// LLVMIntrinsicCallOp
+//===----------------------------------------------------------------------===//
+
+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
+ return type and arguments that maps directly to a llvm intrinsic.
+ It only records intrinsic `intrinsic_name`.
+ }];
+
+ let results = (outs Optional<CIR_AnyType>:$result);
+ let arguments = (ins
+ StrAttr:$intrinsic_name, Variadic<CIR_AnyType>:$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/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 4e6a5ee7ee210..b54256715be96 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -625,6 +625,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<llvm::APSInt> 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 0198a9d4eb192..9c5ae38d8e0fa 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;
@@ -43,6 +42,18 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
// Find out if any arguments are required to be integer constant expressions.
assert(!cir::MissingFeatures::handleBuiltinICEArguments());
+ llvm::SmallVector<mlir::Value> ops;
+
+ // Find out if any arguments are required to be integer constant expressions.
+ unsigned iceArguments = 0;
+ ASTContext::GetBuiltinTypeError error;
+ getContext().GetBuiltinType(builtinID, error, &iceArguments);
+ assert(error == ASTContext::GE_None && "Should not codegen an error");
+
+ for (auto [idx, arg] : llvm::enumerate(e->arguments())) {
+ ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
+ }
+
switch (builtinID) {
default:
return {};
@@ -82,10 +93,30 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
case X86::BI__builtin_ia32_vec_set_v16hi:
case X86::BI__builtin_ia32_vec_set_v8si:
case X86::BI__builtin_ia32_vec_set_v4di:
+ cgm.errorNYI(e->getSourceRange(),
+ std::string("unimplemented X86 builtin call: ") +
+ getContext().BuiltinInfo.getName(builtinID));
+ return {};
case X86::BI_mm_setcsr:
- case X86::BI__builtin_ia32_ldmxcsr:
+ case X86::BI__builtin_ia32_ldmxcsr: {
+ Address tmp =
+ createMemTemp(e->getArg(0)->getType(), getLoc(e->getExprLoc()));
+ builder.createStore(getLoc(e->getExprLoc()), ops[0], tmp);
+ return cir::LLVMIntrinsicCallOp::create(
+ builder, getLoc(e->getExprLoc()),
+ builder.getStringAttr("x86.sse.ldmxcsr"), builder.getVoidTy(),
+ tmp.getPointer())
+ .getResult();
+ }
case X86::BI_mm_getcsr:
- case X86::BI__builtin_ia32_stmxcsr:
+ case X86::BI__builtin_ia32_stmxcsr: {
+ Address tmp = createMemTemp(e->getType(), getLoc(e->getExprLoc()));
+ cir::LLVMIntrinsicCallOp::create(builder, getLoc(e->getExprLoc()),
+ builder.getStringAttr("x86.sse.stmxcsr"),
+ builder.getVoidTy(), tmp.getPointer())
+ .getResult();
+ return builder.createLoad(getLoc(e->getExprLoc()), tmp);
+ }
case X86::BI__builtin_ia32_xsave:
case X86::BI__builtin_ia32_xsave64:
case X86::BI__builtin_ia32_xrstor:
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index f879e580989f7..c2ef98d2b25d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1699,6 +1699,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/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index b4afed7019417..6415160efa901 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -646,6 +646,29 @@ mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
return mlir::success();
}
+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();
+ // 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::llvmIntrinsicElementTypeSupport());
+ replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm." + name, llvmResTy,
+ adaptor.getOperands());
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
cir::AssumeOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
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..45d522b60a811
--- /dev/null
+++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c
@@ -0,0 +1,36 @@
+// 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 <immintrin.h>
+
+void test_mm_setcsr(unsigned int A) {
+ // CIR-LABEL: test_mm_setcsr
+ // CIR: cir.store {{.*}}, {{.*}} : !u32i
+ // CIR: cir.call_llvm_intrinsic "x86.sse.ldmxcsr" {{.*}} : (!cir.ptr<!u32i>) -> !void
+
+ // LLVM-LABEL: test_mm_setcsr
+ // LLVM: store i32
+ // LLVM: call void @llvm.x86.sse.ldmxcsr(ptr {{.*}})
+ _mm_setcsr(A);
+}
+
+unsigned int test_mm_getcsr(void) {
+ // CIR-LABEL: test_mm_getcsr
+ // CIR: cir.call_llvm_intrinsic "x86.sse.stmxcsr" %{{.*}} : (!cir.ptr<!u32i>) -> !void
+ // CIR: cir.load {{.*}} : !cir.ptr<!u32i>, !u32i
+
+ // LLVM-LABEL: test_mm_getcsr
+ // LLVM: call void @llvm.x86.sse.stmxcsr(ptr %{{.*}})
+ // LLVM: load i32
+ return _mm_getcsr();
+}
|
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to wait until #167401 has been merged before reviewing this further so you can rebase this and get the things that are already implemented there.
|
@andykaylor @HendrikHuebner I am done. |
... It is part of #167752.