https://github.com/Luhaocong created https://github.com/llvm/llvm-project/pull/171094
- Support CIR codegen for follow X86 builtin: `_ReadWriteBarrier` `_ReadBarrier` `_WriteBarrier` `__faststorefence` - CIR dialect operations maybe have no results, no value will return after `emitTargetBuiltinExpr` even if it executes successfully. Using `std::optional<mlir::Value>` as return type to reslove this problem. >From 6d8a10d4c9b8df3ea70d3bf326fefb0eac62633c Mon Sep 17 00:00:00 2001 From: Haocong Lu <[email protected]> Date: Mon, 8 Dec 2025 11:24:15 +0800 Subject: [PATCH] [CIR][X86] Implement lowering for `readwritebarrier` builtins - Support CIR codegen for follow X86 builtin: `_ReadWriteBarrier` `_ReadBarrier` `_WriteBarrier` `__faststorefence` - CIR dialect operations maybe have no results, no value will return after `emitTargetBuiltinExpr` even if it executes successfully. Using `std::optional<mlir::Value>` as return type to reslove this problem. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 32 +++-- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 112 +++++++++--------- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 60 +++++++--- clang/lib/CIR/CodeGen/CIRGenFunction.h | 24 ++-- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 +- .../test/CIR/CodeGen/ms-barriers-intrinsics.c | 82 +++++++++++++ 7 files changed, 216 insertions(+), 100 deletions(-) create mode 100644 clang/test/CIR/CodeGen/ms-barriers-intrinsics.c diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index fcc7585cf81a5..e39bc31c3eafa 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5493,7 +5493,7 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> { }]; } -def CIR_AtomicFence : CIR_Op<"atomic.fence"> { +def CIR_AtomicFenceOp : CIR_Op<"atomic.fence"> { let summary = "Atomic thread fence"; let description = [{ C/C++ Atomic thread fence synchronization primitive. Implements the builtin diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 16c006df6853e..87408fdae80d8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -80,7 +80,7 @@ static mlir::Value makeAtomicFenceValue(CIRGenFunction &cgf, auto ordering = static_cast<cir::MemOrder>(constOrderingAttr.getUInt()); - cir::AtomicFence::create( + cir::AtomicFenceOp::create( builder, cgf.getLoc(expr->getSourceRange()), ordering, cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope)); @@ -1352,7 +1352,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, } // Now see if we can emit a target-specific builtin. - if (mlir::Value v = emitTargetBuiltinExpr(builtinID, e, returnValue)) { + if (std::optional<mlir::Value> rst = + emitTargetBuiltinExpr(builtinID, e, returnValue)) { + mlir::Value v = rst.value(); + // CIR dialect operations maybe have no results, no value will return + // even if it executes successfully. + if (!v) + return RValue::get(nullptr); + switch (evalKind) { case cir::TEK_Scalar: if (mlir::isa<cir::VoidType>(v.getType())) @@ -1373,11 +1380,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, return getUndefRValue(e->getType()); } -static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf, - unsigned builtinID, - const CallExpr *e, - ReturnValueSlot &returnValue, - llvm::Triple::ArchType arch) { +static std::optional<mlir::Value> +emitTargetArchBuiltinExpr(CIRGenFunction *cgf, unsigned builtinID, + const CallExpr *e, ReturnValueSlot &returnValue, + llvm::Triple::ArchType arch) { // When compiling in HipStdPar mode we have to be conservative in rejecting // target specific features in the FE, and defer the possible error to the // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is @@ -1386,7 +1392,7 @@ static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf, // EmitStdParUnsupportedBuiltin. if (cgf->getLangOpts().HIPStdPar && cgf->getLangOpts().CUDAIsDevice && arch != cgf->getTarget().getTriple().getArch()) - return {}; + return std::nullopt; switch (arch) { case llvm::Triple::arm: @@ -1395,7 +1401,7 @@ static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf, case llvm::Triple::thumbeb: // These are actually NYI, but that will be reported by emitBuiltinExpr. // At this point, we don't even know that the builtin is target-specific. - return nullptr; + return std::nullopt; case llvm::Triple::aarch64: case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: @@ -1404,7 +1410,7 @@ static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf, case llvm::Triple::bpfel: // These are actually NYI, but that will be reported by emitBuiltinExpr. // At this point, we don't even know that the builtin is target-specific. - return nullptr; + return std::nullopt; case llvm::Triple::x86: case llvm::Triple::x86_64: @@ -1426,13 +1432,13 @@ static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf, case llvm::Triple::riscv64: // These are actually NYI, but that will be reported by emitBuiltinExpr. // At this point, we don't even know that the builtin is target-specific. - return {}; + return std::nullopt; default: - return {}; + return std::nullopt; } } -mlir::Value +std::optional<mlir::Value> CIRGenFunction::emitTargetBuiltinExpr(unsigned builtinID, const CallExpr *e, ReturnValueSlot &returnValue) { if (getContext().BuiltinInfo.isAuxBuiltinID(builtinID)) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 5a9ae59ca253a..bfd16c78e369f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -30,21 +30,22 @@ using namespace clang; using namespace clang::CIRGen; using namespace llvm; -mlir::Value CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID, - const CallExpr *expr) { +std::optional<mlir::Value> +CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID, + const CallExpr *expr) { if (builtinID >= SVE::BI__builtin_sve_reinterpret_s8_s8 && builtinID <= SVE::BI__builtin_sve_reinterpret_f64_f64_x4) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } assert(!cir::MissingFeatures::aarch64SVEIntrinsics()); switch (builtinID) { default: - return {}; + return std::nullopt; case SVE::BI__builtin_sve_svreinterpret_b: case SVE::BI__builtin_sve_svreinterpret_c: @@ -163,20 +164,21 @@ mlir::Value CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Unreachable: All cases in the switch above return. } -mlir::Value CIRGenFunction::emitAArch64SMEBuiltinExpr(unsigned builtinID, - const CallExpr *expr) { +std::optional<mlir::Value> +CIRGenFunction::emitAArch64SMEBuiltinExpr(unsigned builtinID, + const CallExpr *expr) { assert(!cir::MissingFeatures::aarch64SMEIntrinsics()); cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Some intrinsics are equivalent for codegen. @@ -574,7 +576,7 @@ static const std::pair<unsigned, unsigned> neonEquivalentIntrinsicMap[] = { NEON::BI__builtin_neon_vstl1q_lane_s64}, }; -mlir::Value +std::optional<mlir::Value> CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, ReturnValueSlot returnValue, llvm::Triple::ArchType arch) { @@ -590,7 +592,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } switch (builtinID) { @@ -610,34 +612,34 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_trap) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_get_sme_state) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rbit) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rbit64) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_clz || @@ -645,20 +647,20 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_cls) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_cls64) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rint32zf || @@ -666,7 +668,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rint64zf || @@ -674,7 +676,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rint32xf || @@ -682,7 +684,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rint64xf || @@ -690,14 +692,14 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_jcvt) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_ld64b || @@ -707,7 +709,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rndr || @@ -715,14 +717,14 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__clear_cache) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if ((builtinID == clang::AArch64::BI__builtin_arm_ldrex || @@ -731,14 +733,14 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_ldrex || builtinID == clang::AArch64::BI__builtin_arm_ldaex) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if ((builtinID == clang::AArch64::BI__builtin_arm_strex || @@ -747,7 +749,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_strex || @@ -755,35 +757,35 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__getReg) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__break) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_clrex) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI_ReadWriteBarrier) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // CRC32 @@ -819,7 +821,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Memory Operations (MOPS) @@ -827,7 +829,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Memory Tagging Extensions (MTE) Intrinsics @@ -857,7 +859,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_arm_rsr || @@ -871,7 +873,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI_ReadStatusReg || @@ -880,21 +882,21 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI_AddressOfReturnAddress) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__builtin_sponentry) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == clang::AArch64::BI__mulh || @@ -902,7 +904,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI__writex18byte || @@ -912,7 +914,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI__readx18byte || @@ -922,7 +924,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI__addx18byte || @@ -936,7 +938,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI_CopyDoubleFromInt64 || @@ -946,7 +948,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI_CountLeadingOnes || @@ -956,7 +958,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI_CountLeadingSigns || @@ -964,7 +966,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI_CountOneBits || @@ -972,28 +974,28 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI__prefetch) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == AArch64::BI__hlt) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } if (builtinID == NEON::BI__builtin_neon_vcvth_bf16_f32) { cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Handle MSVC intrinsics before argument evaluation to prevent double @@ -1199,7 +1201,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Not all intrinsics handled by the common case work for AArch64 yet, so only @@ -1210,7 +1212,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, switch (builtinID) { default: - return {}; + return std::nullopt; case NEON::BI__builtin_neon_vbsl_v: case NEON::BI__builtin_neon_vbslq_v: case NEON::BI__builtin_neon_vfma_lane_v: @@ -1576,7 +1578,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented AArch64 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } // Unreachable: All cases in the switch above return. diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 1c1ef4da20b0d..d3d026fa7da5c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -370,19 +370,19 @@ static mlir::Value emitX86vpcom(CIRGenBuilderTy &builder, mlir::Location loc, return builder.createVecCompare(loc, pred, op0, op1); } -mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, - const CallExpr *expr) { +std::optional<mlir::Value> +CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { if (builtinID == Builtin::BI__builtin_cpu_is) { cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_is"); - return {}; + return std::nullopt; } if (builtinID == Builtin::BI__builtin_cpu_supports) { cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_supports"); - return {}; + return std::nullopt; } if (builtinID == Builtin::BI__builtin_cpu_init) { cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_init"); - return {}; + return std::nullopt; } // Handle MSVC intrinsics before argument evaluation to prevent double @@ -410,7 +410,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, switch (builtinID) { default: - return {}; + return std::nullopt; case X86::BI_mm_clflush: return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()), "x86.sse2.clflush", voidTy, ops[0]); @@ -432,7 +432,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: @@ -751,7 +751,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; case X86::BI__builtin_ia32_gather3div2df: case X86::BI__builtin_ia32_gather3div2di: case X86::BI__builtin_ia32_gather3div4df: @@ -1018,7 +1018,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; case X86::BI__builtin_ia32_pshuflw: case X86::BI__builtin_ia32_pshuflw256: case X86::BI__builtin_ia32_pshuflw512: @@ -1093,7 +1093,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; case X86::BI__builtin_ia32_kshiftliqi: case X86::BI__builtin_ia32_kshiftlihi: case X86::BI__builtin_ia32_kshiftlisi: @@ -1217,7 +1217,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; case X86::BI__builtin_ia32_vpcomb: case X86::BI__builtin_ia32_vpcomw: case X86::BI__builtin_ia32_vpcomd: @@ -1353,7 +1353,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; case X86::BI__builtin_ia32_pmuludq128: case X86::BI__builtin_ia32_pmuludq256: case X86::BI__builtin_ia32_pmuludq512: { @@ -1467,7 +1467,7 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; case X86::BI__builtin_ia32_cmpnltps: case X86::BI__builtin_ia32_cmpnltpd: return emitVectorFCmp(builder, ops, getLoc(expr->getExprLoc()), @@ -1523,13 +1523,37 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, case X86::BI__mulh: case X86::BI__umulh: case X86::BI_mul128: - case X86::BI_umul128: - case X86::BI__faststorefence: + case X86::BI_umul128: { + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented X86 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return std::nullopt; + } + case X86::BI__faststorefence: { + cir::AtomicFenceOp::create( + builder, getLoc(expr->getExprLoc()), + cir::MemOrder::SequentiallyConsistent, + cir::SyncScopeKindAttr::get(&getMLIRContext(), + cir::SyncScopeKind::System)); + return mlir::Value{}; + } case X86::BI__shiftleft128: - case X86::BI__shiftright128: + case X86::BI__shiftright128: { + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented X86 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return std::nullopt; + } case X86::BI_ReadWriteBarrier: case X86::BI_ReadBarrier: - case X86::BI_WriteBarrier: + case X86::BI_WriteBarrier: { + cir::AtomicFenceOp::create( + builder, getLoc(expr->getExprLoc()), + cir::MemOrder::SequentiallyConsistent, + cir::SyncScopeKindAttr::get(&getMLIRContext(), + cir::SyncScopeKind::SingleThread)); + return mlir::Value{}; + } case X86::BI_AddressOfReturnAddress: case X86::BI__stosb: case X86::BI__ud2: @@ -1562,6 +1586,6 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, cgm.errorNYI(expr->getSourceRange(), std::string("unimplemented X86 builtin call: ") + getContext().BuiltinInfo.getName(builtinID)); - return {}; + return std::nullopt; } } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 0df812bcfb94e..6690f86acff15 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1248,13 +1248,14 @@ class CIRGenFunction : public CIRGenTypeCache { /// CIR emit functions /// ---------------------- public: - mlir::Value emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, - ReturnValueSlot returnValue, - llvm::Triple::ArchType arch); - mlir::Value emitAArch64SMEBuiltinExpr(unsigned builtinID, - const CallExpr *expr); - mlir::Value emitAArch64SVEBuiltinExpr(unsigned builtinID, - const CallExpr *expr); + std::optional<mlir::Value> + emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, + ReturnValueSlot returnValue, + llvm::Triple::ArchType arch); + std::optional<mlir::Value> emitAArch64SMEBuiltinExpr(unsigned builtinID, + const CallExpr *expr); + std::optional<mlir::Value> emitAArch64SVEBuiltinExpr(unsigned builtinID, + const CallExpr *expr); mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, @@ -1814,9 +1815,9 @@ class CIRGenFunction : public CIRGenTypeCache { bool buildingTopLevelCase); mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s); - mlir::Value emitTargetBuiltinExpr(unsigned builtinID, - const clang::CallExpr *e, - ReturnValueSlot &returnValue); + std::optional<mlir::Value> + emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, + ReturnValueSlot &returnValue); /// Given a value and its clang type, returns the value casted to its memory /// representation. @@ -1856,7 +1857,8 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s); - mlir::Value emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr); + std::optional<mlir::Value> emitX86BuiltinExpr(unsigned builtinID, + const CallExpr *expr); /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is /// nonnull, if 1\p LHS is marked _Nonnull. diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 97bd3cf850daa..c8b395b1feb93 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -860,8 +860,8 @@ mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMAtomicFenceLowering::matchAndRewrite( - cir::AtomicFence op, OpAdaptor adaptor, +mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite( + cir::AtomicFenceOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { mlir::LLVM::AtomicOrdering llvmOrder = getLLVMMemOrder(adaptor.getOrdering()); diff --git a/clang/test/CIR/CodeGen/ms-barriers-intrinsics.c b/clang/test/CIR/CodeGen/ms-barriers-intrinsics.c new file mode 100644 index 0000000000000..f316307ec35d2 --- /dev/null +++ b/clang/test/CIR/CodeGen/ms-barriers-intrinsics.c @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -x c -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s +// RUN: FileCheck --check-prefixes=CIR,CIR-X86 --input-file=%t.cir %s +// RUN: %clang_cc1 -x c++ -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s +// RUN: FileCheck --check-prefixes=CIR,CIR-X86 --input-file=%t.cir %s + +// RUN: %clang_cc1 -x c -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s +// RUN: FileCheck --check-prefixes=LLVM,LLVM-X86 --input-file=%t.ll %s +// RUN: %clang_cc1 -x c++ -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s +// RUN: FileCheck --check-prefixes=LLVM,LLVM-X86 --input-file=%t.ll %s + +// RUN: %clang_cc1 -x c -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -emit-llvm -Wall -Werror %s -o - \ +// RUN: | FileCheck %s --check-prefixes=OGCG,OGCG-X86 +// RUN: %clang_cc1 -x c++ -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -emit-llvm -Wall -Werror %s -o - \ +// RUN: | FileCheck %s --check-prefixes=OGCG,OGCG-X86 + +// This test copies clang/test/CodeGen/ms-barriers-intrinsics.c. + +void _ReadWriteBarrier(void); +void _ReadBarrier(void); +void _WriteBarrier(void); +void __faststorefence(void); + +void test_ReadWriteBarrier(void) { _ReadWriteBarrier(); } +// CIR-LABEL: test_ReadWriteBarrier +// CIR: cir.atomic.fence syncscope(single_thread) seq_cst +// CIR: cir.return + +// LLVM-LABEL: test_ReadWriteBarrier +// LLVM: fence syncscope("singlethread") seq_cst +// LLVM: ret void + +// OGCG-LABEL: test_ReadWriteBarrier +// OGCG: fence syncscope("singlethread") seq_cst +// OGCG: ret void + +void test_ReadBarrier(void) { _ReadBarrier(); } +// CIR-LABEL: test_ReadBarrier +// CIR: cir.atomic.fence syncscope(single_thread) seq_cst +// CIR: cir.return + +// LLVM-LABEL: test_ReadBarrier +// LLVM: fence syncscope("singlethread") seq_cst +// LLVM: ret void + +// OGCG-LABEL: test_ReadBarrier +// OGCG: fence syncscope("singlethread") seq_cst +// OGCG: ret void + +void test_WriteBarrier(void) { _WriteBarrier(); } +// CIR-LABEL: test_WriteBarrier +// CIR: cir.atomic.fence syncscope(single_thread) seq_cst +// CIR: cir.return + +// LLVM-LABEL: test_WriteBarrier +// LLVM: fence syncscope("singlethread") seq_cst +// LLVM: ret void + +// OGCG-LABEL: test_WriteBarrier +// OGCG: fence syncscope("singlethread") seq_cst +// OGCG: ret void + +#if defined(__x86_64__) +void test__faststorefence(void) { __faststorefence(); } +// CIR-X86-LABEL: test__faststorefence +// CIR-X86: cir.atomic.fence syncscope(system) seq_cst +// CIR-X86: cir.return + +// LLVM-X86-LABEL: test__faststorefence +// LLVM-X86: fence seq_cst +// LLVM-X86: ret void + +// OGCG-X86-LABEL: test__faststorefence +// OGCG-X86: fence seq_cst +// OGCG-X86: ret void +#endif + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
