llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Jianjian Guan (jacquesguan) <details> <summary>Changes</summary> Include __builtin_riscv_ntl_load and __builtin_riscv_ntl_store. --- Full diff: https://github.com/llvm/llvm-project/pull/205468.diff 4 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp (+31-3) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+4) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp (+25) - (added) clang/test/CIR/CodeGenBuiltins/RISCV/riscv-zihintntl.c (+127) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp index ec262922be942..2109ef45c392e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp @@ -38,6 +38,12 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) { ASTContext::GetBuiltinTypeError error; getContext().GetBuiltinType(builtinID, error, &iceArguments); assert(error == ASTContext::GE_None && "Should not codegen an error"); + + if (builtinID == RISCV::BI__builtin_riscv_ntl_load) + iceArguments |= (1 << 1); + if (builtinID == RISCV::BI__builtin_riscv_ntl_store) + iceArguments |= (1 << 2); + for (auto [idx, arg] : llvm::enumerate(e->arguments())) ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg)); @@ -154,9 +160,31 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) { // Zihintntl case RISCV::BI__builtin_riscv_ntl_load: case RISCV::BI__builtin_riscv_ntl_store: { - cgm.errorNYI(e->getSourceRange(), - std::string("unimplemented RISC-V builtin call: ") + - getContext().BuiltinInfo.getName(builtinID)); + unsigned domainVal = 5; // Default __RISCV_NTLH_ALL + unsigned domainArgNo = + builtinID == RISCV::BI__builtin_riscv_ntl_load ? 1 : 2; + if (e->getNumArgs() > domainArgNo) { + const std::optional<llvm::APSInt> result = + e->getArg(domainArgNo)->getIntegerConstantExpr(getContext()); + assert(result && "Expected NTLH domain argument to be a constant"); + domainVal = result->getZExtValue(); + } + + mlir::Location loc = getLoc(e->getSourceRange()); + mlir::Attribute domainAttr = builder.getI32IntegerAttr(domainVal); + Address addr(ops[0], + cgm.getNaturalPointeeTypeAlignment(e->getArg(0)->getType())); + if (builtinID == RISCV::BI__builtin_riscv_ntl_load) { + auto load = builder.createLoad(loc, addr, /*isVolatile=*/false, + /*isNontemporal=*/true); + load->setAttr("cir.riscv_nontemporal_domain", domainAttr); + return load.getResult(); + } + + mlir::Value val = emitToMemory(ops[1], e->getArg(1)->getType()); + auto store = builder.createStore(loc, val, addr, /*isVolatile=*/false, + /*isNontemporal=*/true); + store->setAttr("cir.riscv_nontemporal_domain", domainAttr); return mlir::Value{}; } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 7cb15f8c5e8a3..cb703a038f721 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1931,6 +1931,8 @@ mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite( op.getIsVolatile(), /*isNonTemporal=*/op.getIsNontemporal(), /*isInvariant=*/false, /*isInvariantGroup=*/false, ordering, llvmSyncScope.value_or(std::string())); + if (mlir::Attribute domain = op->getAttr("cir.riscv_nontemporal_domain")) + newLoad->setAttr("cir.riscv_nontemporal_domain", domain); // Convert adapted result to its original type if needed. mlir::Value result = @@ -1986,6 +1988,8 @@ mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite( op.getIsVolatile(), /*isNonTemporal=*/op.getIsNontemporal(), /*isInvariantGroup=*/false, memorder, llvmSyncScope.value_or(std::string())); + if (mlir::Attribute domain = op->getAttr("cir.riscv_nontemporal_domain")) + storeOp->setAttr("cir.riscv_nontemporal_domain", domain); rewriter.replaceOp(op, storeOp); assert(!cir::MissingFeatures::opLoadStoreTbaa()); return mlir::LogicalResult::success(); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp index dbcd0aed88056..36b46d7a9c666 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp @@ -18,7 +18,9 @@ #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Metadata.h" using namespace llvm; @@ -59,11 +61,34 @@ class CIRDialectLLVMIRTranslationInterface } else if (auto mod = dyn_cast<mlir::ModuleOp>(op)) { if (mlir::failed(amendModule(mod, attribute, moduleTranslation))) return mlir::failure(); + } else if (attribute.getName() == "cir.riscv_nontemporal_domain") { + if (mlir::failed(amendRISCVNontemporalDomain(op, instructions, attribute, + moduleTranslation))) + return mlir::failure(); } return mlir::success(); } private: + mlir::LogicalResult amendRISCVNontemporalDomain( + mlir::Operation *op, llvm::ArrayRef<llvm::Instruction *> instructions, + mlir::NamedAttribute attribute, + mlir::LLVM::ModuleTranslation &moduleTranslation) const { + auto domain = mlir::dyn_cast<mlir::IntegerAttr>(attribute.getValue()); + if (!domain) + return op->emitError() + << "expected cir.riscv_nontemporal_domain to be an integer"; + + llvm::LLVMContext &llvmContext = moduleTranslation.getLLVMContext(); + llvm::MDNode *node = llvm::MDNode::get( + llvmContext, llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(llvmContext), + domain.getValue().getZExtValue()))); + for (llvm::Instruction *inst : instructions) + inst->setMetadata("riscv-nontemporal-domain", node); + return mlir::success(); + } + // Translate CIR function attributes to LLVM function attributes. mlir::LogicalResult amendFunction(mlir::LLVM::LLVMFuncOp func, diff --git a/clang/test/CIR/CodeGenBuiltins/RISCV/riscv-zihintntl.c b/clang/test/CIR/CodeGenBuiltins/RISCV/riscv-zihintntl.c new file mode 100644 index 0000000000000..fb0f27f334ed6 --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/RISCV/riscv-zihintntl.c @@ -0,0 +1,127 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv32 -target-feature +zihintntl -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR +// RUN: %clang_cc1 -triple riscv64 -target-feature +zihintntl -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR +// RUN: %clang_cc1 -triple riscv32 -target-feature +zihintntl -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM +// RUN: %clang_cc1 -triple riscv64 -target-feature +zihintntl -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM +// RUN: %clang_cc1 -triple riscv32 -target-feature +zihintntl -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM +// RUN: %clang_cc1 -triple riscv64 -target-feature +zihintntl -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM + +#include <riscv_ntlh.h> + +signed char sc; +unsigned char uc; +signed short ss; +unsigned short us; +signed int si; +unsigned int ui; +signed long long sll; +unsigned long long ull; +_Float16 h1, h2; +float f1, f2; +double d1, d2; +typedef int v4si __attribute__((vector_size(16))); +typedef signed short v8ss __attribute__((vector_size(16))); +typedef signed char v16sc __attribute__((vector_size(16))); +v4si v4si1, v4si2; +v8ss v8ss1, v8ss2; +v16sc v16sc1, v16sc2; + +// CIR-LABEL: cir.func{{.*}} @ntl_load_all_sizes( +// LLVM-LABEL: @ntl_load_all_sizes( +void ntl_load_all_sizes(void) { + // CIR: cir.load nontemporal align(1) {{.*}} {cir.riscv_nontemporal_domain = 2 : i32} + // LLVM: load i8, ptr {{.*}}, align 1, !nontemporal [[NT:![0-9]+]], !riscv-nontemporal-domain [[D2:![0-9]+]] + uc = __riscv_ntl_load(&sc, __RISCV_NTLH_INNERMOST_PRIVATE); + // CIR: cir.load nontemporal align(1) {{.*}} {cir.riscv_nontemporal_domain = 3 : i32} + // LLVM: load i8, ptr {{.*}}, align 1, !nontemporal [[NT]], !riscv-nontemporal-domain [[D3:![0-9]+]] + sc = __riscv_ntl_load(&uc, __RISCV_NTLH_ALL_PRIVATE); + // CIR: cir.load nontemporal align(2) {{.*}} {cir.riscv_nontemporal_domain = 4 : i32} + // LLVM: load i16, ptr {{.*}}, align 2, !nontemporal [[NT]], !riscv-nontemporal-domain [[D4:![0-9]+]] + us = __riscv_ntl_load(&ss, __RISCV_NTLH_INNERMOST_SHARED); + // CIR: cir.load nontemporal align(2) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: load i16, ptr {{.*}}, align 2, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5:![0-9]+]] + ss = __riscv_ntl_load(&us, __RISCV_NTLH_ALL); + // CIR: cir.load nontemporal align(4) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: load i32, ptr {{.*}}, align 4, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + ui = __riscv_ntl_load(&si); + // CIR: cir.load nontemporal align(4) {{.*}} {cir.riscv_nontemporal_domain = 2 : i32} + // LLVM: load i32, ptr {{.*}}, align 4, !nontemporal [[NT]], !riscv-nontemporal-domain [[D2]] + si = __riscv_ntl_load(&ui, __RISCV_NTLH_INNERMOST_PRIVATE); + // CIR: cir.load nontemporal align(8) {{.*}} {cir.riscv_nontemporal_domain = 3 : i32} + // LLVM: load i64, ptr {{.*}}, align 8, !nontemporal [[NT]], !riscv-nontemporal-domain [[D3]] + ull = __riscv_ntl_load(&sll, __RISCV_NTLH_ALL_PRIVATE); + // CIR: cir.load nontemporal align(8) {{.*}} {cir.riscv_nontemporal_domain = 4 : i32} + // LLVM: load i64, ptr {{.*}}, align 8, !nontemporal [[NT]], !riscv-nontemporal-domain [[D4]] + sll = __riscv_ntl_load(&ull, __RISCV_NTLH_INNERMOST_SHARED); + // CIR: cir.load nontemporal align(2) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: load half, ptr {{.*}}, align 2, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + h1 = __riscv_ntl_load(&h2, __RISCV_NTLH_ALL); + // CIR: cir.load nontemporal align(4) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: load float, ptr {{.*}}, align 4, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + f1 = __riscv_ntl_load(&f2); + // CIR: cir.load nontemporal align(8) {{.*}} {cir.riscv_nontemporal_domain = 2 : i32} + // LLVM: load double, ptr {{.*}}, align 8, !nontemporal [[NT]], !riscv-nontemporal-domain [[D2]] + d1 = __riscv_ntl_load(&d2, __RISCV_NTLH_INNERMOST_PRIVATE); + // CIR: cir.load nontemporal align(16) {{.*}} {cir.riscv_nontemporal_domain = 3 : i32} + // LLVM: load <4 x i32>, ptr {{.*}}, align 16, !nontemporal [[NT]], !riscv-nontemporal-domain [[D3]] + v4si1 = __riscv_ntl_load(&v4si2, __RISCV_NTLH_ALL_PRIVATE); + // CIR: cir.load nontemporal align(16) {{.*}} {cir.riscv_nontemporal_domain = 4 : i32} + // LLVM: load <8 x i16>, ptr {{.*}}, align 16, !nontemporal [[NT]], !riscv-nontemporal-domain [[D4]] + v8ss1 = __riscv_ntl_load(&v8ss2, __RISCV_NTLH_INNERMOST_SHARED); + // CIR: cir.load nontemporal align(16) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: load <16 x i8>, ptr {{.*}}, align 16, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + v16sc1 = __riscv_ntl_load(&v16sc2, __RISCV_NTLH_ALL); +} + +// CIR-LABEL: cir.func{{.*}} @ntl_store_all_sizes( +// LLVM-LABEL: @ntl_store_all_sizes( +void ntl_store_all_sizes(void) { + // CIR: cir.store nontemporal align(1) {{.*}} {cir.riscv_nontemporal_domain = 2 : i32} + // LLVM: store i8 {{.*}}, ptr {{.*}}, align 1, !nontemporal [[NT]], !riscv-nontemporal-domain [[D2]] + __riscv_ntl_store(&uc, 1, __RISCV_NTLH_INNERMOST_PRIVATE); + // CIR: cir.store nontemporal align(1) {{.*}} {cir.riscv_nontemporal_domain = 3 : i32} + // LLVM: store i8 {{.*}}, ptr {{.*}}, align 1, !nontemporal [[NT]], !riscv-nontemporal-domain [[D3]] + __riscv_ntl_store(&sc, 1, __RISCV_NTLH_ALL_PRIVATE); + // CIR: cir.store nontemporal align(2) {{.*}} {cir.riscv_nontemporal_domain = 4 : i32} + // LLVM: store i16 {{.*}}, ptr {{.*}}, align 2, !nontemporal [[NT]], !riscv-nontemporal-domain [[D4]] + __riscv_ntl_store(&us, 1, __RISCV_NTLH_INNERMOST_SHARED); + // CIR: cir.store nontemporal align(2) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: store i16 {{.*}}, ptr {{.*}}, align 2, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + __riscv_ntl_store(&ss, 1, __RISCV_NTLH_ALL); + // CIR: cir.store nontemporal align(4) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: store i32 {{.*}}, ptr {{.*}}, align 4, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + __riscv_ntl_store(&ui, 1); + // CIR: cir.store nontemporal align(4) {{.*}} {cir.riscv_nontemporal_domain = 2 : i32} + // LLVM: store i32 {{.*}}, ptr {{.*}}, align 4, !nontemporal [[NT]], !riscv-nontemporal-domain [[D2]] + __riscv_ntl_store(&si, 1, __RISCV_NTLH_INNERMOST_PRIVATE); + // CIR: cir.store nontemporal align(8) {{.*}} {cir.riscv_nontemporal_domain = 3 : i32} + // LLVM: store i64 {{.*}}, ptr {{.*}}, align 8, !nontemporal [[NT]], !riscv-nontemporal-domain [[D3]] + __riscv_ntl_store(&ull, 1, __RISCV_NTLH_ALL_PRIVATE); + // CIR: cir.store nontemporal align(8) {{.*}} {cir.riscv_nontemporal_domain = 4 : i32} + // LLVM: store i64 {{.*}}, ptr {{.*}}, align 8, !nontemporal [[NT]], !riscv-nontemporal-domain [[D4]] + __riscv_ntl_store(&sll, 1, __RISCV_NTLH_INNERMOST_SHARED); + // CIR: cir.store nontemporal align(2) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: store half {{.*}}, ptr {{.*}}, align 2, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + __riscv_ntl_store(&h1, 1.0, __RISCV_NTLH_ALL); + // CIR: cir.store nontemporal align(4) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: store float {{.*}}, ptr {{.*}}, align 4, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + __riscv_ntl_store(&f1, 1.0); + // CIR: cir.store nontemporal align(8) {{.*}} {cir.riscv_nontemporal_domain = 2 : i32} + // LLVM: store double {{.*}}, ptr {{.*}}, align 8, !nontemporal [[NT]], !riscv-nontemporal-domain [[D2]] + __riscv_ntl_store(&d1, 1.0, __RISCV_NTLH_INNERMOST_PRIVATE); + // CIR: cir.store nontemporal align(16) {{.*}} {cir.riscv_nontemporal_domain = 3 : i32} + // LLVM: store <4 x i32> {{.*}}, ptr {{.*}}, align 16, !nontemporal [[NT]], !riscv-nontemporal-domain [[D3]] + __riscv_ntl_store(&v4si1, v4si2, __RISCV_NTLH_ALL_PRIVATE); + // CIR: cir.store nontemporal align(16) {{.*}} {cir.riscv_nontemporal_domain = 4 : i32} + // LLVM: store <8 x i16> {{.*}}, ptr {{.*}}, align 16, !nontemporal [[NT]], !riscv-nontemporal-domain [[D4]] + __riscv_ntl_store(&v8ss1, v8ss2, __RISCV_NTLH_INNERMOST_SHARED); + // CIR: cir.store nontemporal align(16) {{.*}} {cir.riscv_nontemporal_domain = 5 : i32} + // LLVM: store <16 x i8> {{.*}}, ptr {{.*}}, align 16, !nontemporal [[NT]], !riscv-nontemporal-domain [[D5]] + __riscv_ntl_store(&v16sc1, v16sc2, __RISCV_NTLH_ALL); +} + +// LLVM-DAG: [[NT]] = !{i32 1} +// LLVM-DAG: [[D2]] = !{i32 2} +// LLVM-DAG: [[D3]] = !{i32 3} +// LLVM-DAG: [[D4]] = !{i32 4} +// LLVM-DAG: [[D5]] = !{i32 5} `````````` </details> https://github.com/llvm/llvm-project/pull/205468 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
