10#include "mlir/IR/Attributes.h"
11#include "mlir/IR/BuiltinAttributeInterfaces.h"
12#include "mlir/IR/IRMapping.h"
13#include "mlir/IR/Location.h"
14#include "mlir/IR/Value.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/ADT/TypeSwitch.h"
34#include "llvm/IR/Instructions.h"
35#include "llvm/Support/ErrorHandling.h"
36#include "llvm/Support/MemoryBuffer.h"
37#include "llvm/Support/Path.h"
38#include "llvm/Support/VirtualFileSystem.h"
47#define GEN_PASS_DEF_LOWERINGPREPARE
48#include "clang/CIR/Dialect/Passes.h.inc"
52 SmallString<128> fileName;
54 if (mlirModule.getSymName())
55 fileName = llvm::sys::path::filename(mlirModule.getSymName()->str());
60 for (
size_t i = 0; i < fileName.size(); ++i) {
71struct LoweringPreparePass
72 :
public impl::LoweringPrepareBase<LoweringPreparePass> {
73 LoweringPreparePass() =
default;
83 LoweringPreparePass(
const LoweringPreparePass &other)
84 : impl::LoweringPrepareBase<LoweringPreparePass>(other) {}
86 void runOnOperation()
override;
88 void runOnOp(mlir::Operation *op);
89 void lowerCastOp(cir::CastOp op);
90 void lowerComplexConjOp(cir::ComplexConjOp op);
91 void lowerComplexDivOp(cir::ComplexDivOp op);
92 void lowerComplexMulOp(cir::ComplexMulOp op);
93 void lowerGetGlobalOp(cir::GetGlobalOp op);
94 void lowerGlobalOp(cir::GlobalOp op);
95 void lowerThreeWayCmpOp(cir::CmpThreeWayOp op);
96 void lowerArrayDtor(cir::ArrayDtor op);
97 void lowerArrayCtor(cir::ArrayCtor op);
98 void lowerTrivialCopyCall(cir::CallOp op);
99 void lowerStoreOfConstAggregate(cir::StoreOp op);
100 void lowerLocalInitOp(cir::LocalInitOp op);
105 cir::FuncOp getCalledFunction(cir::CallOp callOp);
114 cir::GlobalOp getOrCreateConstAggregateGlobal(CIRBaseBuilderTy &builder,
116 llvm::StringRef baseName,
118 mlir::TypedAttr constant);
121 cir::FuncOp buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op);
124 void defineGlobalThreadLocalWrapper(cir::GlobalOp op, cir::FuncOp initAlias,
125 bool isVarDefinition);
127 cir::FuncOp defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
128 cir::FuncOp aliasee);
130 cir::FuncOp getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
136 cir::IfOp buildGlobalTlsGuardCheck(CIRBaseBuilderTy &builder,
137 mlir::Location loc, cir::GlobalOp guard);
139 cir::FuncOp getOrCreateDtorFunc(CIRBaseBuilderTy &builder, cir::GlobalOp op,
140 mlir::Region &dtorRegion,
141 cir::CallOp &dtorCall);
144 void buildCXXGlobalInitFunc();
147 void buildCXXGlobalTlsFunc();
150 void buildGlobalCtorDtorList();
152 cir::FuncOp buildRuntimeFunction(
153 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
155 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage);
157 cir::GlobalOp getOrCreateRuntimeVariable(
158 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
160 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage,
161 cir::VisibilityKind visibility = cir::VisibilityKind::Default);
167 llvm::StringMap<FuncOp> cudaKernelMap;
168 llvm::SmallVector<std::pair<cir::GlobalOp, cir::CUDAVarRegistrationInfoAttr>>
173 void buildCUDAModuleCtor();
174 std::optional<FuncOp> buildCUDAModuleDtor();
175 std::optional<FuncOp> buildHIPModuleDtor();
176 std::optional<FuncOp> buildCUDARegisterGlobals();
177 void buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
178 FuncOp regGlobalFunc);
179 void buildCUDARegisterGlobalFunctions(cir::CIRBaseBuilderTy &builder,
180 FuncOp regGlobalFunc);
183 void handleStaticLocal(cir::GlobalOp globalOp, cir::LocalInitOp localInitOp);
192 cir::FuncOp getTlsInitFn();
195 cir::GlobalOp createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
199 cir::GlobalOp createGuardGlobalOp(CIRBaseBuilderTy &builder,
200 mlir::Location loc, llvm::StringRef name,
201 cir::IntType guardTy,
202 cir::GlobalLinkageKind linkage);
205 cir::GlobalOp getStaticLocalDeclGuardAddress(llvm::StringRef globalSymName) {
206 auto it = staticLocalDeclGuardMap.find(globalSymName);
207 if (it != staticLocalDeclGuardMap.end())
213 void setStaticLocalDeclGuardAddress(llvm::StringRef globalSymName,
214 cir::GlobalOp guard) {
215 staticLocalDeclGuardMap[globalSymName] = guard;
219 cir::GlobalOp getOrCreateStaticLocalDeclGuardAddress(
220 CIRBaseBuilderTy &builder, cir::GlobalOp globalOp, StringRef guardName,
221 bool isLocalVarDecl,
bool useInt8GuardVariable) {
223 cir::CIRDataLayout dataLayout(mlirModule);
224 cir::IntType guardTy;
225 clang::CharUnits guardAlignment;
228 if (useInt8GuardVariable) {
229 guardTy = cir::IntType::get(&getContext(), 8,
true);
231 }
else if (useARMGuardVarABI()) {
233 const unsigned sizeTypeSize =
234 astCtx->getTypeSize(astCtx->getSignedSizeType());
236 cir::IntType::get(&getContext(), sizeTypeSize,
true);
240 guardTy = cir::IntType::get(&getContext(), 64,
true);
244 assert(guardTy && guardAlignment.
getQuantity() != 0);
246 llvm::StringRef globalSymName = globalOp.getSymName();
247 cir::GlobalOp guard = getStaticLocalDeclGuardAddress(globalSymName);
250 guard = createGuardGlobalOp(builder, globalOp->getLoc(), guardName,
251 guardTy, globalOp.getLinkage());
252 guard.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
253 guard.setDSOLocal(globalOp.getDsoLocal());
254 guard.setAlignment(guardAlignment.
getAsAlign().value());
255 guard.setTlsModel(globalOp.getTlsModel());
261 bool hasComdat = globalOp.getComdat();
262 const llvm::Triple &triple = astCtx->getTargetInfo().getTriple();
265 if (!isLocalVarDecl && hasComdat &&
266 (triple.isOSBinFormatELF() || triple.isOSBinFormatWasm())) {
268 guard.setComdat(
true);
269 }
else if (hasComdat && globalOp.isWeakForLinker()) {
270 guard.setComdat(
true);
273 setStaticLocalDeclGuardAddress(globalSymName, guard);
282 clang::ASTContext *astCtx;
285 mlir::ModuleOp mlirModule;
305 mlir::SymbolTableCollection symbolTables;
308 llvm::StringMap<uint32_t> dynamicInitializerNames;
309 llvm::SmallVector<cir::FuncOp> dynamicInitializers;
310 llvm::SmallVector<cir::FuncOp> globalThreadLocalInitializers;
311 llvm::StringMap<cir::FuncOp> threadLocalWrappers;
312 llvm::StringMap<cir::FuncOp> threadLocalInitAliases;
315 llvm::StringMap<cir::GlobalOp> staticLocalDeclGuardMap;
317 llvm::StringMap<llvm::SmallVector<cir::GlobalOp, 1>> constAggregateGlobals;
320 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList;
322 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalDtorList;
326 bool useARMGuardVarABI()
const {
327 switch (astCtx->getCXXABIKind()) {
328 case clang::TargetCXXABI::GenericARM:
329 case clang::TargetCXXABI::iOS:
330 case clang::TargetCXXABI::WatchOS:
331 case clang::TargetCXXABI::GenericAArch64:
332 case clang::TargetCXXABI::WebAssembly:
339 void emitGlobalGuardedDtorRegion(CIRBaseBuilderTy &builder,
340 cir::GlobalOp global,
341 mlir::Region &dtorRegion,
bool tls,
342 mlir::Block &entryBB) {
344 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
345 cir::GlobalOp handle = getOrCreateRuntimeVariable(
346 builder,
"__dso_handle", global.getLoc(), builder.getI8Type(),
347 cir::GlobalLinkageKind::ExternalLinkage, cir::VisibilityKind::Hidden);
353 cir::CallOp dtorCall;
354 cir::FuncOp dtorFunc =
355 getOrCreateDtorFunc(builder, global, dtorRegion, dtorCall);
360 cir::PointerType voidFnPtrTy = builder.
getVoidFnPtrTy({voidPtrTy});
361 cir::PointerType handlePtrTy = builder.
getPointerTo(handle.getSymType());
364 cir::FuncType::get({voidFnPtrTy, voidPtrTy, handlePtrTy}, intTy);
366 llvm::StringLiteral nameAtExit =
"__cxa_atexit";
368 nameAtExit = astCtx->getTargetInfo().getTriple().isOSDarwin()
369 ? llvm::StringLiteral(
"_tlv_atexit")
370 : llvm::StringLiteral(
"__cxa_thread_atexit");
372 cir::FuncOp fnAtExit = buildRuntimeFunction(builder, nameAtExit,
373 global.getLoc(), fnAtExitType);
377 builder.setInsertionPointAfter(dtorCall);
379 auto dtorPtrTy = cir::PointerType::get(dtorFunc.getFunctionType());
380 args[0] = cir::GetGlobalOp::create(builder, dtorCall.getLoc(), dtorPtrTy,
381 dtorFunc.getSymName());
382 args[0] = cir::CastOp::create(builder, dtorCall.getLoc(), voidFnPtrTy,
383 cir::CastKind::bitcast, args[0]);
385 cir::CastOp::create(builder, dtorCall.getLoc(), voidPtrTy,
386 cir::CastKind::bitcast, dtorCall.getArgOperand(0));
387 args[2] = cir::GetGlobalOp::create(builder, handle.getLoc(), handlePtrTy,
388 handle.getSymName());
389 builder.
createCallOp(dtorCall.getLoc(), fnAtExit, args);
391 mlir::Block &dtorBlock = dtorRegion.front();
392 entryBB.getOperations().splice(entryBB.end(), dtorBlock.getOperations(),
394 std::prev(dtorBlock.end()));
397 builder.setInsertionPointToEnd(&entryBB);
403 void emitCXXGuardedInitIf(CIRBaseBuilderTy &builder, cir::GlobalOp globalOp,
404 mlir::Region &ctorRegion, mlir::Region &dtorRegion,
405 cir::ASTVarDeclInterface varDecl,
406 mlir::Value guardPtr, cir::PointerType guardPtrTy,
408 auto loc = globalOp->getLoc();
428 mlir::Block *insertBlock = builder.getInsertionBlock();
429 if (!ctorRegion.empty()) {
430 assert(ctorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
432 mlir::Block &block = ctorRegion.front();
433 insertBlock->getOperations().splice(
434 insertBlock->end(), block.getOperations(), block.begin(),
435 std::prev(block.end()));
438 if (!dtorRegion.empty()) {
439 assert(dtorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
441 emitGlobalGuardedDtorRegion(builder, globalOp, dtorRegion, !threadsafe,
444 builder.setInsertionPointToEnd(insertBlock);
445 ctorRegion.getBlocks().clear();
453 mlir::Value acquireResult = acquireCall.getResult();
456 loc, mlir::cast<cir::IntType>(acquireResult.getType()), 0);
457 auto shouldInit = builder.
createCompare(loc, cir::CmpOpKind::ne,
458 acquireResult, acquireZero);
463 cir::IfOp::create(builder, loc, shouldInit,
false,
464 [](mlir::OpBuilder &, mlir::Location) {});
465 mlir::OpBuilder::InsertionGuard insertGuard(builder);
466 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
480 mlir::ValueRange{guardPtr});
483 }
else if (!
varDecl.isLocalVarDecl()) {
489 globalOp->emitError(
"NYI: non-threadsafe init for non-local variables");
504 void setASTContext(clang::ASTContext *c) { astCtx = c; }
509cir::GlobalOp LoweringPreparePass::getOrCreateRuntimeVariable(
510 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
511 mlir::Type type, cir::GlobalLinkageKind linkage,
512 cir::VisibilityKind visibility) {
513 cir::GlobalOp g = dyn_cast_or_null<cir::GlobalOp>(
514 mlir::SymbolTable::lookupNearestSymbolFrom(
515 mlirModule, mlir::StringAttr::get(mlirModule->getContext(), name)));
517 g = cir::GlobalOp::create(builder, loc, name, type);
519 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
520 mlir::SymbolTable::setSymbolVisibility(
521 g, mlir::SymbolTable::Visibility::Private);
522 g.setGlobalVisibility(visibility);
527cir::FuncOp LoweringPreparePass::buildRuntimeFunction(
528 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
529 cir::FuncType type, cir::GlobalLinkageKind linkage) {
530 cir::FuncOp f = dyn_cast_or_null<FuncOp>(SymbolTable::lookupNearestSymbolFrom(
531 mlirModule, StringAttr::get(mlirModule->getContext(), name)));
533 f = cir::FuncOp::create(builder, loc, name, type);
535 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
536 mlir::SymbolTable::setSymbolVisibility(
537 f, mlir::SymbolTable::Visibility::Private);
547 builder.setInsertionPoint(op);
549 mlir::Value src = op.getSrc();
550 mlir::Value imag = builder.
getNullValue(src.getType(), op.getLoc());
556 cir::CastKind elemToBoolKind) {
558 builder.setInsertionPoint(op);
560 mlir::Value src = op.getSrc();
561 if (!mlir::isa<cir::BoolType>(op.getType()))
568 cir::BoolType boolTy = builder.
getBoolTy();
569 mlir::Value srcRealToBool =
570 builder.
createCast(op.getLoc(), elemToBoolKind, srcReal, boolTy);
571 mlir::Value srcImagToBool =
572 builder.
createCast(op.getLoc(), elemToBoolKind, srcImag, boolTy);
573 return builder.
createLogicalOr(op.getLoc(), srcRealToBool, srcImagToBool);
578 cir::CastKind scalarCastKind) {
580 builder.setInsertionPoint(op);
582 mlir::Value src = op.getSrc();
583 auto dstComplexElemTy =
584 mlir::cast<cir::ComplexType>(op.getType()).getElementType();
589 mlir::Value dstReal = builder.
createCast(op.getLoc(), scalarCastKind, srcReal,
591 mlir::Value dstImag = builder.
createCast(op.getLoc(), scalarCastKind, srcImag,
596void LoweringPreparePass::lowerCastOp(cir::CastOp op) {
597 mlir::MLIRContext &ctx = getContext();
598 mlir::Value loweredValue = [&]() -> mlir::Value {
599 switch (op.getKind()) {
600 case cir::CastKind::float_to_complex:
601 case cir::CastKind::int_to_complex:
603 case cir::CastKind::float_complex_to_real:
604 case cir::CastKind::int_complex_to_real:
606 case cir::CastKind::float_complex_to_bool:
608 case cir::CastKind::int_complex_to_bool:
610 case cir::CastKind::float_complex:
612 case cir::CastKind::float_complex_to_int_complex:
614 case cir::CastKind::int_complex:
616 case cir::CastKind::int_complex_to_float_complex:
624 op.replaceAllUsesWith(loweredValue);
631 llvm::StringRef (*libFuncNameGetter)(llvm::APFloat::Semantics),
632 mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal,
633 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag) {
634 cir::FPTypeInterface elementTy =
635 mlir::cast<cir::FPTypeInterface>(ty.getElementType());
637 llvm::StringRef libFuncName = libFuncNameGetter(
638 llvm::APFloat::SemanticsToEnum(elementTy.getFloatSemantics()));
641 cir::FuncType libFuncTy = cir::FuncType::get(libFuncInputTypes, ty);
647 mlir::OpBuilder::InsertionGuard ipGuard{builder};
648 builder.setInsertionPointToStart(pass.mlirModule.getBody());
649 libFunc = pass.buildRuntimeFunction(builder, libFuncName, loc, libFuncTy);
653 builder.
createCallOp(loc, libFunc, {lhsReal, lhsImag, rhsReal, rhsImag});
654 return call.getResult();
657static llvm::StringRef
660 case llvm::APFloat::S_IEEEhalf:
662 case llvm::APFloat::S_IEEEsingle:
664 case llvm::APFloat::S_IEEEdouble:
666 case llvm::APFloat::S_PPCDoubleDouble:
668 case llvm::APFloat::S_x87DoubleExtended:
670 case llvm::APFloat::S_IEEEquad:
673 llvm_unreachable(
"unsupported floating point type");
679 mlir::Value lhsReal, mlir::Value lhsImag,
680 mlir::Value rhsReal, mlir::Value rhsImag) {
682 mlir::Value &a = lhsReal;
683 mlir::Value &b = lhsImag;
684 mlir::Value &c = rhsReal;
685 mlir::Value &d = rhsImag;
689 bool isFP = cir::isFPOrVectorOfFPType(a.getType());
690 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
693 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
696 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
699 auto div = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
703 mlir::Value ac = mul(loc, a, c);
704 mlir::Value bd = mul(loc, b, d);
705 mlir::Value cc = mul(loc, c, c);
706 mlir::Value dd = mul(loc, d, d);
707 mlir::Value acbd = add(loc, ac, bd);
708 mlir::Value ccdd = add(loc, cc, dd);
709 mlir::Value resultReal = div(loc, acbd, ccdd);
711 mlir::Value bc = mul(loc, b, c);
712 mlir::Value ad = mul(loc, a, d);
713 mlir::Value bcad = sub(loc, bc, ad);
714 mlir::Value resultImag = div(loc, bcad, ccdd);
720 mlir::Value lhsReal, mlir::Value lhsImag,
721 mlir::Value rhsReal, mlir::Value rhsImag) {
742 mlir::Value &a = lhsReal;
743 mlir::Value &b = lhsImag;
744 mlir::Value &c = rhsReal;
745 mlir::Value &d = rhsImag;
748 assert(cir::isFPOrVectorOfFPType(a.getType()) &&
749 "range-reduction complex divide expects floating-point operands");
751 auto trueBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
752 mlir::Value r = builder.
createFDiv(loc, d, c);
753 mlir::Value rd = builder.
createFMul(loc, r, d);
754 mlir::Value tmp = builder.
createFAdd(loc, c, rd);
756 mlir::Value br = builder.
createFMul(loc, b, r);
757 mlir::Value abr = builder.
createFAdd(loc, a, br);
758 mlir::Value e = builder.
createFDiv(loc, abr, tmp);
760 mlir::Value ar = builder.
createFMul(loc, a, r);
761 mlir::Value bar = builder.
createFSub(loc, b, ar);
762 mlir::Value f = builder.
createFDiv(loc, bar, tmp);
768 auto falseBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
769 mlir::Value r = builder.
createFDiv(loc, c, d);
770 mlir::Value rc = builder.
createFMul(loc, r, c);
771 mlir::Value tmp = builder.
createFAdd(loc, d, rc);
773 mlir::Value ar = builder.
createFMul(loc, a, r);
774 mlir::Value arb = builder.
createFAdd(loc, ar, b);
775 mlir::Value e = builder.
createFDiv(loc, arb, tmp);
777 mlir::Value br = builder.
createFMul(loc, b, r);
778 mlir::Value bra = builder.
createFSub(loc, br, a);
779 mlir::Value f = builder.
createFDiv(loc, bra, tmp);
785 auto cFabs = cir::FAbsOp::create(builder, loc, c);
786 auto dFabs = cir::FAbsOp::create(builder, loc, d);
787 cir::CmpOp cmpResult =
788 builder.
createCompare(loc, cir::CmpOpKind::ge, cFabs, dFabs);
789 auto ternary = cir::TernaryOp::create(builder, loc, cmpResult,
790 trueBranchBuilder, falseBranchBuilder);
792 return ternary.getResult();
799 auto getHigherPrecisionFPType = [&context](mlir::Type type) -> mlir::Type {
800 if (mlir::isa<cir::FP16Type>(type))
801 return cir::SingleType::get(&context);
803 if (mlir::isa<cir::SingleType>(type) || mlir::isa<cir::BF16Type>(type))
804 return cir::DoubleType::get(&context);
806 if (mlir::isa<cir::DoubleType>(type))
807 return cir::LongDoubleType::get(&context, type);
812 auto getFloatTypeSemantics =
813 [&cc](mlir::Type type) ->
const llvm::fltSemantics & {
815 if (mlir::isa<cir::FP16Type>(type))
818 if (mlir::isa<cir::BF16Type>(type))
821 if (mlir::isa<cir::SingleType>(type))
824 if (mlir::isa<cir::DoubleType>(type))
827 if (mlir::isa<cir::LongDoubleType>(type)) {
829 llvm_unreachable(
"NYI Float type semantics with OpenMP");
833 if (mlir::isa<cir::FP128Type>(type)) {
835 llvm_unreachable(
"NYI Float type semantics with OpenMP");
839 llvm_unreachable(
"Unsupported float type semantics");
842 const mlir::Type higherElementType = getHigherPrecisionFPType(elementType);
843 const llvm::fltSemantics &elementTypeSemantics =
844 getFloatTypeSemantics(elementType);
845 const llvm::fltSemantics &higherElementTypeSemantics =
846 getFloatTypeSemantics(higherElementType);
855 if (llvm::APFloat::semanticsMaxExponent(elementTypeSemantics) * 2 + 1 <=
856 llvm::APFloat::semanticsMaxExponent(higherElementTypeSemantics)) {
857 return higherElementType;
867 mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal,
868 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag,
870 cir::ComplexType complexTy = op.getType();
871 if (mlir::isa<cir::FPTypeInterface>(complexTy.getElementType())) {
872 cir::ComplexRangeKind range = op.getRange();
873 if (range == cir::ComplexRangeKind::Improved)
877 if (range == cir::ComplexRangeKind::Full)
879 loc, complexTy, lhsReal, lhsImag, rhsReal,
882 if (range == cir::ComplexRangeKind::Promoted) {
883 mlir::Type originalElementType = complexTy.getElementType();
884 mlir::Type higherPrecisionElementType =
886 originalElementType);
888 if (!higherPrecisionElementType)
892 cir::CastKind floatingCastKind = cir::CastKind::floating;
893 lhsReal = builder.
createCast(floatingCastKind, lhsReal,
894 higherPrecisionElementType);
895 lhsImag = builder.
createCast(floatingCastKind, lhsImag,
896 higherPrecisionElementType);
897 rhsReal = builder.
createCast(floatingCastKind, rhsReal,
898 higherPrecisionElementType);
899 rhsImag = builder.
createCast(floatingCastKind, rhsImag,
900 higherPrecisionElementType);
903 builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
908 mlir::Value finalReal =
909 builder.
createCast(floatingCastKind, resultReal, originalElementType);
910 mlir::Value finalImag =
911 builder.
createCast(floatingCastKind, resultImag, originalElementType);
920void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) {
921 cir::CIRBaseBuilderTy builder(getContext());
922 builder.setInsertionPointAfter(op);
923 mlir::Location loc = op.getLoc();
924 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
925 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
931 mlir::Value loweredResult =
933 rhsImag, getContext(), *astCtx);
934 op.replaceAllUsesWith(loweredResult);
938static llvm::StringRef
941 case llvm::APFloat::S_IEEEhalf:
943 case llvm::APFloat::S_IEEEsingle:
945 case llvm::APFloat::S_IEEEdouble:
947 case llvm::APFloat::S_PPCDoubleDouble:
949 case llvm::APFloat::S_x87DoubleExtended:
951 case llvm::APFloat::S_IEEEquad:
954 llvm_unreachable(
"unsupported floating point type");
960 mlir::Location loc, cir::ComplexMulOp op,
961 mlir::Value lhsReal, mlir::Value lhsImag,
962 mlir::Value rhsReal, mlir::Value rhsImag) {
964 bool isFP = cir::isFPOrVectorOfFPType(lhsReal.getType());
965 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
968 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
971 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
975 mlir::Value resultRealLhs = mul(loc, lhsReal, rhsReal);
976 mlir::Value resultRealRhs = mul(loc, lhsImag, rhsImag);
977 mlir::Value resultImagLhs = mul(loc, lhsReal, rhsImag);
978 mlir::Value resultImagRhs = mul(loc, lhsImag, rhsReal);
979 mlir::Value resultReal = sub(loc, resultRealLhs, resultRealRhs);
980 mlir::Value resultImag = add(loc, resultImagLhs, resultImagRhs);
981 mlir::Value algebraicResult =
984 cir::ComplexType complexTy = op.getType();
985 cir::ComplexRangeKind rangeKind = op.getRange();
986 if (mlir::isa<cir::IntType>(complexTy.getElementType()) ||
987 rangeKind == cir::ComplexRangeKind::Basic ||
988 rangeKind == cir::ComplexRangeKind::Improved ||
989 rangeKind == cir::ComplexRangeKind::Promoted)
990 return algebraicResult;
997 mlir::Value resultRealIsNaN = builder.
createIsNaN(loc, resultReal);
998 mlir::Value resultImagIsNaN = builder.
createIsNaN(loc, resultImag);
999 mlir::Value resultRealAndImagAreNaN =
1002 return cir::TernaryOp::create(
1003 builder, loc, resultRealAndImagAreNaN,
1004 [&](mlir::OpBuilder &, mlir::Location) {
1007 lhsReal, lhsImag, rhsReal, rhsImag);
1010 [&](mlir::OpBuilder &, mlir::Location) {
1016void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
1017 cir::CIRBaseBuilderTy builder(getContext());
1018 builder.setInsertionPointAfter(op);
1019 mlir::Location loc = op.getLoc();
1020 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
1021 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
1026 mlir::Value loweredResult =
lowerComplexMul(*
this, builder, loc, op, lhsReal,
1027 lhsImag, rhsReal, rhsImag);
1028 op.replaceAllUsesWith(loweredResult);
1032void LoweringPreparePass::lowerComplexConjOp(cir::ComplexConjOp op) {
1033 mlir::Location loc = op.getLoc();
1034 CIRBaseBuilderTy builder(getContext());
1035 builder.setInsertionPointAfter(op);
1037 mlir::Value operand = op.getOperand();
1042 const bool isFP = cir::isFPOrVectorOfFPType(operandReal.getType());
1043 mlir::Value resultImag = isFP ? builder.
createFNeg(loc, operandImag)
1046 mlir::Value result =
1048 op->replaceAllUsesWith(mlir::ValueRange{result});
1052cir::FuncOp LoweringPreparePass::getOrCreateDtorFunc(CIRBaseBuilderTy &builder,
1054 mlir::Region &dtorRegion,
1055 cir::CallOp &dtorCall) {
1056 mlir::OpBuilder::InsertionGuard guard(builder);
1059 cir::VoidType voidTy = builder.
getVoidTy();
1060 auto voidPtrTy = cir::PointerType::get(voidTy);
1063 mlir::Block &dtorBlock = dtorRegion.front();
1067 auto opIt = dtorBlock.getOperations().begin();
1068 cir::GetGlobalOp ggop = mlir::cast<cir::GetGlobalOp>(*opIt);
1079 if (dtorBlock.getOperations().size() == 3) {
1080 auto callOp = mlir::dyn_cast<cir::CallOp>(&*(++opIt));
1081 auto yieldOp = mlir::dyn_cast<cir::YieldOp>(&*(++opIt));
1082 if (yieldOp && callOp && callOp.getNumOperands() == 1 &&
1083 callOp.getArgOperand(0) == ggop) {
1085 return getCalledFunction(callOp);
1092 builder.setInsertionPointAfter(op);
1093 SmallString<256> fnName(
"__cxx_global_array_dtor");
1094 uint32_t cnt = dynamicInitializerNames[fnName]++;
1096 fnName +=
"." + std::to_string(cnt);
1099 auto fnType = cir::FuncType::get({voidPtrTy}, voidTy);
1100 cir::FuncOp dtorFunc =
1101 buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1102 cir::GlobalLinkageKind::InternalLinkage);
1104 SmallVector<mlir::NamedAttribute> paramAttrs;
1105 paramAttrs.push_back(
1106 builder.getNamedAttr(
"llvm.noundef", builder.getUnitAttr()));
1107 SmallVector<mlir::Attribute> argAttrDicts;
1108 argAttrDicts.push_back(
1109 mlir::DictionaryAttr::get(builder.getContext(), paramAttrs));
1110 dtorFunc.setArgAttrsAttr(
1111 mlir::ArrayAttr::get(builder.getContext(), argAttrDicts));
1113 mlir::Block *entryBB = dtorFunc.addEntryBlock();
1116 entryBB->getOperations().splice(entryBB->begin(), dtorBlock.getOperations(),
1117 dtorBlock.begin(), dtorBlock.end());
1120 cir::GetGlobalOp dtorGGop =
1121 mlir::cast<cir::GetGlobalOp>(entryBB->getOperations().front());
1122 builder.setInsertionPointToStart(&dtorBlock);
1123 builder.clone(*dtorGGop.getOperation());
1127 mlir::Value dtorArg = entryBB->getArgument(0);
1128 dtorGGop.replaceAllUsesWith(dtorArg);
1132 mlir::Block &finalBlock = dtorFunc.getBody().back();
1133 auto yieldOp = cast<cir::YieldOp>(finalBlock.getTerminator());
1134 builder.setInsertionPoint(yieldOp);
1135 cir::ReturnOp::create(builder, yieldOp->getLoc());
1140 cir::GetGlobalOp origGGop =
1141 mlir::cast<cir::GetGlobalOp>(dtorBlock.getOperations().front());
1142 builder.setInsertionPointAfter(origGGop);
1143 mlir::Value ggopResult = origGGop.getResult();
1144 dtorCall = builder.
createCallOp(op.getLoc(), dtorFunc, ggopResult);
1147 auto finalYield = cir::YieldOp::create(builder, op.getLoc());
1150 dtorBlock.getOperations().erase(std::next(mlir::Block::iterator(finalYield)),
1152 dtorRegion.getBlocks().erase(std::next(dtorRegion.begin()), dtorRegion.end());
1158LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op) {
1161 SmallString<256> fnName(
"__cxx_global_var_init");
1163 uint32_t cnt = dynamicInitializerNames[fnName]++;
1165 fnName +=
"." + std::to_string(cnt);
1168 CIRBaseBuilderTy builder(getContext());
1169 builder.setInsertionPointAfter(op);
1170 cir::VoidType voidTy = builder.
getVoidTy();
1171 auto fnType = cir::FuncType::get({}, voidTy);
1172 FuncOp f = buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1173 cir::GlobalLinkageKind::InternalLinkage);
1181 mlir::Block *entryBB = f.addEntryBlock();
1182 builder.setInsertionPointToStart(entryBB);
1186 bool needsTlsGuard = op.getDynTlsRefs() && op.getDynTlsRefs()->getGuardName();
1188 if (needsTlsGuard) {
1189 guardIf = buildGlobalTlsGuardCheck(
1190 builder, op.getLoc(),
1191 getOrCreateStaticLocalDeclGuardAddress(
1192 builder, op, op.getDynTlsRefs()->getGuardName().getValue(),
1194 op.hasInternalLinkage()));
1195 builder.setInsertionPointToEnd(&guardIf.getThenRegion().front());
1198 if (!op.getCtorRegion().empty()) {
1199 mlir::Block &block = op.getCtorRegion().front();
1200 mlir::Block *insertBlock = builder.getBlock();
1201 insertBlock->getOperations().splice(insertBlock->end(),
1202 block.getOperations(), block.begin(),
1203 std::prev(block.end()));
1207 mlir::Region &dtorRegion = op.getDtorRegion();
1208 if (!dtorRegion.empty()) {
1211 emitGlobalGuardedDtorRegion(builder, op, dtorRegion,
1212 op.getTlsModel().has_value(),
1213 *builder.getBlock());
1217 if (needsTlsGuard) {
1218 builder.setInsertionPointToEnd(&guardIf.getThenRegion().back());
1219 cir::YieldOp::create(builder, op.getLoc());
1223 builder.setInsertionPointToEnd(entryBB);
1224 mlir::Operation *yieldOp =
nullptr;
1225 if (!op.getCtorRegion().empty()) {
1226 mlir::Block &block = op.getCtorRegion().front();
1227 yieldOp = &block.getOperations().back();
1229 assert(!dtorRegion.empty());
1230 mlir::Block &block = dtorRegion.front();
1231 yieldOp = &block.getOperations().back();
1234 assert(isa<cir::YieldOp>(*yieldOp));
1235 cir::ReturnOp::create(builder, yieldOp->getLoc());
1240LoweringPreparePass::getGuardAcquireFn(cir::PointerType guardPtrTy) {
1242 CIRBaseBuilderTy builder(getContext());
1243 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1244 builder.setInsertionPointToStart(mlirModule.getBody());
1245 mlir::Location loc = mlirModule.getLoc();
1246 cir::IntType intTy = cir::IntType::get(&getContext(), 32,
true);
1247 auto fnType = cir::FuncType::get({guardPtrTy}, intTy);
1248 return buildRuntimeFunction(builder,
"__cxa_guard_acquire", loc, fnType);
1252LoweringPreparePass::getGuardReleaseFn(cir::PointerType guardPtrTy) {
1254 CIRBaseBuilderTy builder(getContext());
1255 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1256 builder.setInsertionPointToStart(mlirModule.getBody());
1257 mlir::Location loc = mlirModule.getLoc();
1258 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1259 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1260 return buildRuntimeFunction(builder,
"__cxa_guard_release", loc, fnType);
1263cir::FuncOp LoweringPreparePass::getTlsInitFn() {
1265 CIRBaseBuilderTy builder(getContext());
1266 mlir::OpBuilder::InsertionGuard _{builder};
1267 builder.setInsertionPointToStart(mlirModule.getBody());
1268 mlir::Location loc = mlirModule.getLoc();
1270 return buildRuntimeFunction(builder,
"__tls_init", loc, fnType,
1271 cir::GlobalLinkageKind::InternalLinkage);
1274cir::GlobalOp LoweringPreparePass::createGuardGlobalOp(
1275 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef name,
1276 cir::IntType guardTy, cir::GlobalLinkageKind linkage) {
1277 mlir::OpBuilder::InsertionGuard guard(builder);
1278 builder.setInsertionPointToStart(mlirModule.getBody());
1279 cir::GlobalOp g = cir::GlobalOp::create(builder, loc, name, guardTy);
1281 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1282 mlir::SymbolTable::setSymbolVisibility(
1283 g, mlir::SymbolTable::Visibility::Private);
1287void LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
1288 cir::LocalInitOp localInitOp) {
1289 CIRBaseBuilderTy builder(getContext());
1291 std::optional<cir::ASTVarDeclInterface> astOption = globalOp.getAst();
1292 assert(astOption.has_value());
1293 cir::ASTVarDeclInterface
varDecl = astOption.value();
1295 builder.setInsertionPointAfter(localInitOp);
1296 mlir::Block *localInitBlock = builder.getInsertionBlock();
1299 mlir::Operation *ret = localInitBlock->getTerminator();
1303 builder.setInsertionPointAfter(localInitOp);
1307 bool nonTemplateInline =
1313 if (nonTemplateInline) {
1314 globalOp->emitError(
1315 "NYI: guarded initialization for inline namespace-scope variables");
1322 bool threadsafe = astCtx->
getLangOpts().ThreadsafeStatics &&
1323 (
varDecl.isLocalVarDecl() || nonTemplateInline) &&
1328 bool useInt8GuardVariable = !threadsafe && globalOp.hasInternalLinkage();
1331 cir::GlobalOp guard = getOrCreateStaticLocalDeclGuardAddress(
1332 builder, globalOp, globalOp.getStaticLocalGuard()->getName().getValue(),
1333 varDecl.isLocalVarDecl(), useInt8GuardVariable);
1336 localInitBlock->push_back(ret);
1340 mlir::Value guardPtr = builder.
createGetGlobal(guard, localInitOp.getTls());
1362 unsigned maxInlineWidthInBits =
1365 if (!threadsafe || maxInlineWidthInBits) {
1367 auto bytePtrTy = cir::PointerType::get(builder.
getSIntNTy(8));
1368 mlir::Value bytePtr = builder.
createBitcast(guardPtr, bytePtrTy);
1370 localInitOp.getLoc(), bytePtr, *guard.getAlignment());
1379 auto loadOp = mlir::cast<cir::LoadOp>(guardLoad.getDefiningOp());
1380 loadOp.setMemOrder(cir::MemOrder::Acquire);
1381 loadOp.setSyncScope(cir::SyncScopeKind::System);
1404 if (useARMGuardVarABI() && !useInt8GuardVariable) {
1406 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()),
1408 guardLoad = builder.
createAnd(localInitOp.getLoc(), guardLoad, one);
1413 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()), 0);
1414 auto needsInit = builder.
createCompare(localInitOp.getLoc(),
1415 cir::CmpOpKind::eq, guardLoad, zero);
1419 builder, globalOp.getLoc(), needsInit,
1420 false, [&](mlir::OpBuilder &, mlir::Location) {
1421 emitCXXGuardedInitIf(builder, globalOp, localInitOp.getCtorRegion(),
1422 localInitOp.getDtorRegion(), varDecl, guardPtr,
1423 builder.getPointerTo(guard.getSymType()),
1429 globalOp->emitError(
"NYI: guarded init without inline atomics support");
1434 builder.getInsertionBlock()->push_back(ret);
1437void LoweringPreparePass::lowerLocalInitOp(cir::LocalInitOp initOp) {
1440 if (initOp.getCtorRegion().empty() && initOp.getDtorRegion().empty()) {
1445 cir::GlobalOp globalOp = initOp.getReferencedGlobal(symbolTables);
1446 assert(globalOp &&
"No global-op found");
1448 handleStaticLocal(globalOp, initOp);
1455 return tls == cir::TLS_Model::GeneralDynamic &&
1459static cir::GlobalLinkageKind
1462 return op.getLinkage();
1467 return op.getLinkage();
1471 if (op.isDeclaration())
1472 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1473 return cir::GlobalLinkageKind::WeakODRLinkage;
1477LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
1479 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1480 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1482 mlir::StringAttr wrapperName = op.getDynTlsRefs()->getWrapperName();
1484 auto existingWrapperIter = threadLocalWrappers.find(wrapperName.getValue());
1485 if (existingWrapperIter != threadLocalWrappers.end())
1486 return existingWrapperIter->second;
1489 auto funcType = cir::FuncType::get({}, builder.
getPointerTo(op.getSymType()));
1491 cir::FuncOp::create(builder, op.getLoc(), wrapperName, funcType);
1493 cir::GlobalLinkageKind linkageKind =
1495 func.setLinkageAttr(
1496 cir::GlobalLinkageKindAttr::get(&getContext(), linkageKind));
1501 func.isWeakForLinker())
1502 func.setComdat(
true);
1504 mlir::SymbolTable::setSymbolVisibility(
1505 func, mlir::SymbolTable::Visibility::Private);
1510 op.getGlobalVisibility() == cir::VisibilityKind::Hidden)
1511 func.setGlobalVisibility(cir::VisibilityKind::Hidden);
1514 op->emitError(
"Unhandled thread wrapper attributes for CC and Nounwind");
1516 threadLocalWrappers.insert({wrapperName.getValue(), func});
1520void LoweringPreparePass::defineGlobalThreadLocalWrapper(cir::GlobalOp op,
1521 cir::FuncOp initAlias,
1522 bool isVarDefinition) {
1523 CIRBaseBuilderTy builder(getContext());
1524 cir::FuncOp wrapper = getOrCreateThreadLocalWrapper(builder, op);
1525 mlir::Block *entryBB = wrapper.addEntryBlock();
1526 builder.setInsertionPointToStart(entryBB);
1530 mlir::Location aliasLoc = initAlias.getLoc();
1531 if (!isVarDefinition) {
1533 mlir::Value funcLoad = cir::GetGlobalOp::create(
1534 builder, aliasLoc, cir::PointerType::get(initAlias.getFunctionType()),
1535 initAlias.getSymName());
1536 mlir::Value nullCheck =
1538 mlir::Value cmp = cir::CmpOp::create(
1539 builder, aliasLoc, cir::CmpOpKind::ne, funcLoad, nullCheck);
1540 cir::IfOp::create(builder, aliasLoc, cmp,
false,
1541 [&](mlir::OpBuilder &, mlir::Location loc) {
1543 cir::YieldOp::create(builder, aliasLoc);
1552 cir::ReturnOp::create(builder, op.getLoc(), {get});
1556LoweringPreparePass::defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
1557 cir::FuncOp aliasee) {
1558 CIRBaseBuilderTy builder(getContext());
1559 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1560 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1561 mlir::StringAttr aliasName = op.getDynTlsRefs()->getInitName();
1562 auto existingAliasIter = threadLocalInitAliases.find(aliasName.getValue());
1564 if (existingAliasIter != threadLocalInitAliases.end())
1565 return existingAliasIter->second;
1569 cir::FuncOp::create(builder, op.getLoc(), aliasName, funcType);
1570 alias.setLinkage(op.getLinkage());
1573 alias.setAliasee(aliasee.getSymName());
1578 alias.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1579 mlir::SymbolTable::setSymbolVisibility(
1580 alias, mlir::SymbolTable::Visibility::Private);
1583 threadLocalInitAliases.insert({aliasName.getValue(), alias});
1587void LoweringPreparePass::lowerGlobalOp(GlobalOp op) {
1589 if (op.getStaticLocalGuard())
1592 mlir::Region &ctorRegion = op.getCtorRegion();
1593 mlir::Region &dtorRegion = op.getDtorRegion();
1594 cir::FuncOp initAlias;
1596 if (!ctorRegion.empty() || !dtorRegion.empty()) {
1599 cir::FuncOp f = buildCXXGlobalVarDeclInitFunc(op);
1602 ctorRegion.getBlocks().clear();
1603 dtorRegion.getBlocks().clear();
1606 if (op.getTlsModel() == TLS_Model::GeneralDynamic &&
1607 !op.getStaticLocalGuard().has_value()) {
1619 if (op.getDynTlsRefs()->getGuardName()) {
1621 initAlias = defineGlobalThreadLocalInitAlias(op, f);
1624 initAlias = defineGlobalThreadLocalInitAlias(op, getTlsInitFn());
1628 globalThreadLocalInitializers.push_back(f);
1631 dynamicInitializers.push_back(f);
1633 }
else if (op.getTlsModel() == TLS_Model::GeneralDynamic &&
1634 op.getDynTlsRefs() && op.isDeclaration()) {
1637 initAlias = defineGlobalThreadLocalInitAlias(op, {});
1643 if (op.getTlsModel() == TLS_Model::GeneralDynamic && op.getDynTlsRefs())
1644 defineGlobalThreadLocalWrapper(op, initAlias, !op.isDeclaration());
1649void LoweringPreparePass::lowerGetGlobalOp(GetGlobalOp op) {
1652 auto globalOp = mlir::cast<cir::GlobalOp>(
1653 symbolTables.lookupNearestSymbolFrom(op, op.getNameAttr()));
1659 if (globalOp.getTlsModel() != TLS_Model::GeneralDynamic ||
1660 !globalOp.getDynTlsRefs())
1678 mlir::Operation *parentOp = op->getParentOp();
1679 if (parentOp == globalOp) {
1680 mlir::Region *ctorRegion = &globalOp.getCtorRegion();
1681 mlir::Region *dtorRegion = &globalOp.getDtorRegion();
1683 if (!ctorRegion->empty() && &*ctorRegion->op_begin() == op.getOperation())
1685 if (!dtorRegion->empty() && &*dtorRegion->op_begin() == op.getOperation())
1689 CIRBaseBuilderTy builder(getContext());
1690 cir::FuncOp wrapperFunc = getOrCreateThreadLocalWrapper(builder, globalOp);
1692 builder.setInsertionPoint(op);
1694 wrapperFunc.getLoc(),
1695 mlir::FlatSymbolRefAttr::get(wrapperFunc.getSymNameAttr()),
1696 wrapperFunc.getFunctionType().getReturnType(), {});
1697 op->replaceAllUsesWith(call);
1701void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
1702 CIRBaseBuilderTy builder(getContext());
1703 builder.setInsertionPointAfter(op);
1705 mlir::Location loc = op->getLoc();
1706 cir::CmpThreeWayInfoAttr cmpInfo = op.getInfo();
1715 mlir::Value transformedResult;
1716 if (cmpInfo.getOrdering() != CmpOrdering::Partial) {
1719 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1720 mlir::Value selectOnLt = builder.
createSelect(loc, lt, ltRes, gtRes);
1722 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1723 transformedResult = builder.
createSelect(loc, eq, eqRes, selectOnLt);
1727 loc, op.getType(), cmpInfo.getUnordered().value());
1730 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1731 mlir::Value selectOnEq = builder.
createSelect(loc, eq, eqRes, unorderedRes);
1733 builder.
createCompare(loc, CmpOpKind::gt, op.getLhs(), op.getRhs());
1734 mlir::Value selectOnGt = builder.
createSelect(loc, gt, gtRes, selectOnEq);
1736 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1737 transformedResult = builder.
createSelect(loc, lt, ltRes, selectOnGt);
1740 op.replaceAllUsesWith(transformedResult);
1744template <
typename AttributeTy>
1745static llvm::SmallVector<mlir::Attribute>
1749 for (
const auto &[name, priority] : list)
1750 attrs.push_back(AttributeTy::get(context, name, priority));
1754void LoweringPreparePass::buildGlobalCtorDtorList() {
1755 if (!globalCtorList.empty()) {
1756 llvm::SmallVector<mlir::Attribute> globalCtors =
1760 mlirModule->setAttr(cir::CIRDialect::getGlobalCtorsAttrName(),
1761 mlir::ArrayAttr::get(&getContext(), globalCtors));
1764 if (!globalDtorList.empty()) {
1765 llvm::SmallVector<mlir::Attribute> globalDtors =
1768 mlirModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(),
1769 mlir::ArrayAttr::get(&getContext(), globalDtors));
1774LoweringPreparePass::createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
1775 mlir::Location loc) {
1776 mlir::OpBuilder::InsertionGuard guard(builder);
1777 builder.setInsertionPointToStart(mlirModule.getBody());
1780 cir::IntType guardTy = builder.
getSIntNTy(8);
1781 auto g = cir::GlobalOp::create(builder, loc,
"__tls_guard", guardTy);
1782 g.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
1783 builder.getContext(), cir::GlobalLinkageKind::InternalLinkage));
1787 g.setTlsModel(TLS_Model::GeneralDynamic);
1788 g.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
1792cir::IfOp LoweringPreparePass::buildGlobalTlsGuardCheck(
1793 CIRBaseBuilderTy &builder, mlir::Location loc, cir::GlobalOp guard) {
1795 mlir::Value getGuardValue = getGuard;
1800 if (guard.getSymType() != builder.
getSIntNTy(8))
1802 getGuard, cir::PointerType::get(builder.
getSIntNTy(8)));
1804 mlir::Value guardLoad =
1808 builder.
createCompare(loc, cir::CmpOpKind::eq, guardLoad, zero);
1809 return cir::IfOp::create(
1811 false, [&](mlir::OpBuilder &, mlir::Location loc) {
1815 loc, builder.
getConstantInt(loc, guard.getSymType(), 1), getGuard);
1819void LoweringPreparePass::buildCXXGlobalTlsFunc() {
1820 if (globalThreadLocalInitializers.empty())
1826 cir::FuncOp tlsInit = getTlsInitFn();
1827 mlir::Location loc = tlsInit.getLoc();
1828 CIRBaseBuilderTy builder(getContext());
1829 mlir::Block *entryBB = tlsInit.addEntryBlock();
1830 builder.setInsertionPointToStart(entryBB);
1832 cir::IfOp ifOperation = buildGlobalTlsGuardCheck(
1833 builder, loc, createGlobalThreadLocalGuard(builder, loc));
1836 builder.setInsertionPointToEnd(&ifOperation.getThenRegion().front());
1837 for (cir::FuncOp initFunc : globalThreadLocalInitializers)
1839 cir::YieldOp::create(builder, loc);
1841 builder.setInsertionPointAfter(ifOperation);
1842 cir::ReturnOp::create(builder, loc);
1845void LoweringPreparePass::buildCXXGlobalInitFunc() {
1846 if (dynamicInitializers.empty())
1853 SmallString<256> fnName;
1854 cir::GlobalLinkageKind linkage;
1862 llvm::raw_svector_ostream
out(fnName);
1863 std::unique_ptr<clang::MangleContext> mangleCtx(
1865 cast<clang::ItaniumMangleContext>(*mangleCtx)
1867 linkage = cir::GlobalLinkageKind::ExternalLinkage;
1869 fnName +=
"_GLOBAL__sub_I_";
1871 linkage = cir::GlobalLinkageKind::InternalLinkage;
1874 CIRBaseBuilderTy builder(getContext());
1875 builder.setInsertionPointToEnd(&mlirModule.getBodyRegion().back());
1876 auto fnType = cir::FuncType::get({}, builder.
getVoidTy());
1877 cir::FuncOp f = buildRuntimeFunction(builder, fnName, mlirModule.getLoc(),
1879 builder.setInsertionPointToStart(f.addEntryBlock());
1880 for (cir::FuncOp &f : dynamicInitializers)
1884 globalCtorList.emplace_back(fnName,
1885 cir::GlobalCtorAttr::getDefaultPriority());
1887 cir::ReturnOp::create(builder, f.getLoc());
1896 mlir::Operation *op, mlir::Type eltTy,
1898 mlir::Value numElements,
1899 uint64_t arrayLen,
bool isCtor) {
1900 mlir::Location loc = op->getLoc();
1901 bool isDynamic = numElements !=
nullptr;
1905 const unsigned sizeTypeSize =
1911 mlir::Value begin, end;
1914 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, numElements);
1916 mlir::Value endOffsetVal =
1918 begin = cir::CastOp::create(builder, loc, eltTy,
1919 cir::CastKind::array_to_ptrdecay, addr);
1920 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
1923 mlir::Value start = isCtor ? begin : end;
1924 mlir::Value stop = isCtor ? end : begin;
1930 mlir::Value guardCond;
1933 guardCond = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
1939 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, start, stop);
1941 ifOp = cir::IfOp::create(builder, loc, guardCond,
1943 [&](mlir::OpBuilder &, mlir::Location) {});
1944 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1947 mlir::Value tmpAddr =
1952 mlir::Block *bodyBlock = &op->getRegion(0).front();
1957 auto cloneRegionBodyInto = [&](mlir::Block *srcBlock,
1958 mlir::Value replacement) {
1959 mlir::IRMapping map;
1960 map.map(srcBlock->getArgument(0), replacement);
1961 for (mlir::Operation ®ionOp : *srcBlock) {
1962 if (!mlir::isa<cir::YieldOp>(®ionOp))
1963 builder.clone(regionOp, map);
1967 mlir::Block *partialDtorBlock =
nullptr;
1968 if (
auto arrayCtor = mlir::dyn_cast<cir::ArrayCtor>(op)) {
1969 mlir::Region &partialDtor = arrayCtor.getPartialDtor();
1970 if (!partialDtor.empty())
1971 partialDtorBlock = &partialDtor.front();
1972 }
else if (
auto arrayDtor = mlir::dyn_cast<cir::ArrayDtor>(op)) {
1981 if (arrayDtor.getDtorMayThrow())
1982 partialDtorBlock = bodyBlock;
1985 auto emitCtorDtorLoop = [&]() {
1989 [&](mlir::OpBuilder &b, mlir::Location loc) {
1990 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
1991 auto cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
1992 currentElement, stop);
1996 [&](mlir::OpBuilder &b, mlir::Location loc) {
1997 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
1999 cloneRegionBodyInto(bodyBlock, currentElement);
2000 mlir::Value stride = builder.
getUnsignedInt(loc, 1, sizeTypeSize);
2001 auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2002 currentElement, stride);
2005 mlir::Value stride = builder.
getSignedInt(loc, -1, sizeTypeSize);
2006 auto prevElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2007 currentElement, stride);
2009 cloneRegionBodyInto(bodyBlock, prevElement);
2012 cir::YieldOp::create(b, loc);
2016 if (partialDtorBlock) {
2017 cir::CleanupScopeOp::create(
2018 builder, loc, cir::CleanupKind::EH,
2020 [&](mlir::OpBuilder &b, mlir::Location loc) {
2022 cir::YieldOp::create(b, loc);
2025 [&](mlir::OpBuilder &b, mlir::Location loc) {
2026 auto cur = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2028 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, cur, begin);
2030 builder, loc, cmp,
false,
2031 [&](mlir::OpBuilder &b, mlir::Location loc) {
2035 [&](mlir::OpBuilder &b, mlir::Location loc) {
2036 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2037 auto neq = cir::CmpOp::create(
2038 builder, loc, cir::CmpOpKind::ne, el, begin);
2042 [&](mlir::OpBuilder &b, mlir::Location loc) {
2043 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2044 mlir::Value negOne =
2046 auto prev = cir::PtrStrideOp::create(builder, loc, eltTy,
2049 cloneRegionBodyInto(partialDtorBlock, prev);
2052 cir::YieldOp::create(builder, loc);
2054 cir::YieldOp::create(b, loc);
2061 cir::YieldOp::create(builder, loc);
2066void LoweringPreparePass::lowerArrayDtor(cir::ArrayDtor op) {
2067 CIRBaseBuilderTy builder(getContext());
2068 builder.setInsertionPointAfter(op.getOperation());
2070 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2072 if (op.getNumElements()) {
2074 op.getNumElements(), 0,
2080 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2086void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
2087 cir::CIRBaseBuilderTy builder(getContext());
2088 builder.setInsertionPointAfter(op.getOperation());
2090 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2092 if (op.getNumElements()) {
2094 op.getNumElements(), 0,
2100 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2106cir::FuncOp LoweringPreparePass::getCalledFunction(cir::CallOp callOp) {
2107 mlir::SymbolRefAttr sym = llvm::dyn_cast_if_present<mlir::SymbolRefAttr>(
2108 callOp.getCallableForCallee());
2111 return symbolTables.lookupNearestSymbolFrom<cir::FuncOp>(callOp, sym);
2114void LoweringPreparePass::lowerTrivialCopyCall(cir::CallOp op) {
2115 cir::FuncOp funcOp = getCalledFunction(op);
2119 std::optional<cir::CtorKind> ctorKind = funcOp.getCxxConstructorKind();
2120 if (ctorKind && *ctorKind == cir::CtorKind::Copy &&
2121 funcOp.isCxxTrivialMemberFunction()) {
2123 CIRBaseBuilderTy builder(getContext());
2124 mlir::ValueRange operands = op.getOperands();
2125 mlir::Value dest = operands[0];
2126 mlir::Value src = operands[1];
2127 builder.setInsertionPoint(op);
2133cir::GlobalOp LoweringPreparePass::getOrCreateConstAggregateGlobal(
2134 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef baseName,
2135 mlir::Type ty, mlir::TypedAttr constant) {
2137 llvm::SmallVector<cir::GlobalOp, 1> &versions =
2138 constAggregateGlobals[baseName];
2141 for (cir::GlobalOp gv : versions) {
2142 if (gv.getSymType() == ty && gv.getInitialValue() == constant)
2150 llvm::SmallString<128>
name(baseName);
2151 size_t baseLen =
name.size();
2152 unsigned version = versions.size();
2154 name.resize(baseLen);
2156 name.push_back(
'.');
2157 llvm::Twine(version).toVector(name);
2159 auto existingGv = symbolTables.lookupSymbolIn<cir::GlobalOp>(
2160 mlirModule, mlir::StringAttr::get(&getContext(), name));
2163 versions.push_back(existingGv);
2164 if (existingGv.getSymType() == ty &&
2165 existingGv.getInitialValue() == constant)
2171 mlir::OpBuilder::InsertionGuard guard(builder);
2172 builder.setInsertionPointToStart(mlirModule.getBody());
2174 cir::GlobalOp::create(builder, loc, name, ty,
2176 cir::LangAddressSpaceAttr::get(
2177 &getContext(), cir::LangAddressSpace::Default),
2178 cir::GlobalLinkageKind::PrivateLinkage);
2179 mlir::SymbolTable::setSymbolVisibility(
2180 gv, mlir::SymbolTable::Visibility::Private);
2181 gv.setInitialValueAttr(constant);
2185 symbolTables.getSymbolTable(mlirModule).insert(gv);
2187 versions.push_back(gv);
2191void LoweringPreparePass::lowerStoreOfConstAggregate(cir::StoreOp op) {
2193 auto constOp = op.getValue().getDefiningOp<cir::ConstantOp>();
2197 mlir::Type ty = constOp.getType();
2198 if (!mlir::isa<cir::ArrayType, cir::RecordType>(ty))
2204 auto alloca = op.getAddr().getDefiningOp<cir::AllocaOp>();
2208 mlir::TypedAttr constant = constOp.getValue();
2219 auto func = op->getParentOfType<cir::FuncOp>();
2222 llvm::StringRef funcName = func.getSymName();
2225 llvm::StringRef varName = alloca.getName();
2228 std::string baseName = (
"__const." + funcName +
"." + varName).str();
2229 CIRBaseBuilderTy builder(getContext());
2233 cir::GlobalOp gv = getOrCreateConstAggregateGlobal(builder, op.getLoc(),
2234 baseName, ty, constant);
2237 builder.setInsertionPoint(op);
2239 auto ptrTy = cir::PointerType::get(ty);
2240 mlir::Value globalPtr =
2241 cir::GetGlobalOp::create(builder, op.getLoc(), ptrTy, gv.getSymName());
2250 if (constOp.use_empty())
2254void LoweringPreparePass::runOnOp(mlir::Operation *op) {
2255 if (
auto arrayCtor = dyn_cast<cir::ArrayCtor>(op)) {
2256 lowerArrayCtor(arrayCtor);
2257 }
else if (
auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) {
2258 lowerArrayDtor(arrayDtor);
2259 }
else if (
auto cast = mlir::dyn_cast<cir::CastOp>(op)) {
2261 }
else if (
auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
2262 lowerComplexConjOp(complexConj);
2263 }
else if (
auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
2264 lowerComplexDivOp(complexDiv);
2265 }
else if (
auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
2266 lowerComplexMulOp(complexMul);
2267 }
else if (
auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) {
2268 lowerGlobalOp(glob);
2269 if (
auto regAttr = glob->getAttrOfType<CUDAVarRegistrationInfoAttr>(
2270 CUDAVarRegistrationInfoAttr::getMnemonic()))
2271 cudaDeviceVars.emplace_back(glob, regAttr);
2272 }
else if (
auto getGlob = mlir::dyn_cast<cir::GetGlobalOp>(op)) {
2273 lowerGetGlobalOp(getGlob);
2274 }
else if (
auto callOp = dyn_cast<cir::CallOp>(op)) {
2275 lowerTrivialCopyCall(callOp);
2276 }
else if (
auto storeOp = dyn_cast<cir::StoreOp>(op)) {
2277 lowerStoreOfConstAggregate(storeOp);
2278 }
else if (
auto fnOp = dyn_cast<cir::FuncOp>(op)) {
2279 if (
auto globalCtor = fnOp.getGlobalCtorPriority())
2280 globalCtorList.emplace_back(fnOp.getName(), globalCtor.value());
2281 else if (
auto globalDtor = fnOp.getGlobalDtorPriority())
2282 globalDtorList.emplace_back(fnOp.getName(), globalDtor.value());
2284 if (mlir::Attribute attr =
2285 fnOp->getAttr(cir::CUDAKernelNameAttr::getMnemonic())) {
2286 auto kernelNameAttr = dyn_cast<CUDAKernelNameAttr>(attr);
2287 llvm::StringRef kernelName = kernelNameAttr.getKernelName();
2288 cudaKernelMap[kernelName] = fnOp;
2290 }
else if (
auto threeWayCmp = dyn_cast<cir::CmpThreeWayOp>(op)) {
2291 lowerThreeWayCmpOp(threeWayCmp);
2292 }
else if (
auto initOp = dyn_cast<cir::LocalInitOp>(op)) {
2293 lowerLocalInitOp(initOp);
2304 llvm::StringRef name) {
2305 return (
"__" + prefix + name).str();
2327void LoweringPreparePass::buildCUDAModuleCtor() {
2330 if (astCtx->
getLangOpts().GPURelocatableDeviceCode)
2331 llvm_unreachable(
"GPU RDC NYI");
2335 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2340 mlir::Attribute cudaBinaryHandleAttr =
2341 mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName());
2342 if (!cudaBinaryHandleAttr) {
2348 llvm::StringRef cudaGPUBinaryName =
2349 mlir::cast<CUDABinaryHandleAttr>(cudaBinaryHandleAttr)
2353 llvm::vfs::FileSystem &vfs =
2355 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> gpuBinaryOrErr =
2356 vfs.getBufferForFile(cudaGPUBinaryName);
2357 if (std::error_code ec = gpuBinaryOrErr.getError()) {
2358 mlirModule->emitError(
"cannot open GPU binary file: " + cudaGPUBinaryName +
2359 ": " + ec.message());
2362 std::unique_ptr<llvm::MemoryBuffer> gpuBinary =
2363 std::move(gpuBinaryOrErr.get());
2367 mlir::Location loc = mlirModule->getLoc();
2368 CIRBaseBuilderTy builder(getContext());
2369 builder.setInsertionPointToStart(mlirModule.getBody());
2373 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2375 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2381 llvm::StringRef fatbinConstName =
2382 astCtx->
getLangOpts().HIP ?
".hip_fatbin" :
".nv_fatbin";
2384 llvm::StringRef fatbinSectionName =
2385 astCtx->
getLangOpts().HIP ?
".hipFatBinSegment" :
".nvFatBinSegment";
2389 ArrayType::get(&getContext(), charTy, gpuBinary->getBuffer().size());
2391 GlobalOp fatbinStr = GlobalOp::create(builder, loc, fatbinStrName, fatbinType,
2393 GlobalLinkageKind::PrivateLinkage);
2394 fatbinStr.setAlignment(8);
2395 fatbinStr.setInitialValueAttr(cir::ConstArrayAttr::get(
2396 fatbinType, StringAttr::get(gpuBinary->getBuffer(), fatbinType)));
2397 fatbinStr.setSection(fatbinConstName);
2398 fatbinStr.setPrivate();
2402 auto fatbinWrapperType = cir::StructType::get(
2403 &getContext(), {intTy, intTy, voidPtrTy, voidPtrTy},
2404 false,
false,
false);
2405 std::string fatbinWrapperName =
2407 GlobalOp fatbinWrapper = GlobalOp::create(
2408 builder, loc, fatbinWrapperName, fatbinWrapperType,
2409 true, {}, GlobalLinkageKind::PrivateLinkage);
2410 fatbinWrapper.setSection(fatbinSectionName);
2412 constexpr unsigned cudaFatMagic = 0x466243b1;
2413 constexpr unsigned hipFatMagic = 0x48495046;
2414 unsigned fatMagic =
isHIP ? hipFatMagic : cudaFatMagic;
2416 auto magicInit = IntAttr::get(intTy, fatMagic);
2417 auto versionInit = IntAttr::get(intTy, 1);
2418 auto fatbinStrSymbol =
2419 mlir::FlatSymbolRefAttr::get(fatbinStr.getSymNameAttr());
2420 auto fatbinInit = GlobalViewAttr::get(voidPtrTy, fatbinStrSymbol);
2422 fatbinWrapper.setInitialValueAttr(cir::ConstRecordAttr::get(
2424 mlir::ArrayAttr::get(&getContext(),
2425 {magicInit, versionInit, fatbinInit, unusedInit})));
2428 std::string gpubinHandleName =
2431 GlobalOp gpuBinHandle = GlobalOp::create(
2432 builder, loc, gpubinHandleName, voidPtrPtrTy,
2433 false, {}, cir::GlobalLinkageKind::InternalLinkage);
2435 gpuBinHandle.setPrivate();
2440 std::string regFuncName =
2442 FuncType regFuncType = FuncType::get({voidPtrTy}, voidPtrPtrTy);
2443 cir::FuncOp regFunc =
2444 buildRuntimeFunction(builder, regFuncName, loc, regFuncType);
2447 cir::FuncOp moduleCtor = buildRuntimeFunction(
2448 builder, moduleCtorName, loc, FuncType::get({}, voidTy),
2449 GlobalLinkageKind::InternalLinkage);
2451 globalCtorList.emplace_back(moduleCtorName,
2452 cir::GlobalCtorAttr::getDefaultPriority());
2453 builder.setInsertionPointToStart(moduleCtor.addEntryBlock());
2461 mlir::Block *entryBlock = builder.getInsertionBlock();
2462 mlir::Region *parent = entryBlock->getParent();
2463 mlir::Block *ifBlock = builder.createBlock(parent);
2464 mlir::Block *exitBlock = builder.createBlock(parent);
2466 mlir::OpBuilder::InsertionGuard guard(builder);
2467 builder.setInsertionPointToEnd(entryBlock);
2468 mlir::Value handle =
2470 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2471 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2472 mlir::Value isNull =
2473 builder.
createCompare(loc, cir::CmpOpKind::eq, handle, nullPtr);
2474 cir::BrCondOp::create(builder, loc, isNull, ifBlock, exitBlock);
2478 mlir::OpBuilder::InsertionGuard guard(builder);
2479 builder.setInsertionPointToStart(ifBlock);
2481 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2482 cir::CallOp gpuBinaryHandleCall =
2484 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2486 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2487 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2488 cir::BrOp::create(builder, loc, exitBlock);
2493 mlir::OpBuilder::InsertionGuard guard(builder);
2494 builder.setInsertionPointToStart(exitBlock);
2495 mlir::Value gHandle =
2498 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals())
2501 if (std::optional<FuncOp> dtor = buildHIPModuleDtor()) {
2502 cir::CIRBaseBuilderTy globalBuilder(getContext());
2503 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2504 FuncOp atexit = buildRuntimeFunction(
2505 globalBuilder,
"atexit", loc,
2506 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2507 mlir::Value dtorFunc = GetGlobalOp::create(
2508 builder, loc, PointerType::get(dtor->getFunctionType()),
2509 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2512 cir::ReturnOp::create(builder, loc);
2516 if (!astCtx->
getLangOpts().GPURelocatableDeviceCode) {
2524 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2525 cir::CallOp gpuBinaryHandleCall =
2527 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2529 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2530 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2533 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals()) {
2534 builder.
createCallOp(loc, *regGlobal, gpuBinaryHandle);
2543 cir::CIRBaseBuilderTy globalBuilder(getContext());
2544 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2546 buildRuntimeFunction(globalBuilder,
"__cudaRegisterFatBinaryEnd", loc,
2547 FuncType::get({voidPtrPtrTy}, voidTy));
2551 llvm_unreachable(
"GPU RDC NYI");
2556 if (std::optional<FuncOp> dtor = buildCUDAModuleDtor()) {
2559 cir::CIRBaseBuilderTy globalBuilder(getContext());
2560 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2561 FuncOp atexit = buildRuntimeFunction(
2562 globalBuilder,
"atexit", loc,
2563 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2564 mlir::Value dtorFunc = GetGlobalOp::create(
2565 builder, loc, PointerType::get(dtor->getFunctionType()),
2566 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2569 cir::ReturnOp::create(builder, loc);
2572std::optional<FuncOp> LoweringPreparePass::buildCUDAModuleDtor() {
2573 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2578 VoidType voidTy = VoidType::get(&getContext());
2579 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2581 mlir::Location loc = mlirModule.getLoc();
2583 cir::CIRBaseBuilderTy builder(getContext());
2584 builder.setInsertionPointToStart(mlirModule.getBody());
2587 std::string unregisterFuncName =
2589 FuncOp unregisterFunc = buildRuntimeFunction(
2590 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2599 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2600 GlobalLinkageKind::InternalLinkage);
2602 builder.setInsertionPointToStart(dtor.addEntryBlock());
2608 GlobalOp gpubinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2610 mlir::Value gpubin = builder.
createLoad(loc, gpubinAddress);
2612 ReturnOp::create(builder, loc);
2629std::optional<FuncOp> LoweringPreparePass::buildHIPModuleDtor() {
2630 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2635 VoidType voidTy = VoidType::get(&getContext());
2636 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2638 mlir::Location loc = mlirModule.getLoc();
2640 cir::CIRBaseBuilderTy builder(getContext());
2641 builder.setInsertionPointToStart(mlirModule.getBody());
2644 std::string unregisterFuncName =
2646 FuncOp unregisterFunc = buildRuntimeFunction(
2647 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2651 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2652 GlobalLinkageKind::InternalLinkage);
2655 GlobalOp gpuBinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2657 mlir::Block *entryBlock = dtor.addEntryBlock();
2658 mlir::Block *ifBlock = builder.createBlock(&dtor.getBody());
2659 mlir::Block *exitBlock = builder.createBlock(&dtor.getBody());
2661 mlir::OpBuilder::InsertionGuard guard(builder);
2662 builder.setInsertionPointToEnd(entryBlock);
2663 mlir::Value handle =
2665 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2666 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2667 mlir::Value isNotNull =
2668 builder.
createCompare(loc, cir::CmpOpKind::ne, handle, nullPtr);
2669 cir::BrCondOp::create(builder, loc, isNotNull, ifBlock, exitBlock);
2673 mlir::OpBuilder::InsertionGuard ifGuard(builder);
2674 builder.setInsertionPointToStart(ifBlock);
2677 cir::BrOp::create(builder, loc, exitBlock);
2680 mlir::OpBuilder::InsertionGuard exitGuard(builder);
2681 builder.setInsertionPointToStart(exitBlock);
2682 cir::ReturnOp::create(builder, loc);
2688std::optional<FuncOp> LoweringPreparePass::buildCUDARegisterGlobals() {
2689 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2692 cir::CIRBaseBuilderTy builder(getContext());
2693 builder.setInsertionPointToStart(mlirModule.getBody());
2695 mlir::Location loc = mlirModule.getLoc();
2698 auto voidTy = VoidType::get(&getContext());
2699 auto voidPtrTy = PointerType::get(voidTy);
2700 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2704 std::string regGlobalFuncName =
2706 auto regGlobalFuncTy = FuncType::get({voidPtrPtrTy}, voidTy);
2707 FuncOp regGlobalFunc =
2708 buildRuntimeFunction(builder, regGlobalFuncName, loc, regGlobalFuncTy,
2709 GlobalLinkageKind::InternalLinkage);
2710 builder.setInsertionPointToStart(regGlobalFunc.addEntryBlock());
2712 buildCUDARegisterGlobalFunctions(builder, regGlobalFunc);
2713 buildCUDARegisterVars(builder, regGlobalFunc);
2715 ReturnOp::create(builder, loc);
2716 return regGlobalFunc;
2719void LoweringPreparePass::buildCUDARegisterGlobalFunctions(
2720 cir::CIRBaseBuilderTy &builder, FuncOp regGlobalFunc) {
2721 mlir::Location loc = mlirModule.getLoc();
2723 cir::CIRDataLayout dataLayout(mlirModule);
2725 auto voidTy = VoidType::get(&getContext());
2726 auto voidPtrTy = PointerType::get(voidTy);
2727 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2729 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2733 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2735 cir::CIRBaseBuilderTy globalBuilder(getContext());
2736 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2750 FuncOp cudaRegisterFunction = buildRuntimeFunction(
2752 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2753 voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy},
2756 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2757 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2758 auto tmpString = cir::GlobalOp::create(
2759 globalBuilder, loc, (
".str" + str).str(), strType,
2761 cir::GlobalLinkageKind::PrivateLinkage);
2764 tmpString.setInitialValueAttr(
2765 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2766 tmpString.setPrivate();
2770 cir::ConstantOp cirNullPtr = builder.
getNullPtr(voidPtrTy, loc);
2772 for (
auto kernelName : cudaKernelMap.keys()) {
2773 FuncOp deviceStub = cudaKernelMap[kernelName];
2774 GlobalOp deviceFuncStr = makeConstantString(kernelName);
2778 mlir::Value hostFunc;
2785 auto funcHandle = cast<GlobalOp>(mlirModule.lookupSymbol(kernelName));
2790 GetGlobalOp::create(
2791 builder, loc, PointerType::get(deviceStub.getFunctionType()),
2792 mlir::FlatSymbolRefAttr::get(deviceStub.getSymNameAttr())),
2796 loc, cudaRegisterFunction,
2797 {fatbinHandle, hostFunc, deviceFunc, deviceFunc,
2798 ConstantOp::create(builder, loc, IntAttr::get(intTy, -1)), cirNullPtr,
2799 cirNullPtr, cirNullPtr, cirNullPtr, cirNullPtr});
2806void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
2807 FuncOp regGlobalFunc) {
2808 mlir::Location loc = mlirModule.getLoc();
2810 cir::CIRDataLayout dataLayout(mlirModule);
2813 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2817 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2820 if (cudaDeviceVars.empty())
2823 cir::CIRBaseBuilderTy globalBuilder(getContext());
2824 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2831 cir::VoidType voidTy = builder.
getVoidTy();
2832 FuncOp cudaRegisterVar = buildRuntimeFunction(
2834 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2835 sizeTy, intTy, intTy},
2838 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2839 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2840 auto tmpString = cir::GlobalOp::create(
2841 globalBuilder, loc, (
".str" + str).str(), strType,
2843 cir::GlobalLinkageKind::PrivateLinkage);
2844 tmpString.setInitialValueAttr(
2845 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2846 tmpString.setPrivate();
2850 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2852 for (
auto &[global, regAttr] : cudaDeviceVars) {
2853 switch (regAttr.getKind()) {
2854 case cir::CUDADeviceVarKind::Variable:
2856 case cir::CUDADeviceVarKind::Surface:
2857 llvm_unreachable(
"Surface registration NYI");
2858 case cir::CUDADeviceVarKind::Texture:
2859 llvm_unreachable(
"Texture registration NYI");
2862 if (regAttr.getIsManaged())
2863 llvm_unreachable(
"Managed variable registration NYI");
2865 GlobalOp deviceNameStr = makeConstantString(regAttr.getDeviceSideName());
2868 mlir::Value hostVar =
2871 auto isExtern = ConstantOp::create(
2872 builder, loc, IntAttr::get(intTy, regAttr.getIsExtern() ? 1 : 0));
2873 llvm::TypeSize size = dataLayout.getTypeAllocSize(global.getSymType());
2874 auto varSize = ConstantOp::create(
2875 builder, loc, IntAttr::get(sizeTy, size.getFixedValue()));
2876 auto isConstant = ConstantOp::create(
2877 builder, loc, IntAttr::get(intTy, regAttr.getIsConstant() ? 1 : 0));
2878 auto normalized = ConstantOp::create(builder, loc, IntAttr::get(intTy, 0));
2880 {fatbinHandle, hostVar, deviceName, deviceName,
2881 isExtern, varSize, isConstant, normalized});
2885void LoweringPreparePass::runOnOperation() {
2886 mlir::Operation *op = getOperation();
2887 if (isa<::mlir::ModuleOp>(op))
2888 mlirModule = cast<::mlir::ModuleOp>(op);
2890 llvm::SmallVector<mlir::Operation *> opsToTransform;
2892 op->walk([&](mlir::Operation *op) {
2893 if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
2894 cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
2895 cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
2896 cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
2897 cir::CmpThreeWayOp, cir::LocalInitOp>(op))
2898 opsToTransform.push_back(op);
2901 for (mlir::Operation *o : opsToTransform)
2904 buildCXXGlobalInitFunc();
2905 buildCXXGlobalTlsFunc();
2907 buildCUDAModuleCtor();
2909 buildGlobalCtorDtorList();
2913 return std::make_unique<LoweringPreparePass>();
2916std::unique_ptr<Pass>
2918 auto pass = std::make_unique<LoweringPreparePass>();
2919 pass->setASTContext(astCtx);
2920 return std::move(pass);
Defines the clang::ASTContext interface.
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static mlir::Value buildRangeReductionComplexDiv(CIRBaseBuilderTy &builder, mlir::Location loc, mlir::Value lhsReal, mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag)
static llvm::StringRef getComplexDivLibCallName(llvm::APFloat::Semantics semantics)
static llvm::SmallVector< mlir::Attribute > prepareCtorDtorAttrList(mlir::MLIRContext *context, llvm::ArrayRef< std::pair< std::string, uint32_t > > list)
static llvm::StringRef getComplexMulLibCallName(llvm::APFloat::Semantics semantics)
static cir::GlobalLinkageKind getThreadLocalWrapperLinkage(GlobalOp op, clang::ASTContext &astCtx)
static mlir::Value buildComplexBinOpLibCall(LoweringPreparePass &pass, CIRBaseBuilderTy &builder, llvm::StringRef(*libFuncNameGetter)(llvm::APFloat::Semantics), mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal, mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag)
static mlir::Value lowerComplexMul(LoweringPreparePass &pass, CIRBaseBuilderTy &builder, mlir::Location loc, cir::ComplexMulOp op, mlir::Value lhsReal, mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag)
static std::string addUnderscoredPrefix(llvm::StringRef prefix, llvm::StringRef name)
static SmallString< 128 > getTransformedFileName(mlir::ModuleOp mlirModule)
static mlir::Value lowerComplexToComplexCast(mlir::MLIRContext &ctx, cir::CastOp op, cir::CastKind scalarCastKind)
static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder, clang::ASTContext *astCtx, mlir::Operation *op, mlir::Type eltTy, mlir::Value addr, mlir::Value numElements, uint64_t arrayLen, bool isCtor)
Lower a cir.array.ctor or cir.array.dtor into a do-while loop that iterates over every element.
static bool isThreadWrapperReplaceable(cir::TLS_Model tls, clang::ASTContext &astCtx)
static mlir::Value lowerComplexToScalarCast(mlir::MLIRContext &ctx, cir::CastOp op, cir::CastKind elemToBoolKind)
static mlir::Value buildAlgebraicComplexDiv(CIRBaseBuilderTy &builder, mlir::Location loc, mlir::Value lhsReal, mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag)
static llvm::StringRef getCUDAPrefix(clang::ASTContext *astCtx)
static mlir::Type higherPrecisionElementTypeForComplexArithmetic(mlir::MLIRContext &context, clang::ASTContext &cc, CIRBaseBuilderTy &builder, mlir::Type elementType)
static mlir::Value lowerScalarToComplexCast(mlir::MLIRContext &ctx, cir::CastOp op)
static mlir::Value lowerComplexDiv(LoweringPreparePass &pass, CIRBaseBuilderTy &builder, mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal, mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag, mlir::MLIRContext &mlirCx, clang::ASTContext &cc)
Defines the clang::Module class, which describes a module in the source code.
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
Defines the SourceManager interface.
Defines various enumerations that describe declaration and type specifiers.
Defines the TargetCXXABI class, which abstracts details of the C++ ABI that we're targeting.
mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::TypedAttr getConstNullPtrAttr(mlir::Type t)
mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile=false, bool skipTailPadding=false)
Create a copy with inferred length.
cir::VoidType getVoidTy()
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
cir::PointerType getVoidFnPtrTy(mlir::TypeRange argTypes={})
Returns void (*)(T...) as a cir::PointerType.
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::IntType getUIntNTy(int n)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, bool isVolatile=false, uint64_t alignment=0, bool isNontemporal=false)
mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::FuncType getVoidFnTy(mlir::TypeRange argTypes={})
Returns void (T...) as a cir::FuncType.
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createMinus(mlir::Location loc, mlir::Value input, bool nsw=false)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand)
cir::IntType getSIntNTy(int n)
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, uint64_t alignment)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::BoolType getBoolTy()
mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val, unsigned numBits)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
MangleContext * createMangleContext(const TargetInfo *T=nullptr)
If T is null pointer, assume the target in ASTContext.
const LangOptions & getLangOpts() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const TargetInfo & getTargetInfo() const
QualType getSignedSizeType() const
Return the unique signed counterpart of the integer type corresponding to size_t.
Module * getCurrentNamedModule() const
Get module under construction, nullptr if this is not a C++20 module.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
llvm::vfs::FileSystem & getVirtualFileSystem() const
bool isModuleImplementation() const
Is this a module implementation.
FileManager & getFileManager() const
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getMaxAtomicInlineWidth() const
Return the maximum width lock-free atomic operation which can be inlined given the supported features...
const llvm::fltSemantics & getDoubleFormat() const
const llvm::fltSemantics & getHalfFormat() const
const llvm::fltSemantics & getBFloat16Format() const
const llvm::fltSemantics & getLongDoubleFormat() const
const llvm::fltSemantics & getFloatFormat() const
virtual uint64_t getMaxPointerWidth() const
Return the maximum width of pointers on this target.
const llvm::fltSemantics & getFloat128Format() const
const llvm::VersionTuple & getSDKVersion() const
Defines the clang::TargetInfo interface.
static bool isLocalLinkage(GlobalLinkageKind linkage)
static bool isWeakODRLinkage(GlobalLinkageKind linkage)
static bool isLinkOnceLinkage(GlobalLinkageKind linkage)
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
bool isHIP(ID Id)
isHIP - Is this a HIP input.
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
bool CudaFeatureEnabled(llvm::VersionTuple, CudaFeature)
LLVM_READONLY bool isPreprocessingNumberBody(unsigned char c)
Return true if this is the body character of a C preprocessing number, which is [a-zA-Z0-9_.
@ CUDA_USES_FATBIN_REGISTER_END
std::unique_ptr< Pass > createLoweringPreparePass()
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
static bool hipModuleCtor()
static bool guardAbortOnException()
static bool opGlobalAnnotations()
static bool opGlobalCtorPriority()
static bool shouldSplitConstantStore()
static bool shouldUseMemSetToInitialize()
static bool opFuncExtraAttrs()
static bool shouldUseBZeroPlusStoresToInitialize()
static bool fastMathFlags()
static bool astVarDeclInterface()