Skip to content

Commit db3e279

Browse files
authored
[CIR][CIRGen][builtin] handle _mm_clflush (#1397)
1 parent 52bb68c commit db3e279

File tree

5 files changed

+146
-63
lines changed

5 files changed

+146
-63
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2626,6 +2626,23 @@ mlir::Value CIRGenFunction::emitTargetBuiltinExpr(unsigned BuiltinID,
26262626
getTarget().getTriple().getArch());
26272627
}
26282628

2629+
mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned ICEArguments,
2630+
unsigned Idx,
2631+
const CallExpr *E) {
2632+
mlir::Value Arg = {};
2633+
if ((ICEArguments & (1 << Idx)) == 0) {
2634+
Arg = emitScalarExpr(E->getArg(Idx));
2635+
} else {
2636+
// If this is required to be a constant, constant fold it so that we
2637+
// know that the generated intrinsic gets a ConstantInt.
2638+
std::optional<llvm::APSInt> Result =
2639+
E->getArg(Idx)->getIntegerConstantExpr(getContext());
2640+
assert(Result && "Expected argument to be a constant");
2641+
Arg = builder.getConstInt(getLoc(E->getSourceRange()), *Result);
2642+
}
2643+
return Arg;
2644+
}
2645+
26292646
void CIRGenFunction::emitVAStartEnd(mlir::Value ArgValue, bool IsStart) {
26302647
// LLVM codegen casts to *i8, no real gain on doing this for CIRGen this
26312648
// early, defer to LLVM lowering.

clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,50 +1676,6 @@ static const ARMVectorIntrinsicInfo AArch64SMEIntrinsicMap[] = {
16761676
#undef SMEMAP1
16771677
#undef SMEMAP2
16781678

1679-
// Many of MSVC builtins are on x64, ARM and AArch64; to avoid repeating code,
1680-
// we handle them here.
1681-
enum class CIRGenFunction::MSVCIntrin {
1682-
_BitScanForward,
1683-
_BitScanReverse,
1684-
_InterlockedAnd,
1685-
_InterlockedDecrement,
1686-
_InterlockedExchange,
1687-
_InterlockedExchangeAdd,
1688-
_InterlockedExchangeSub,
1689-
_InterlockedIncrement,
1690-
_InterlockedOr,
1691-
_InterlockedXor,
1692-
_InterlockedExchangeAdd_acq,
1693-
_InterlockedExchangeAdd_rel,
1694-
_InterlockedExchangeAdd_nf,
1695-
_InterlockedExchange_acq,
1696-
_InterlockedExchange_rel,
1697-
_InterlockedExchange_nf,
1698-
_InterlockedCompareExchange_acq,
1699-
_InterlockedCompareExchange_rel,
1700-
_InterlockedCompareExchange_nf,
1701-
_InterlockedCompareExchange128,
1702-
_InterlockedCompareExchange128_acq,
1703-
_InterlockedCompareExchange128_rel,
1704-
_InterlockedCompareExchange128_nf,
1705-
_InterlockedOr_acq,
1706-
_InterlockedOr_rel,
1707-
_InterlockedOr_nf,
1708-
_InterlockedXor_acq,
1709-
_InterlockedXor_rel,
1710-
_InterlockedXor_nf,
1711-
_InterlockedAnd_acq,
1712-
_InterlockedAnd_rel,
1713-
_InterlockedAnd_nf,
1714-
_InterlockedIncrement_acq,
1715-
_InterlockedIncrement_rel,
1716-
_InterlockedIncrement_nf,
1717-
_InterlockedDecrement_acq,
1718-
_InterlockedDecrement_rel,
1719-
_InterlockedDecrement_nf,
1720-
__fastfail,
1721-
};
1722-
17231679
static std::optional<CIRGenFunction::MSVCIntrin>
17241680
translateAarch64ToMsvcIntrin(unsigned BuiltinID) {
17251681
using MSVCIntrin = CIRGenFunction::MSVCIntrin;
@@ -2102,23 +2058,6 @@ mlir::Value CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned BuiltinID,
21022058
llvm_unreachable("NYI");
21032059
}
21042060

2105-
mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(unsigned ICEArguments,
2106-
unsigned Idx,
2107-
const CallExpr *E) {
2108-
mlir::Value Arg = {};
2109-
if ((ICEArguments & (1 << Idx)) == 0) {
2110-
Arg = emitScalarExpr(E->getArg(Idx));
2111-
} else {
2112-
// If this is required to be a constant, constant fold it so that we
2113-
// know that the generated intrinsic gets a ConstantInt.
2114-
std::optional<llvm::APSInt> Result =
2115-
E->getArg(Idx)->getIntegerConstantExpr(getContext());
2116-
assert(Result && "Expected argument to be a constant");
2117-
Arg = builder.getConstInt(getLoc(E->getSourceRange()), *Result);
2118-
}
2119-
return Arg;
2120-
}
2121-
21222061
static mlir::Value emitArmLdrexNon128Intrinsic(unsigned int builtinID,
21232062
const CallExpr *clangCallExpr,
21242063
CIRGenFunction &cgf) {

clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,79 @@ using namespace clang;
3131
using namespace clang::CIRGen;
3232
using namespace cir;
3333

34+
static std::optional<CIRGenFunction::MSVCIntrin>
35+
translateX86ToMsvcIntrin(unsigned BuiltinID) {
36+
using MSVCIntrin = CIRGenFunction::MSVCIntrin;
37+
switch (BuiltinID) {
38+
default:
39+
return std::nullopt;
40+
case clang::X86::BI_BitScanForward:
41+
case clang::X86::BI_BitScanForward64:
42+
return MSVCIntrin::_BitScanForward;
43+
case clang::X86::BI_BitScanReverse:
44+
case clang::X86::BI_BitScanReverse64:
45+
return MSVCIntrin::_BitScanReverse;
46+
case clang::X86::BI_InterlockedAnd64:
47+
return MSVCIntrin::_InterlockedAnd;
48+
case clang::X86::BI_InterlockedCompareExchange128:
49+
return MSVCIntrin::_InterlockedCompareExchange128;
50+
case clang::X86::BI_InterlockedExchange64:
51+
return MSVCIntrin::_InterlockedExchange;
52+
case clang::X86::BI_InterlockedExchangeAdd64:
53+
return MSVCIntrin::_InterlockedExchangeAdd;
54+
case clang::X86::BI_InterlockedExchangeSub64:
55+
return MSVCIntrin::_InterlockedExchangeSub;
56+
case clang::X86::BI_InterlockedOr64:
57+
return MSVCIntrin::_InterlockedOr;
58+
case clang::X86::BI_InterlockedXor64:
59+
return MSVCIntrin::_InterlockedXor;
60+
case clang::X86::BI_InterlockedDecrement64:
61+
return MSVCIntrin::_InterlockedDecrement;
62+
case clang::X86::BI_InterlockedIncrement64:
63+
return MSVCIntrin::_InterlockedIncrement;
64+
}
65+
llvm_unreachable("must return from switch");
66+
}
67+
3468
mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned BuiltinID,
3569
const CallExpr *E) {
36-
llvm_unreachable("NYI");
70+
if (BuiltinID == Builtin::BI__builtin_cpu_is)
71+
llvm_unreachable("__builtin_cpu_is NYI");
72+
if (BuiltinID == Builtin::BI__builtin_cpu_supports)
73+
llvm_unreachable("__builtin_cpu_supports NYI");
74+
if (BuiltinID == Builtin::BI__builtin_cpu_init)
75+
llvm_unreachable("__builtin_cpu_init NYI");
76+
77+
// Handle MSVC intrinsics before argument evaluation to prevent double
78+
// evaluation.
79+
if (std::optional<MSVCIntrin> MsvcIntId = translateX86ToMsvcIntrin(BuiltinID))
80+
llvm_unreachable("translateX86ToMsvcIntrin NYI");
81+
82+
llvm::SmallVector<mlir::Value, 4> Ops;
83+
84+
// Find out if any arguments are required to be integer constant expressions.
85+
unsigned ICEArguments = 0;
86+
ASTContext::GetBuiltinTypeError Error;
87+
getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
88+
assert(Error == ASTContext::GE_None && "Should not codegen an error");
89+
90+
for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
91+
Ops.push_back(emitScalarOrConstFoldImmArg(ICEArguments, i, E));
92+
}
93+
94+
switch (BuiltinID) {
95+
default:
96+
return nullptr;
97+
case X86::BI_mm_prefetch: {
98+
llvm_unreachable("_mm_prefetch NYI");
99+
}
100+
case X86::BI_mm_clflush: {
101+
mlir::Type voidTy = cir::VoidType::get(&getMLIRContext());
102+
return builder
103+
.create<cir::LLVMIntrinsicCallOp>(
104+
getLoc(E->getExprLoc()), builder.getStringAttr("x86.sse2.clflush"),
105+
voidTy, Ops[0])
106+
.getResult();
107+
}
108+
}
37109
}

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,49 @@ class CIRGenFunction : public CIRGenTypeCache {
10151015
RValue emitCoroutineIntrinsic(const CallExpr *E, unsigned int IID);
10161016
RValue emitCoroutineFrame();
10171017

1018-
enum class MSVCIntrin;
1018+
// Many of MSVC builtins are on x64, ARM and AArch64; to avoid repeating code,
1019+
// we handle them here.
1020+
enum class MSVCIntrin {
1021+
_BitScanForward,
1022+
_BitScanReverse,
1023+
_InterlockedAnd,
1024+
_InterlockedDecrement,
1025+
_InterlockedExchange,
1026+
_InterlockedExchangeAdd,
1027+
_InterlockedExchangeSub,
1028+
_InterlockedIncrement,
1029+
_InterlockedOr,
1030+
_InterlockedXor,
1031+
_InterlockedExchangeAdd_acq,
1032+
_InterlockedExchangeAdd_rel,
1033+
_InterlockedExchangeAdd_nf,
1034+
_InterlockedExchange_acq,
1035+
_InterlockedExchange_rel,
1036+
_InterlockedExchange_nf,
1037+
_InterlockedCompareExchange_acq,
1038+
_InterlockedCompareExchange_rel,
1039+
_InterlockedCompareExchange_nf,
1040+
_InterlockedCompareExchange128,
1041+
_InterlockedCompareExchange128_acq,
1042+
_InterlockedCompareExchange128_rel,
1043+
_InterlockedCompareExchange128_nf,
1044+
_InterlockedOr_acq,
1045+
_InterlockedOr_rel,
1046+
_InterlockedOr_nf,
1047+
_InterlockedXor_acq,
1048+
_InterlockedXor_rel,
1049+
_InterlockedXor_nf,
1050+
_InterlockedAnd_acq,
1051+
_InterlockedAnd_rel,
1052+
_InterlockedAnd_nf,
1053+
_InterlockedIncrement_acq,
1054+
_InterlockedIncrement_rel,
1055+
_InterlockedIncrement_nf,
1056+
_InterlockedDecrement_acq,
1057+
_InterlockedDecrement_rel,
1058+
_InterlockedDecrement_nf,
1059+
__fastfail,
1060+
};
10191061

10201062
mlir::Value emitARMMVEBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
10211063
ReturnValueSlot ReturnValue,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Global variables of intergal types
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s
3+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
4+
// RUN: %clang_cc1 -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s
5+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
6+
7+
void test_mm_clflush(const void* tmp_vCp) {
8+
// CIR-LABEL: test_mm_clflush
9+
// LLVM-LABEL: test_mm_clflush
10+
_mm_clflush(tmp_vCp);
11+
// CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr<!void>) -> !void
12+
// LLVM: call void @llvm.x86.sse2.clflush(ptr {{%.*}})
13+
}

0 commit comments

Comments
 (0)