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);
101 void lowerStdOp(cir::StdOpInterface op);
106 cir::FuncOp getCalledFunction(cir::CallOp callOp);
115 cir::GlobalOp getOrCreateConstAggregateGlobal(CIRBaseBuilderTy &builder,
117 llvm::StringRef baseName,
119 mlir::TypedAttr constant);
122 cir::FuncOp buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op);
125 void defineGlobalThreadLocalWrapper(cir::GlobalOp op, cir::FuncOp initAlias,
126 bool isVarDefinition);
128 cir::FuncOp defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
129 cir::FuncOp aliasee);
131 cir::FuncOp getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
137 cir::IfOp buildGlobalTlsGuardCheck(CIRBaseBuilderTy &builder,
138 mlir::Location loc, cir::GlobalOp guard);
140 cir::FuncOp getOrCreateDtorFunc(CIRBaseBuilderTy &builder, cir::GlobalOp op,
141 mlir::Region &dtorRegion,
142 cir::CallOp &dtorCall);
145 void buildCXXGlobalInitFunc();
148 void buildCXXGlobalTlsFunc();
151 void buildGlobalCtorDtorList();
153 cir::FuncOp buildRuntimeFunction(
154 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
156 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage);
158 cir::GlobalOp getOrCreateRuntimeVariable(
159 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
161 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage,
162 cir::VisibilityKind visibility = cir::VisibilityKind::Default);
168 llvm::StringMap<FuncOp> cudaKernelMap;
169 llvm::SmallVector<std::pair<cir::GlobalOp, cir::CUDAVarRegistrationInfoAttr>>
174 void buildCUDAModuleCtor();
175 std::optional<FuncOp> buildCUDAModuleDtor();
176 std::optional<FuncOp> buildHIPModuleDtor();
177 std::optional<FuncOp> buildCUDARegisterGlobals();
178 void buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
179 FuncOp regGlobalFunc);
180 void buildCUDARegisterGlobalFunctions(cir::CIRBaseBuilderTy &builder,
181 FuncOp regGlobalFunc);
184 void handleStaticLocal(cir::GlobalOp globalOp, cir::LocalInitOp localInitOp);
193 cir::FuncOp getTlsInitFn();
196 cir::GlobalOp createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
200 cir::GlobalOp createGuardGlobalOp(CIRBaseBuilderTy &builder,
201 mlir::Location loc, llvm::StringRef name,
202 cir::IntType guardTy,
203 cir::GlobalLinkageKind linkage);
206 cir::GlobalOp getStaticLocalDeclGuardAddress(llvm::StringRef globalSymName) {
207 auto it = staticLocalDeclGuardMap.find(globalSymName);
208 if (it != staticLocalDeclGuardMap.end())
214 void setStaticLocalDeclGuardAddress(llvm::StringRef globalSymName,
215 cir::GlobalOp guard) {
216 staticLocalDeclGuardMap[globalSymName] = guard;
220 cir::GlobalOp getOrCreateStaticLocalDeclGuardAddress(
221 CIRBaseBuilderTy &builder, cir::GlobalOp globalOp, StringRef guardName,
222 bool isLocalVarDecl,
bool useInt8GuardVariable) {
224 cir::CIRDataLayout dataLayout(mlirModule);
225 cir::IntType guardTy;
226 clang::CharUnits guardAlignment;
229 if (useInt8GuardVariable) {
230 guardTy = cir::IntType::get(&getContext(), 8,
true);
232 }
else if (useARMGuardVarABI()) {
234 const unsigned sizeTypeSize =
235 astCtx->getTypeSize(astCtx->getSignedSizeType());
237 cir::IntType::get(&getContext(), sizeTypeSize,
true);
241 guardTy = cir::IntType::get(&getContext(), 64,
true);
245 assert(guardTy && guardAlignment.
getQuantity() != 0);
247 llvm::StringRef globalSymName = globalOp.getSymName();
248 cir::GlobalOp guard = getStaticLocalDeclGuardAddress(globalSymName);
251 guard = createGuardGlobalOp(builder, globalOp->getLoc(), guardName,
252 guardTy, globalOp.getLinkage());
253 guard.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
254 guard.setDSOLocal(globalOp.getDsoLocal());
255 guard.setAlignment(guardAlignment.
getAsAlign().value());
256 guard.setTlsModel(globalOp.getTlsModel());
262 bool hasComdat = globalOp.getComdat();
263 const llvm::Triple &triple = astCtx->getTargetInfo().getTriple();
266 if (!isLocalVarDecl && hasComdat &&
267 (triple.isOSBinFormatELF() || triple.isOSBinFormatWasm())) {
269 guard.setComdat(
true);
270 }
else if (hasComdat && globalOp.isWeakForLinker()) {
271 guard.setComdat(
true);
274 setStaticLocalDeclGuardAddress(globalSymName, guard);
283 clang::ASTContext *astCtx;
286 mlir::ModuleOp mlirModule;
306 mlir::SymbolTableCollection symbolTables;
309 llvm::StringMap<uint32_t> dynamicInitializerNames;
310 llvm::SmallVector<cir::FuncOp> dynamicInitializers;
311 llvm::SmallVector<cir::FuncOp> globalThreadLocalInitializers;
312 llvm::StringMap<cir::FuncOp> threadLocalWrappers;
313 llvm::StringMap<cir::FuncOp> threadLocalInitAliases;
316 llvm::StringMap<cir::GlobalOp> staticLocalDeclGuardMap;
318 llvm::StringMap<llvm::SmallVector<cir::GlobalOp, 1>> constAggregateGlobals;
321 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList;
323 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalDtorList;
327 bool useARMGuardVarABI()
const {
328 switch (astCtx->getCXXABIKind()) {
329 case clang::TargetCXXABI::GenericARM:
330 case clang::TargetCXXABI::iOS:
331 case clang::TargetCXXABI::WatchOS:
332 case clang::TargetCXXABI::GenericAArch64:
333 case clang::TargetCXXABI::WebAssembly:
340 void emitGlobalGuardedDtorRegion(CIRBaseBuilderTy &builder,
341 cir::GlobalOp global,
342 mlir::Region &dtorRegion,
bool tls,
343 mlir::Block &entryBB) {
345 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
346 cir::GlobalOp handle = getOrCreateRuntimeVariable(
347 builder,
"__dso_handle", global.getLoc(), builder.getI8Type(),
348 cir::GlobalLinkageKind::ExternalLinkage, cir::VisibilityKind::Hidden);
354 cir::CallOp dtorCall;
355 cir::FuncOp dtorFunc =
356 getOrCreateDtorFunc(builder, global, dtorRegion, dtorCall);
361 cir::PointerType voidFnPtrTy = builder.
getVoidFnPtrTy({voidPtrTy});
362 cir::PointerType handlePtrTy = builder.
getPointerTo(handle.getSymType());
365 cir::FuncType::get({voidFnPtrTy, voidPtrTy, handlePtrTy}, intTy);
367 llvm::StringLiteral nameAtExit =
"__cxa_atexit";
369 nameAtExit = astCtx->getTargetInfo().getTriple().isOSDarwin()
370 ? llvm::StringLiteral(
"_tlv_atexit")
371 : llvm::StringLiteral(
"__cxa_thread_atexit");
373 cir::FuncOp fnAtExit = buildRuntimeFunction(builder, nameAtExit,
374 global.getLoc(), fnAtExitType);
378 builder.setInsertionPointAfter(dtorCall);
380 auto dtorPtrTy = cir::PointerType::get(dtorFunc.getFunctionType());
381 args[0] = cir::GetGlobalOp::create(builder, dtorCall.getLoc(), dtorPtrTy,
382 dtorFunc.getSymName());
383 args[0] = cir::CastOp::create(builder, dtorCall.getLoc(), voidFnPtrTy,
384 cir::CastKind::bitcast, args[0]);
386 cir::CastOp::create(builder, dtorCall.getLoc(), voidPtrTy,
387 cir::CastKind::bitcast, dtorCall.getArgOperand(0));
388 args[2] = cir::GetGlobalOp::create(builder, handle.getLoc(), handlePtrTy,
389 handle.getSymName());
390 builder.
createCallOp(dtorCall.getLoc(), fnAtExit, args);
392 mlir::Block &dtorBlock = dtorRegion.front();
393 entryBB.getOperations().splice(entryBB.end(), dtorBlock.getOperations(),
395 std::prev(dtorBlock.end()));
398 builder.setInsertionPointToEnd(&entryBB);
404 void emitCXXGuardedInitIf(CIRBaseBuilderTy &builder, cir::GlobalOp globalOp,
405 mlir::Region &ctorRegion, mlir::Region &dtorRegion,
406 cir::ASTVarDeclInterface varDecl,
407 mlir::Value guardPtr, cir::PointerType guardPtrTy,
409 auto loc = globalOp->getLoc();
429 mlir::Block *insertBlock = builder.getInsertionBlock();
430 if (!ctorRegion.empty()) {
431 assert(ctorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
433 mlir::Block &block = ctorRegion.front();
434 insertBlock->getOperations().splice(
435 insertBlock->end(), block.getOperations(), block.begin(),
436 std::prev(block.end()));
439 if (!dtorRegion.empty()) {
440 assert(dtorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
442 emitGlobalGuardedDtorRegion(builder, globalOp, dtorRegion, !threadsafe,
445 builder.setInsertionPointToEnd(insertBlock);
446 ctorRegion.getBlocks().clear();
454 mlir::Value acquireResult = acquireCall.getResult();
457 loc, mlir::cast<cir::IntType>(acquireResult.getType()), 0);
458 auto shouldInit = builder.
createCompare(loc, cir::CmpOpKind::ne,
459 acquireResult, acquireZero);
464 cir::IfOp::create(builder, loc, shouldInit,
false,
465 [](mlir::OpBuilder &, mlir::Location) {});
466 mlir::OpBuilder::InsertionGuard insertGuard(builder);
467 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
481 mlir::ValueRange{guardPtr});
484 }
else if (!
varDecl.isLocalVarDecl()) {
490 globalOp->emitError(
"NYI: non-threadsafe init for non-local variables");
505 void setASTContext(clang::ASTContext *c) { astCtx = c; }
510cir::GlobalOp LoweringPreparePass::getOrCreateRuntimeVariable(
511 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
512 mlir::Type type, cir::GlobalLinkageKind linkage,
513 cir::VisibilityKind visibility) {
514 cir::GlobalOp g = dyn_cast_or_null<cir::GlobalOp>(
515 mlir::SymbolTable::lookupNearestSymbolFrom(
516 mlirModule, mlir::StringAttr::get(mlirModule->getContext(), name)));
518 g = cir::GlobalOp::create(builder, loc, name, type);
520 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
521 mlir::SymbolTable::setSymbolVisibility(
522 g, mlir::SymbolTable::Visibility::Private);
523 g.setGlobalVisibility(visibility);
528cir::FuncOp LoweringPreparePass::buildRuntimeFunction(
529 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
530 cir::FuncType type, cir::GlobalLinkageKind linkage) {
531 cir::FuncOp f = dyn_cast_or_null<FuncOp>(SymbolTable::lookupNearestSymbolFrom(
532 mlirModule, StringAttr::get(mlirModule->getContext(), name)));
534 f = cir::FuncOp::create(builder, loc, name, type);
536 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
537 mlir::SymbolTable::setSymbolVisibility(
538 f, mlir::SymbolTable::Visibility::Private);
548 builder.setInsertionPoint(op);
550 mlir::Value src = op.getSrc();
551 mlir::Value imag = builder.
getNullValue(src.getType(), op.getLoc());
557 cir::CastKind elemToBoolKind) {
559 builder.setInsertionPoint(op);
561 mlir::Value src = op.getSrc();
562 if (!mlir::isa<cir::BoolType>(op.getType()))
569 cir::BoolType boolTy = builder.
getBoolTy();
570 mlir::Value srcRealToBool =
571 builder.
createCast(op.getLoc(), elemToBoolKind, srcReal, boolTy);
572 mlir::Value srcImagToBool =
573 builder.
createCast(op.getLoc(), elemToBoolKind, srcImag, boolTy);
574 return builder.
createLogicalOr(op.getLoc(), srcRealToBool, srcImagToBool);
579 cir::CastKind scalarCastKind) {
581 builder.setInsertionPoint(op);
583 mlir::Value src = op.getSrc();
584 auto dstComplexElemTy =
585 mlir::cast<cir::ComplexType>(op.getType()).getElementType();
590 mlir::Value dstReal = builder.
createCast(op.getLoc(), scalarCastKind, srcReal,
592 mlir::Value dstImag = builder.
createCast(op.getLoc(), scalarCastKind, srcImag,
597void LoweringPreparePass::lowerCastOp(cir::CastOp op) {
598 mlir::MLIRContext &ctx = getContext();
599 mlir::Value loweredValue = [&]() -> mlir::Value {
600 switch (op.getKind()) {
601 case cir::CastKind::float_to_complex:
602 case cir::CastKind::int_to_complex:
604 case cir::CastKind::float_complex_to_real:
605 case cir::CastKind::int_complex_to_real:
607 case cir::CastKind::float_complex_to_bool:
609 case cir::CastKind::int_complex_to_bool:
611 case cir::CastKind::float_complex:
613 case cir::CastKind::float_complex_to_int_complex:
615 case cir::CastKind::int_complex:
617 case cir::CastKind::int_complex_to_float_complex:
625 op.replaceAllUsesWith(loweredValue);
632 llvm::StringRef (*libFuncNameGetter)(llvm::APFloat::Semantics),
633 mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal,
634 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag) {
635 cir::FPTypeInterface elementTy =
636 mlir::cast<cir::FPTypeInterface>(ty.getElementType());
638 llvm::StringRef libFuncName = libFuncNameGetter(
639 llvm::APFloat::SemanticsToEnum(elementTy.getFloatSemantics()));
642 cir::FuncType libFuncTy = cir::FuncType::get(libFuncInputTypes, ty);
648 mlir::OpBuilder::InsertionGuard ipGuard{builder};
649 builder.setInsertionPointToStart(pass.mlirModule.getBody());
650 libFunc = pass.buildRuntimeFunction(builder, libFuncName, loc, libFuncTy);
654 builder.
createCallOp(loc, libFunc, {lhsReal, lhsImag, rhsReal, rhsImag});
655 return call.getResult();
658static llvm::StringRef
661 case llvm::APFloat::S_IEEEhalf:
663 case llvm::APFloat::S_IEEEsingle:
665 case llvm::APFloat::S_IEEEdouble:
667 case llvm::APFloat::S_PPCDoubleDouble:
669 case llvm::APFloat::S_x87DoubleExtended:
671 case llvm::APFloat::S_IEEEquad:
674 llvm_unreachable(
"unsupported floating point type");
680 mlir::Value lhsReal, mlir::Value lhsImag,
681 mlir::Value rhsReal, mlir::Value rhsImag) {
683 mlir::Value &a = lhsReal;
684 mlir::Value &b = lhsImag;
685 mlir::Value &c = rhsReal;
686 mlir::Value &d = rhsImag;
690 bool isFP = cir::isFPOrVectorOfFPType(a.getType());
691 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
694 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
697 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
700 auto div = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
704 mlir::Value ac = mul(loc, a, c);
705 mlir::Value bd = mul(loc, b, d);
706 mlir::Value cc = mul(loc, c, c);
707 mlir::Value dd = mul(loc, d, d);
708 mlir::Value acbd = add(loc, ac, bd);
709 mlir::Value ccdd = add(loc, cc, dd);
710 mlir::Value resultReal = div(loc, acbd, ccdd);
712 mlir::Value bc = mul(loc, b, c);
713 mlir::Value ad = mul(loc, a, d);
714 mlir::Value bcad = sub(loc, bc, ad);
715 mlir::Value resultImag = div(loc, bcad, ccdd);
721 mlir::Value lhsReal, mlir::Value lhsImag,
722 mlir::Value rhsReal, mlir::Value rhsImag) {
743 mlir::Value &a = lhsReal;
744 mlir::Value &b = lhsImag;
745 mlir::Value &c = rhsReal;
746 mlir::Value &d = rhsImag;
749 assert(cir::isFPOrVectorOfFPType(a.getType()) &&
750 "range-reduction complex divide expects floating-point operands");
752 auto trueBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
753 mlir::Value r = builder.
createFDiv(loc, d, c);
754 mlir::Value rd = builder.
createFMul(loc, r, d);
755 mlir::Value tmp = builder.
createFAdd(loc, c, rd);
757 mlir::Value br = builder.
createFMul(loc, b, r);
758 mlir::Value abr = builder.
createFAdd(loc, a, br);
759 mlir::Value e = builder.
createFDiv(loc, abr, tmp);
761 mlir::Value ar = builder.
createFMul(loc, a, r);
762 mlir::Value bar = builder.
createFSub(loc, b, ar);
763 mlir::Value f = builder.
createFDiv(loc, bar, tmp);
769 auto falseBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
770 mlir::Value r = builder.
createFDiv(loc, c, d);
771 mlir::Value rc = builder.
createFMul(loc, r, c);
772 mlir::Value tmp = builder.
createFAdd(loc, d, rc);
774 mlir::Value ar = builder.
createFMul(loc, a, r);
775 mlir::Value arb = builder.
createFAdd(loc, ar, b);
776 mlir::Value e = builder.
createFDiv(loc, arb, tmp);
778 mlir::Value br = builder.
createFMul(loc, b, r);
779 mlir::Value bra = builder.
createFSub(loc, br, a);
780 mlir::Value f = builder.
createFDiv(loc, bra, tmp);
786 auto cFabs = cir::FAbsOp::create(builder, loc, c);
787 auto dFabs = cir::FAbsOp::create(builder, loc, d);
788 cir::CmpOp cmpResult =
789 builder.
createCompare(loc, cir::CmpOpKind::ge, cFabs, dFabs);
790 auto ternary = cir::TernaryOp::create(builder, loc, cmpResult,
791 trueBranchBuilder, falseBranchBuilder);
793 return ternary.getResult();
800 auto getHigherPrecisionFPType = [&context](mlir::Type type) -> mlir::Type {
801 if (mlir::isa<cir::FP16Type>(type))
802 return cir::SingleType::get(&context);
804 if (mlir::isa<cir::SingleType>(type) || mlir::isa<cir::BF16Type>(type))
805 return cir::DoubleType::get(&context);
807 if (mlir::isa<cir::DoubleType>(type))
808 return cir::LongDoubleType::get(&context, type);
813 auto getFloatTypeSemantics =
814 [&cc](mlir::Type type) ->
const llvm::fltSemantics & {
816 if (mlir::isa<cir::FP16Type>(type))
819 if (mlir::isa<cir::BF16Type>(type))
822 if (mlir::isa<cir::SingleType>(type))
825 if (mlir::isa<cir::DoubleType>(type))
828 if (mlir::isa<cir::LongDoubleType>(type)) {
830 llvm_unreachable(
"NYI Float type semantics with OpenMP");
834 if (mlir::isa<cir::FP128Type>(type)) {
836 llvm_unreachable(
"NYI Float type semantics with OpenMP");
840 llvm_unreachable(
"Unsupported float type semantics");
843 const mlir::Type higherElementType = getHigherPrecisionFPType(elementType);
844 const llvm::fltSemantics &elementTypeSemantics =
845 getFloatTypeSemantics(elementType);
846 const llvm::fltSemantics &higherElementTypeSemantics =
847 getFloatTypeSemantics(higherElementType);
856 if (llvm::APFloat::semanticsMaxExponent(elementTypeSemantics) * 2 + 1 <=
857 llvm::APFloat::semanticsMaxExponent(higherElementTypeSemantics)) {
858 return higherElementType;
868 mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal,
869 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag,
871 cir::ComplexType complexTy = op.getType();
872 if (mlir::isa<cir::FPTypeInterface>(complexTy.getElementType())) {
873 cir::ComplexRangeKind range = op.getRange();
874 if (range == cir::ComplexRangeKind::Improved)
878 if (range == cir::ComplexRangeKind::Full)
880 loc, complexTy, lhsReal, lhsImag, rhsReal,
883 if (range == cir::ComplexRangeKind::Promoted) {
884 mlir::Type originalElementType = complexTy.getElementType();
885 mlir::Type higherPrecisionElementType =
887 originalElementType);
889 if (!higherPrecisionElementType)
893 cir::CastKind floatingCastKind = cir::CastKind::floating;
894 lhsReal = builder.
createCast(floatingCastKind, lhsReal,
895 higherPrecisionElementType);
896 lhsImag = builder.
createCast(floatingCastKind, lhsImag,
897 higherPrecisionElementType);
898 rhsReal = builder.
createCast(floatingCastKind, rhsReal,
899 higherPrecisionElementType);
900 rhsImag = builder.
createCast(floatingCastKind, rhsImag,
901 higherPrecisionElementType);
904 builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
909 mlir::Value finalReal =
910 builder.
createCast(floatingCastKind, resultReal, originalElementType);
911 mlir::Value finalImag =
912 builder.
createCast(floatingCastKind, resultImag, originalElementType);
921void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) {
922 cir::CIRBaseBuilderTy builder(getContext());
923 builder.setInsertionPointAfter(op);
924 mlir::Location loc = op.getLoc();
925 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
926 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
932 mlir::Value loweredResult =
934 rhsImag, getContext(), *astCtx);
935 op.replaceAllUsesWith(loweredResult);
939static llvm::StringRef
942 case llvm::APFloat::S_IEEEhalf:
944 case llvm::APFloat::S_IEEEsingle:
946 case llvm::APFloat::S_IEEEdouble:
948 case llvm::APFloat::S_PPCDoubleDouble:
950 case llvm::APFloat::S_x87DoubleExtended:
952 case llvm::APFloat::S_IEEEquad:
955 llvm_unreachable(
"unsupported floating point type");
961 mlir::Location loc, cir::ComplexMulOp op,
962 mlir::Value lhsReal, mlir::Value lhsImag,
963 mlir::Value rhsReal, mlir::Value rhsImag) {
965 bool isFP = cir::isFPOrVectorOfFPType(lhsReal.getType());
966 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
969 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
972 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
976 mlir::Value resultRealLhs = mul(loc, lhsReal, rhsReal);
977 mlir::Value resultRealRhs = mul(loc, lhsImag, rhsImag);
978 mlir::Value resultImagLhs = mul(loc, lhsReal, rhsImag);
979 mlir::Value resultImagRhs = mul(loc, lhsImag, rhsReal);
980 mlir::Value resultReal = sub(loc, resultRealLhs, resultRealRhs);
981 mlir::Value resultImag = add(loc, resultImagLhs, resultImagRhs);
982 mlir::Value algebraicResult =
985 cir::ComplexType complexTy = op.getType();
986 cir::ComplexRangeKind rangeKind = op.getRange();
987 if (mlir::isa<cir::IntType>(complexTy.getElementType()) ||
988 rangeKind == cir::ComplexRangeKind::Basic ||
989 rangeKind == cir::ComplexRangeKind::Improved ||
990 rangeKind == cir::ComplexRangeKind::Promoted)
991 return algebraicResult;
998 mlir::Value resultRealIsNaN = builder.
createIsNaN(loc, resultReal);
999 mlir::Value resultImagIsNaN = builder.
createIsNaN(loc, resultImag);
1000 mlir::Value resultRealAndImagAreNaN =
1003 return cir::TernaryOp::create(
1004 builder, loc, resultRealAndImagAreNaN,
1005 [&](mlir::OpBuilder &, mlir::Location) {
1008 lhsReal, lhsImag, rhsReal, rhsImag);
1011 [&](mlir::OpBuilder &, mlir::Location) {
1017void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
1018 cir::CIRBaseBuilderTy builder(getContext());
1019 builder.setInsertionPointAfter(op);
1020 mlir::Location loc = op.getLoc();
1021 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
1022 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
1027 mlir::Value loweredResult =
lowerComplexMul(*
this, builder, loc, op, lhsReal,
1028 lhsImag, rhsReal, rhsImag);
1029 op.replaceAllUsesWith(loweredResult);
1033void LoweringPreparePass::lowerComplexConjOp(cir::ComplexConjOp op) {
1034 mlir::Location loc = op.getLoc();
1035 CIRBaseBuilderTy builder(getContext());
1036 builder.setInsertionPointAfter(op);
1038 mlir::Value operand = op.getOperand();
1043 const bool isFP = cir::isFPOrVectorOfFPType(operandReal.getType());
1044 mlir::Value resultImag = isFP ? builder.
createFNeg(loc, operandImag)
1047 mlir::Value result =
1049 op->replaceAllUsesWith(mlir::ValueRange{result});
1053cir::FuncOp LoweringPreparePass::getOrCreateDtorFunc(CIRBaseBuilderTy &builder,
1055 mlir::Region &dtorRegion,
1056 cir::CallOp &dtorCall) {
1057 mlir::OpBuilder::InsertionGuard guard(builder);
1060 cir::VoidType voidTy = builder.
getVoidTy();
1061 auto voidPtrTy = cir::PointerType::get(voidTy);
1064 mlir::Block &dtorBlock = dtorRegion.front();
1068 auto opIt = dtorBlock.getOperations().begin();
1069 cir::GetGlobalOp ggop = mlir::cast<cir::GetGlobalOp>(*opIt);
1080 if (dtorBlock.getOperations().size() == 3) {
1081 auto callOp = mlir::dyn_cast<cir::CallOp>(&*(++opIt));
1082 auto yieldOp = mlir::dyn_cast<cir::YieldOp>(&*(++opIt));
1083 if (yieldOp && callOp && callOp.getNumOperands() == 1 &&
1084 callOp.getArgOperand(0) == ggop) {
1086 return getCalledFunction(callOp);
1093 builder.setInsertionPointAfter(op);
1094 SmallString<256> fnName(
"__cxx_global_array_dtor");
1095 uint32_t cnt = dynamicInitializerNames[fnName]++;
1097 fnName +=
"." + std::to_string(cnt);
1100 auto fnType = cir::FuncType::get({voidPtrTy}, voidTy);
1101 cir::FuncOp dtorFunc =
1102 buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1103 cir::GlobalLinkageKind::InternalLinkage);
1105 SmallVector<mlir::NamedAttribute> paramAttrs;
1106 paramAttrs.push_back(
1107 builder.getNamedAttr(
"llvm.noundef", builder.getUnitAttr()));
1108 SmallVector<mlir::Attribute> argAttrDicts;
1109 argAttrDicts.push_back(
1110 mlir::DictionaryAttr::get(builder.getContext(), paramAttrs));
1111 dtorFunc.setArgAttrsAttr(
1112 mlir::ArrayAttr::get(builder.getContext(), argAttrDicts));
1114 mlir::Block *entryBB = dtorFunc.addEntryBlock();
1117 entryBB->getOperations().splice(entryBB->begin(), dtorBlock.getOperations(),
1118 dtorBlock.begin(), dtorBlock.end());
1121 cir::GetGlobalOp dtorGGop =
1122 mlir::cast<cir::GetGlobalOp>(entryBB->getOperations().front());
1123 builder.setInsertionPointToStart(&dtorBlock);
1124 builder.clone(*dtorGGop.getOperation());
1128 mlir::Value dtorArg = entryBB->getArgument(0);
1129 dtorGGop.replaceAllUsesWith(dtorArg);
1133 mlir::Block &finalBlock = dtorFunc.getBody().back();
1134 auto yieldOp = cast<cir::YieldOp>(finalBlock.getTerminator());
1135 builder.setInsertionPoint(yieldOp);
1136 cir::ReturnOp::create(builder, yieldOp->getLoc());
1141 cir::GetGlobalOp origGGop =
1142 mlir::cast<cir::GetGlobalOp>(dtorBlock.getOperations().front());
1143 builder.setInsertionPointAfter(origGGop);
1144 mlir::Value ggopResult = origGGop.getResult();
1145 dtorCall = builder.
createCallOp(op.getLoc(), dtorFunc, ggopResult);
1148 auto finalYield = cir::YieldOp::create(builder, op.getLoc());
1151 dtorBlock.getOperations().erase(std::next(mlir::Block::iterator(finalYield)),
1153 dtorRegion.getBlocks().erase(std::next(dtorRegion.begin()), dtorRegion.end());
1159LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op) {
1162 SmallString<256> fnName(
"__cxx_global_var_init");
1164 uint32_t cnt = dynamicInitializerNames[fnName]++;
1166 fnName +=
"." + std::to_string(cnt);
1169 CIRBaseBuilderTy builder(getContext());
1170 builder.setInsertionPointAfter(op);
1171 cir::VoidType voidTy = builder.
getVoidTy();
1172 auto fnType = cir::FuncType::get({}, voidTy);
1173 FuncOp f = buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1174 cir::GlobalLinkageKind::InternalLinkage);
1182 mlir::Block *entryBB = f.addEntryBlock();
1183 builder.setInsertionPointToStart(entryBB);
1187 bool needsTlsGuard = op.getDynTlsRefs() && op.getDynTlsRefs()->getGuardName();
1189 if (needsTlsGuard) {
1190 guardIf = buildGlobalTlsGuardCheck(
1191 builder, op.getLoc(),
1192 getOrCreateStaticLocalDeclGuardAddress(
1193 builder, op, op.getDynTlsRefs()->getGuardName().getValue(),
1195 op.hasInternalLinkage()));
1196 builder.setInsertionPointToEnd(&guardIf.getThenRegion().front());
1199 if (!op.getCtorRegion().empty()) {
1200 mlir::Block &block = op.getCtorRegion().front();
1201 mlir::Block *insertBlock = builder.getBlock();
1202 insertBlock->getOperations().splice(insertBlock->end(),
1203 block.getOperations(), block.begin(),
1204 std::prev(block.end()));
1208 mlir::Region &dtorRegion = op.getDtorRegion();
1209 if (!dtorRegion.empty()) {
1212 emitGlobalGuardedDtorRegion(builder, op, dtorRegion,
1213 op.getTlsModel().has_value(),
1214 *builder.getBlock());
1218 if (needsTlsGuard) {
1219 builder.setInsertionPointToEnd(&guardIf.getThenRegion().back());
1220 cir::YieldOp::create(builder, op.getLoc());
1224 builder.setInsertionPointToEnd(entryBB);
1225 mlir::Operation *yieldOp =
nullptr;
1226 if (!op.getCtorRegion().empty()) {
1227 mlir::Block &block = op.getCtorRegion().front();
1228 yieldOp = &block.getOperations().back();
1230 assert(!dtorRegion.empty());
1231 mlir::Block &block = dtorRegion.front();
1232 yieldOp = &block.getOperations().back();
1235 assert(isa<cir::YieldOp>(*yieldOp));
1236 cir::ReturnOp::create(builder, yieldOp->getLoc());
1241LoweringPreparePass::getGuardAcquireFn(cir::PointerType guardPtrTy) {
1243 CIRBaseBuilderTy builder(getContext());
1244 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1245 builder.setInsertionPointToStart(mlirModule.getBody());
1246 mlir::Location loc = mlirModule.getLoc();
1247 cir::IntType intTy = cir::IntType::get(&getContext(), 32,
true);
1248 auto fnType = cir::FuncType::get({guardPtrTy}, intTy);
1249 return buildRuntimeFunction(builder,
"__cxa_guard_acquire", loc, fnType);
1253LoweringPreparePass::getGuardReleaseFn(cir::PointerType guardPtrTy) {
1255 CIRBaseBuilderTy builder(getContext());
1256 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1257 builder.setInsertionPointToStart(mlirModule.getBody());
1258 mlir::Location loc = mlirModule.getLoc();
1259 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1260 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1261 return buildRuntimeFunction(builder,
"__cxa_guard_release", loc, fnType);
1264cir::FuncOp LoweringPreparePass::getTlsInitFn() {
1266 CIRBaseBuilderTy builder(getContext());
1267 mlir::OpBuilder::InsertionGuard _{builder};
1268 builder.setInsertionPointToStart(mlirModule.getBody());
1269 mlir::Location loc = mlirModule.getLoc();
1271 return buildRuntimeFunction(builder,
"__tls_init", loc, fnType,
1272 cir::GlobalLinkageKind::InternalLinkage);
1275cir::GlobalOp LoweringPreparePass::createGuardGlobalOp(
1276 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef name,
1277 cir::IntType guardTy, cir::GlobalLinkageKind linkage) {
1278 mlir::OpBuilder::InsertionGuard guard(builder);
1279 builder.setInsertionPointToStart(mlirModule.getBody());
1280 cir::GlobalOp g = cir::GlobalOp::create(builder, loc, name, guardTy);
1282 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1283 mlir::SymbolTable::setSymbolVisibility(
1284 g, mlir::SymbolTable::Visibility::Private);
1288void LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
1289 cir::LocalInitOp localInitOp) {
1290 CIRBaseBuilderTy builder(getContext());
1292 std::optional<cir::ASTVarDeclInterface> astOption = globalOp.getAst();
1293 assert(astOption.has_value());
1294 cir::ASTVarDeclInterface
varDecl = astOption.value();
1296 builder.setInsertionPointAfter(localInitOp);
1297 mlir::Block *localInitBlock = builder.getInsertionBlock();
1300 mlir::Operation *ret = localInitBlock->getTerminator();
1304 builder.setInsertionPointAfter(localInitOp);
1308 bool nonTemplateInline =
1314 if (nonTemplateInline) {
1315 globalOp->emitError(
1316 "NYI: guarded initialization for inline namespace-scope variables");
1323 bool threadsafe = astCtx->
getLangOpts().ThreadsafeStatics &&
1324 (
varDecl.isLocalVarDecl() || nonTemplateInline) &&
1329 bool useInt8GuardVariable = !threadsafe && globalOp.hasInternalLinkage();
1332 cir::GlobalOp guard = getOrCreateStaticLocalDeclGuardAddress(
1333 builder, globalOp, globalOp.getStaticLocalGuard()->getName().getValue(),
1334 varDecl.isLocalVarDecl(), useInt8GuardVariable);
1337 localInitBlock->push_back(ret);
1341 mlir::Value guardPtr = builder.
createGetGlobal(guard, localInitOp.getTls());
1363 unsigned maxInlineWidthInBits =
1366 if (!threadsafe || maxInlineWidthInBits) {
1368 auto bytePtrTy = cir::PointerType::get(builder.
getSIntNTy(8));
1369 mlir::Value bytePtr = builder.
createBitcast(guardPtr, bytePtrTy);
1371 localInitOp.getLoc(), bytePtr, *guard.getAlignment());
1380 auto loadOp = mlir::cast<cir::LoadOp>(guardLoad.getDefiningOp());
1381 loadOp.setMemOrder(cir::MemOrder::Acquire);
1382 loadOp.setSyncScope(cir::SyncScopeKind::System);
1405 if (useARMGuardVarABI() && !useInt8GuardVariable) {
1407 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()),
1409 guardLoad = builder.
createAnd(localInitOp.getLoc(), guardLoad, one);
1414 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()), 0);
1415 auto needsInit = builder.
createCompare(localInitOp.getLoc(),
1416 cir::CmpOpKind::eq, guardLoad, zero);
1420 builder, globalOp.getLoc(), needsInit,
1421 false, [&](mlir::OpBuilder &, mlir::Location) {
1422 emitCXXGuardedInitIf(builder, globalOp, localInitOp.getCtorRegion(),
1423 localInitOp.getDtorRegion(), varDecl, guardPtr,
1424 builder.getPointerTo(guard.getSymType()),
1430 globalOp->emitError(
"NYI: guarded init without inline atomics support");
1435 builder.getInsertionBlock()->push_back(ret);
1438void LoweringPreparePass::lowerLocalInitOp(cir::LocalInitOp initOp) {
1441 if (initOp.getCtorRegion().empty() && initOp.getDtorRegion().empty()) {
1446 cir::GlobalOp globalOp = initOp.getReferencedGlobal(symbolTables);
1447 assert(globalOp &&
"No global-op found");
1449 handleStaticLocal(globalOp, initOp);
1456 return tls == cir::TLS_Model::GeneralDynamic &&
1460static cir::GlobalLinkageKind
1463 return op.getLinkage();
1468 return op.getLinkage();
1472 if (op.isDeclaration())
1473 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1474 return cir::GlobalLinkageKind::WeakODRLinkage;
1478LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
1480 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1481 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1483 mlir::StringAttr wrapperName = op.getDynTlsRefs()->getWrapperName();
1485 auto existingWrapperIter = threadLocalWrappers.find(wrapperName.getValue());
1486 if (existingWrapperIter != threadLocalWrappers.end())
1487 return existingWrapperIter->second;
1490 auto funcType = cir::FuncType::get({}, builder.
getPointerTo(op.getSymType()));
1492 cir::FuncOp::create(builder, op.getLoc(), wrapperName, funcType);
1494 cir::GlobalLinkageKind linkageKind =
1496 func.setLinkageAttr(
1497 cir::GlobalLinkageKindAttr::get(&getContext(), linkageKind));
1502 func.isWeakForLinker())
1503 func.setComdat(
true);
1505 mlir::SymbolTable::setSymbolVisibility(
1506 func, mlir::SymbolTable::Visibility::Private);
1511 op.getGlobalVisibility() == cir::VisibilityKind::Hidden)
1512 func.setGlobalVisibility(cir::VisibilityKind::Hidden);
1515 op->emitError(
"Unhandled thread wrapper attributes for CC and Nounwind");
1517 threadLocalWrappers.insert({wrapperName.getValue(), func});
1521void LoweringPreparePass::defineGlobalThreadLocalWrapper(cir::GlobalOp op,
1522 cir::FuncOp initAlias,
1523 bool isVarDefinition) {
1524 CIRBaseBuilderTy builder(getContext());
1525 cir::FuncOp wrapper = getOrCreateThreadLocalWrapper(builder, op);
1526 mlir::Block *entryBB = wrapper.addEntryBlock();
1527 builder.setInsertionPointToStart(entryBB);
1531 mlir::Location aliasLoc = initAlias.getLoc();
1532 if (!isVarDefinition) {
1534 mlir::Value funcLoad = cir::GetGlobalOp::create(
1535 builder, aliasLoc, cir::PointerType::get(initAlias.getFunctionType()),
1536 initAlias.getSymName());
1537 mlir::Value nullCheck =
1539 mlir::Value cmp = cir::CmpOp::create(
1540 builder, aliasLoc, cir::CmpOpKind::ne, funcLoad, nullCheck);
1541 cir::IfOp::create(builder, aliasLoc, cmp,
false,
1542 [&](mlir::OpBuilder &, mlir::Location loc) {
1544 cir::YieldOp::create(builder, aliasLoc);
1553 cir::ReturnOp::create(builder, op.getLoc(), {get});
1557LoweringPreparePass::defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
1558 cir::FuncOp aliasee) {
1559 CIRBaseBuilderTy builder(getContext());
1560 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1561 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1562 mlir::StringAttr aliasName = op.getDynTlsRefs()->getInitName();
1563 auto existingAliasIter = threadLocalInitAliases.find(aliasName.getValue());
1565 if (existingAliasIter != threadLocalInitAliases.end())
1566 return existingAliasIter->second;
1570 cir::FuncOp::create(builder, op.getLoc(), aliasName, funcType);
1571 alias.setLinkage(op.getLinkage());
1574 alias.setAliasee(aliasee.getSymName());
1579 alias.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1580 mlir::SymbolTable::setSymbolVisibility(
1581 alias, mlir::SymbolTable::Visibility::Private);
1584 threadLocalInitAliases.insert({aliasName.getValue(), alias});
1588void LoweringPreparePass::lowerGlobalOp(GlobalOp op) {
1590 if (op.getStaticLocalGuard())
1593 mlir::Region &ctorRegion = op.getCtorRegion();
1594 mlir::Region &dtorRegion = op.getDtorRegion();
1595 cir::FuncOp initAlias;
1597 if (!ctorRegion.empty() || !dtorRegion.empty()) {
1600 cir::FuncOp f = buildCXXGlobalVarDeclInitFunc(op);
1603 ctorRegion.getBlocks().clear();
1604 dtorRegion.getBlocks().clear();
1607 if (op.getTlsModel() == TLS_Model::GeneralDynamic &&
1608 !op.getStaticLocalGuard().has_value()) {
1620 if (op.getDynTlsRefs()->getGuardName()) {
1622 initAlias = defineGlobalThreadLocalInitAlias(op, f);
1625 initAlias = defineGlobalThreadLocalInitAlias(op, getTlsInitFn());
1629 globalThreadLocalInitializers.push_back(f);
1632 dynamicInitializers.push_back(f);
1634 }
else if (op.getTlsModel() == TLS_Model::GeneralDynamic &&
1635 op.getDynTlsRefs() && op.isDeclaration()) {
1638 initAlias = defineGlobalThreadLocalInitAlias(op, {});
1644 if (op.getTlsModel() == TLS_Model::GeneralDynamic && op.getDynTlsRefs())
1645 defineGlobalThreadLocalWrapper(op, initAlias, !op.isDeclaration());
1650void LoweringPreparePass::lowerGetGlobalOp(GetGlobalOp op) {
1653 auto globalOp = mlir::cast<cir::GlobalOp>(
1654 symbolTables.lookupNearestSymbolFrom(op, op.getNameAttr()));
1660 if (globalOp.getTlsModel() != TLS_Model::GeneralDynamic ||
1661 !globalOp.getDynTlsRefs())
1679 mlir::Operation *parentOp = op->getParentOp();
1680 if (parentOp == globalOp) {
1681 mlir::Region *ctorRegion = &globalOp.getCtorRegion();
1682 mlir::Region *dtorRegion = &globalOp.getDtorRegion();
1684 if (!ctorRegion->empty() && &*ctorRegion->op_begin() == op.getOperation())
1686 if (!dtorRegion->empty() && &*dtorRegion->op_begin() == op.getOperation())
1690 CIRBaseBuilderTy builder(getContext());
1691 cir::FuncOp wrapperFunc = getOrCreateThreadLocalWrapper(builder, globalOp);
1693 builder.setInsertionPoint(op);
1695 wrapperFunc.getLoc(),
1696 mlir::FlatSymbolRefAttr::get(wrapperFunc.getSymNameAttr()),
1697 wrapperFunc.getFunctionType().getReturnType(), {});
1698 op->replaceAllUsesWith(call);
1702void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
1703 CIRBaseBuilderTy builder(getContext());
1704 builder.setInsertionPointAfter(op);
1706 mlir::Location loc = op->getLoc();
1707 cir::CmpThreeWayInfoAttr cmpInfo = op.getInfo();
1716 mlir::Value transformedResult;
1717 if (cmpInfo.getOrdering() != CmpOrdering::Partial) {
1720 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1721 mlir::Value selectOnLt = builder.
createSelect(loc, lt, ltRes, gtRes);
1723 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1724 transformedResult = builder.
createSelect(loc, eq, eqRes, selectOnLt);
1728 loc, op.getType(), cmpInfo.getUnordered().value());
1731 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1732 mlir::Value selectOnEq = builder.
createSelect(loc, eq, eqRes, unorderedRes);
1734 builder.
createCompare(loc, CmpOpKind::gt, op.getLhs(), op.getRhs());
1735 mlir::Value selectOnGt = builder.
createSelect(loc, gt, gtRes, selectOnEq);
1737 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1738 transformedResult = builder.
createSelect(loc, lt, ltRes, selectOnGt);
1741 op.replaceAllUsesWith(transformedResult);
1745template <
typename AttributeTy>
1746static llvm::SmallVector<mlir::Attribute>
1750 for (
const auto &[name, priority] : list)
1751 attrs.push_back(AttributeTy::get(context, name, priority));
1755void LoweringPreparePass::buildGlobalCtorDtorList() {
1756 if (!globalCtorList.empty()) {
1757 llvm::SmallVector<mlir::Attribute> globalCtors =
1761 mlirModule->setAttr(cir::CIRDialect::getGlobalCtorsAttrName(),
1762 mlir::ArrayAttr::get(&getContext(), globalCtors));
1765 if (!globalDtorList.empty()) {
1766 llvm::SmallVector<mlir::Attribute> globalDtors =
1769 mlirModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(),
1770 mlir::ArrayAttr::get(&getContext(), globalDtors));
1775LoweringPreparePass::createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
1776 mlir::Location loc) {
1777 mlir::OpBuilder::InsertionGuard guard(builder);
1778 builder.setInsertionPointToStart(mlirModule.getBody());
1781 cir::IntType guardTy = builder.
getSIntNTy(8);
1782 auto g = cir::GlobalOp::create(builder, loc,
"__tls_guard", guardTy);
1783 g.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
1784 builder.getContext(), cir::GlobalLinkageKind::InternalLinkage));
1788 g.setTlsModel(TLS_Model::GeneralDynamic);
1789 g.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
1793cir::IfOp LoweringPreparePass::buildGlobalTlsGuardCheck(
1794 CIRBaseBuilderTy &builder, mlir::Location loc, cir::GlobalOp guard) {
1796 mlir::Value getGuardValue = getGuard;
1801 if (guard.getSymType() != builder.
getSIntNTy(8))
1803 getGuard, cir::PointerType::get(builder.
getSIntNTy(8)));
1805 mlir::Value guardLoad =
1809 builder.
createCompare(loc, cir::CmpOpKind::eq, guardLoad, zero);
1810 return cir::IfOp::create(
1812 false, [&](mlir::OpBuilder &, mlir::Location loc) {
1816 loc, builder.
getConstantInt(loc, guard.getSymType(), 1), getGuard);
1820void LoweringPreparePass::buildCXXGlobalTlsFunc() {
1821 if (globalThreadLocalInitializers.empty())
1827 cir::FuncOp tlsInit = getTlsInitFn();
1828 mlir::Location loc = tlsInit.getLoc();
1829 CIRBaseBuilderTy builder(getContext());
1830 mlir::Block *entryBB = tlsInit.addEntryBlock();
1831 builder.setInsertionPointToStart(entryBB);
1833 cir::IfOp ifOperation = buildGlobalTlsGuardCheck(
1834 builder, loc, createGlobalThreadLocalGuard(builder, loc));
1837 builder.setInsertionPointToEnd(&ifOperation.getThenRegion().front());
1838 for (cir::FuncOp initFunc : globalThreadLocalInitializers)
1840 cir::YieldOp::create(builder, loc);
1842 builder.setInsertionPointAfter(ifOperation);
1843 cir::ReturnOp::create(builder, loc);
1846void LoweringPreparePass::buildCXXGlobalInitFunc() {
1847 if (dynamicInitializers.empty())
1854 SmallString<256> fnName;
1855 cir::GlobalLinkageKind linkage;
1863 llvm::raw_svector_ostream
out(fnName);
1864 std::unique_ptr<clang::MangleContext> mangleCtx(
1866 cast<clang::ItaniumMangleContext>(*mangleCtx)
1868 linkage = cir::GlobalLinkageKind::ExternalLinkage;
1870 fnName +=
"_GLOBAL__sub_I_";
1872 linkage = cir::GlobalLinkageKind::InternalLinkage;
1875 CIRBaseBuilderTy builder(getContext());
1876 builder.setInsertionPointToEnd(&mlirModule.getBodyRegion().back());
1877 auto fnType = cir::FuncType::get({}, builder.
getVoidTy());
1878 cir::FuncOp f = buildRuntimeFunction(builder, fnName, mlirModule.getLoc(),
1880 builder.setInsertionPointToStart(f.addEntryBlock());
1881 for (cir::FuncOp &f : dynamicInitializers)
1885 globalCtorList.emplace_back(fnName,
1886 cir::GlobalCtorAttr::getDefaultPriority());
1888 cir::ReturnOp::create(builder, f.getLoc());
1897 mlir::Operation *op, mlir::Type eltTy,
1899 mlir::Value numElements,
1900 uint64_t arrayLen,
bool isCtor) {
1901 mlir::Location loc = op->getLoc();
1902 bool isDynamic = numElements !=
nullptr;
1906 const unsigned sizeTypeSize =
1912 mlir::Value begin, end;
1915 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, numElements);
1917 mlir::Value endOffsetVal =
1919 begin = cir::CastOp::create(builder, loc, eltTy,
1920 cir::CastKind::array_to_ptrdecay, addr);
1921 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
1924 mlir::Value start = isCtor ? begin : end;
1925 mlir::Value stop = isCtor ? end : begin;
1931 mlir::Value guardCond;
1934 guardCond = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
1940 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, start, stop);
1942 ifOp = cir::IfOp::create(builder, loc, guardCond,
1944 [&](mlir::OpBuilder &, mlir::Location) {});
1945 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1948 mlir::Value tmpAddr =
1953 mlir::Block *bodyBlock = &op->getRegion(0).front();
1958 auto cloneRegionBodyInto = [&](mlir::Block *srcBlock,
1959 mlir::Value replacement) {
1960 mlir::IRMapping map;
1961 map.map(srcBlock->getArgument(0), replacement);
1962 for (mlir::Operation ®ionOp : *srcBlock) {
1963 if (!mlir::isa<cir::YieldOp>(®ionOp))
1964 builder.clone(regionOp, map);
1968 mlir::Block *partialDtorBlock =
nullptr;
1969 if (
auto arrayCtor = mlir::dyn_cast<cir::ArrayCtor>(op)) {
1970 mlir::Region &partialDtor = arrayCtor.getPartialDtor();
1971 if (!partialDtor.empty())
1972 partialDtorBlock = &partialDtor.front();
1973 }
else if (
auto arrayDtor = mlir::dyn_cast<cir::ArrayDtor>(op)) {
1982 if (arrayDtor.getDtorMayThrow())
1983 partialDtorBlock = bodyBlock;
1986 auto emitCtorDtorLoop = [&]() {
1990 [&](mlir::OpBuilder &b, mlir::Location loc) {
1991 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
1992 auto cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
1993 currentElement, stop);
1997 [&](mlir::OpBuilder &b, mlir::Location loc) {
1998 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2000 cloneRegionBodyInto(bodyBlock, currentElement);
2001 mlir::Value stride = builder.
getUnsignedInt(loc, 1, sizeTypeSize);
2002 auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2003 currentElement, stride);
2006 mlir::Value stride = builder.
getSignedInt(loc, -1, sizeTypeSize);
2007 auto prevElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2008 currentElement, stride);
2010 cloneRegionBodyInto(bodyBlock, prevElement);
2013 cir::YieldOp::create(b, loc);
2017 if (partialDtorBlock) {
2018 cir::CleanupScopeOp::create(
2019 builder, loc, cir::CleanupKind::EH,
2021 [&](mlir::OpBuilder &b, mlir::Location loc) {
2023 cir::YieldOp::create(b, loc);
2026 [&](mlir::OpBuilder &b, mlir::Location loc) {
2027 auto cur = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2029 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, cur, begin);
2031 builder, loc, cmp,
false,
2032 [&](mlir::OpBuilder &b, mlir::Location loc) {
2036 [&](mlir::OpBuilder &b, mlir::Location loc) {
2037 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2038 auto neq = cir::CmpOp::create(
2039 builder, loc, cir::CmpOpKind::ne, el, begin);
2043 [&](mlir::OpBuilder &b, mlir::Location loc) {
2044 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2045 mlir::Value negOne =
2047 auto prev = cir::PtrStrideOp::create(builder, loc, eltTy,
2050 cloneRegionBodyInto(partialDtorBlock, prev);
2053 cir::YieldOp::create(builder, loc);
2055 cir::YieldOp::create(b, loc);
2062 cir::YieldOp::create(builder, loc);
2067void LoweringPreparePass::lowerArrayDtor(cir::ArrayDtor op) {
2068 CIRBaseBuilderTy builder(getContext());
2069 builder.setInsertionPointAfter(op.getOperation());
2071 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2073 if (op.getNumElements()) {
2075 op.getNumElements(), 0,
2081 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2087void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
2088 cir::CIRBaseBuilderTy builder(getContext());
2089 builder.setInsertionPointAfter(op.getOperation());
2091 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2093 if (op.getNumElements()) {
2095 op.getNumElements(), 0,
2101 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2107cir::FuncOp LoweringPreparePass::getCalledFunction(cir::CallOp callOp) {
2108 mlir::SymbolRefAttr sym = llvm::dyn_cast_if_present<mlir::SymbolRefAttr>(
2109 callOp.getCallableForCallee());
2112 return symbolTables.lookupNearestSymbolFrom<cir::FuncOp>(callOp, sym);
2115void LoweringPreparePass::lowerTrivialCopyCall(cir::CallOp op) {
2116 cir::FuncOp funcOp = getCalledFunction(op);
2120 std::optional<cir::CtorKind> ctorKind = funcOp.getCxxConstructorKind();
2121 if (ctorKind && *ctorKind == cir::CtorKind::Copy &&
2122 funcOp.isCxxTrivialMemberFunction()) {
2124 CIRBaseBuilderTy builder(getContext());
2125 mlir::ValueRange operands = op.getOperands();
2126 mlir::Value dest = operands[0];
2127 mlir::Value src = operands[1];
2128 builder.setInsertionPoint(op);
2134cir::GlobalOp LoweringPreparePass::getOrCreateConstAggregateGlobal(
2135 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef baseName,
2136 mlir::Type ty, mlir::TypedAttr constant) {
2138 llvm::SmallVector<cir::GlobalOp, 1> &versions =
2139 constAggregateGlobals[baseName];
2142 for (cir::GlobalOp gv : versions) {
2143 if (gv.getSymType() == ty && gv.getInitialValue() == constant)
2151 llvm::SmallString<128>
name(baseName);
2152 size_t baseLen =
name.size();
2153 unsigned version = versions.size();
2155 name.resize(baseLen);
2157 name.push_back(
'.');
2158 llvm::Twine(version).toVector(name);
2160 auto existingGv = symbolTables.lookupSymbolIn<cir::GlobalOp>(
2161 mlirModule, mlir::StringAttr::get(&getContext(), name));
2164 versions.push_back(existingGv);
2165 if (existingGv.getSymType() == ty &&
2166 existingGv.getInitialValue() == constant)
2172 mlir::OpBuilder::InsertionGuard guard(builder);
2173 builder.setInsertionPointToStart(mlirModule.getBody());
2175 cir::GlobalOp::create(builder, loc, name, ty,
2177 cir::LangAddressSpaceAttr::get(
2178 &getContext(), cir::LangAddressSpace::Default),
2179 cir::GlobalLinkageKind::PrivateLinkage);
2180 mlir::SymbolTable::setSymbolVisibility(
2181 gv, mlir::SymbolTable::Visibility::Private);
2182 gv.setInitialValueAttr(constant);
2186 symbolTables.getSymbolTable(mlirModule).insert(gv);
2188 versions.push_back(gv);
2192void LoweringPreparePass::lowerStoreOfConstAggregate(cir::StoreOp op) {
2194 auto constOp = op.getValue().getDefiningOp<cir::ConstantOp>();
2198 mlir::Type ty = constOp.getType();
2199 if (!mlir::isa<cir::ArrayType, cir::RecordType>(ty))
2205 auto alloca = op.getAddr().getDefiningOp<cir::AllocaOp>();
2209 mlir::TypedAttr constant = constOp.getValue();
2220 auto func = op->getParentOfType<cir::FuncOp>();
2223 llvm::StringRef funcName = func.getSymName();
2226 llvm::StringRef varName = alloca.getName();
2229 std::string baseName = (
"__const." + funcName +
"." + varName).str();
2230 CIRBaseBuilderTy builder(getContext());
2234 cir::GlobalOp gv = getOrCreateConstAggregateGlobal(builder, op.getLoc(),
2235 baseName, ty, constant);
2238 builder.setInsertionPoint(op);
2240 auto ptrTy = cir::PointerType::get(ty);
2241 mlir::Value globalPtr =
2242 cir::GetGlobalOp::create(builder, op.getLoc(), ptrTy, gv.getSymName());
2251 if (constOp.use_empty())
2258void LoweringPreparePass::lowerStdOp(cir::StdOpInterface typedOp) {
2259 mlir::Operation *op = typedOp.getOperation();
2260 cir::CIRBaseBuilderTy builder(getContext());
2261 builder.setInsertionPointAfter(op);
2262 mlir::Type resultType;
2263 if (op->getNumResults())
2264 resultType = op->getResult(0).getType();
2266 op->getLoc(), typedOp.getOriginalFnAttr(), resultType, op->getOperands());
2267 for (mlir::NamedAttribute attr : op->getAttrs())
2268 if (
attr.getName() != typedOp.getOriginalFnAttrName())
2269 call->setAttr(
attr.getName(),
attr.getValue());
2271 op->replaceAllUsesWith(call);
2275void LoweringPreparePass::runOnOp(mlir::Operation *op) {
2276 if (
auto arrayCtor = dyn_cast<cir::ArrayCtor>(op)) {
2277 lowerArrayCtor(arrayCtor);
2278 }
else if (
auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) {
2279 lowerArrayDtor(arrayDtor);
2280 }
else if (
auto stdOp = mlir::dyn_cast<cir::StdOpInterface>(op)) {
2282 }
else if (
auto cast = mlir::dyn_cast<cir::CastOp>(op)) {
2284 }
else if (
auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
2285 lowerComplexConjOp(complexConj);
2286 }
else if (
auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
2287 lowerComplexDivOp(complexDiv);
2288 }
else if (
auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
2289 lowerComplexMulOp(complexMul);
2290 }
else if (
auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) {
2291 lowerGlobalOp(glob);
2292 if (
auto regAttr = glob->getAttrOfType<CUDAVarRegistrationInfoAttr>(
2293 CUDAVarRegistrationInfoAttr::getMnemonic()))
2294 cudaDeviceVars.emplace_back(glob, regAttr);
2295 }
else if (
auto getGlob = mlir::dyn_cast<cir::GetGlobalOp>(op)) {
2296 lowerGetGlobalOp(getGlob);
2297 }
else if (
auto callOp = dyn_cast<cir::CallOp>(op)) {
2298 lowerTrivialCopyCall(callOp);
2299 }
else if (
auto storeOp = dyn_cast<cir::StoreOp>(op)) {
2300 lowerStoreOfConstAggregate(storeOp);
2301 }
else if (
auto fnOp = dyn_cast<cir::FuncOp>(op)) {
2302 if (
auto globalCtor = fnOp.getGlobalCtorPriority())
2303 globalCtorList.emplace_back(fnOp.getName(), globalCtor.value());
2304 else if (
auto globalDtor = fnOp.getGlobalDtorPriority())
2305 globalDtorList.emplace_back(fnOp.getName(), globalDtor.value());
2307 if (mlir::Attribute attr =
2308 fnOp->getAttr(cir::CUDAKernelNameAttr::getMnemonic())) {
2309 auto kernelNameAttr = dyn_cast<CUDAKernelNameAttr>(attr);
2310 llvm::StringRef kernelName = kernelNameAttr.getKernelName();
2311 cudaKernelMap[kernelName] = fnOp;
2313 }
else if (
auto threeWayCmp = dyn_cast<cir::CmpThreeWayOp>(op)) {
2314 lowerThreeWayCmpOp(threeWayCmp);
2315 }
else if (
auto initOp = dyn_cast<cir::LocalInitOp>(op)) {
2316 lowerLocalInitOp(initOp);
2327 llvm::StringRef name) {
2328 return (
"__" + prefix + name).str();
2350void LoweringPreparePass::buildCUDAModuleCtor() {
2353 if (astCtx->
getLangOpts().GPURelocatableDeviceCode)
2354 llvm_unreachable(
"GPU RDC NYI");
2358 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2363 mlir::Attribute cudaBinaryHandleAttr =
2364 mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName());
2365 if (!cudaBinaryHandleAttr) {
2371 llvm::StringRef cudaGPUBinaryName =
2372 mlir::cast<CUDABinaryHandleAttr>(cudaBinaryHandleAttr)
2376 llvm::vfs::FileSystem &vfs =
2378 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> gpuBinaryOrErr =
2379 vfs.getBufferForFile(cudaGPUBinaryName);
2380 if (std::error_code ec = gpuBinaryOrErr.getError()) {
2381 mlirModule->emitError(
"cannot open GPU binary file: " + cudaGPUBinaryName +
2382 ": " + ec.message());
2385 std::unique_ptr<llvm::MemoryBuffer> gpuBinary =
2386 std::move(gpuBinaryOrErr.get());
2390 mlir::Location loc = mlirModule->getLoc();
2391 CIRBaseBuilderTy builder(getContext());
2392 builder.setInsertionPointToStart(mlirModule.getBody());
2396 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2398 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2404 llvm::StringRef fatbinConstName =
2405 astCtx->
getLangOpts().HIP ?
".hip_fatbin" :
".nv_fatbin";
2407 llvm::StringRef fatbinSectionName =
2408 astCtx->
getLangOpts().HIP ?
".hipFatBinSegment" :
".nvFatBinSegment";
2412 ArrayType::get(&getContext(), charTy, gpuBinary->getBuffer().size());
2414 GlobalOp fatbinStr = GlobalOp::create(builder, loc, fatbinStrName, fatbinType,
2416 GlobalLinkageKind::PrivateLinkage);
2417 fatbinStr.setAlignment(8);
2418 fatbinStr.setInitialValueAttr(cir::ConstArrayAttr::get(
2419 fatbinType, StringAttr::get(gpuBinary->getBuffer(), fatbinType)));
2420 fatbinStr.setSection(fatbinConstName);
2421 fatbinStr.setPrivate();
2425 auto fatbinWrapperType = cir::StructType::get(
2426 &getContext(), {intTy, intTy, voidPtrTy, voidPtrTy},
2427 false,
false,
false);
2428 std::string fatbinWrapperName =
2430 GlobalOp fatbinWrapper = GlobalOp::create(
2431 builder, loc, fatbinWrapperName, fatbinWrapperType,
2432 true, {}, GlobalLinkageKind::PrivateLinkage);
2433 fatbinWrapper.setSection(fatbinSectionName);
2435 constexpr unsigned cudaFatMagic = 0x466243b1;
2436 constexpr unsigned hipFatMagic = 0x48495046;
2437 unsigned fatMagic =
isHIP ? hipFatMagic : cudaFatMagic;
2439 auto magicInit = IntAttr::get(intTy, fatMagic);
2440 auto versionInit = IntAttr::get(intTy, 1);
2441 auto fatbinStrSymbol =
2442 mlir::FlatSymbolRefAttr::get(fatbinStr.getSymNameAttr());
2443 auto fatbinInit = GlobalViewAttr::get(voidPtrTy, fatbinStrSymbol);
2445 fatbinWrapper.setInitialValueAttr(cir::ConstRecordAttr::get(
2447 mlir::ArrayAttr::get(&getContext(),
2448 {magicInit, versionInit, fatbinInit, unusedInit})));
2451 std::string gpubinHandleName =
2454 GlobalOp gpuBinHandle = GlobalOp::create(
2455 builder, loc, gpubinHandleName, voidPtrPtrTy,
2456 false, {}, cir::GlobalLinkageKind::InternalLinkage);
2458 gpuBinHandle.setPrivate();
2463 std::string regFuncName =
2465 FuncType regFuncType = FuncType::get({voidPtrTy}, voidPtrPtrTy);
2466 cir::FuncOp regFunc =
2467 buildRuntimeFunction(builder, regFuncName, loc, regFuncType);
2470 cir::FuncOp moduleCtor = buildRuntimeFunction(
2471 builder, moduleCtorName, loc, FuncType::get({}, voidTy),
2472 GlobalLinkageKind::InternalLinkage);
2474 globalCtorList.emplace_back(moduleCtorName,
2475 cir::GlobalCtorAttr::getDefaultPriority());
2476 builder.setInsertionPointToStart(moduleCtor.addEntryBlock());
2484 mlir::Block *entryBlock = builder.getInsertionBlock();
2485 mlir::Region *parent = entryBlock->getParent();
2486 mlir::Block *ifBlock = builder.createBlock(parent);
2487 mlir::Block *exitBlock = builder.createBlock(parent);
2489 mlir::OpBuilder::InsertionGuard guard(builder);
2490 builder.setInsertionPointToEnd(entryBlock);
2491 mlir::Value handle =
2493 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2494 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2495 mlir::Value isNull =
2496 builder.
createCompare(loc, cir::CmpOpKind::eq, handle, nullPtr);
2497 cir::BrCondOp::create(builder, loc, isNull, ifBlock, exitBlock);
2501 mlir::OpBuilder::InsertionGuard guard(builder);
2502 builder.setInsertionPointToStart(ifBlock);
2504 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2505 cir::CallOp gpuBinaryHandleCall =
2507 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2509 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2510 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2511 cir::BrOp::create(builder, loc, exitBlock);
2516 mlir::OpBuilder::InsertionGuard guard(builder);
2517 builder.setInsertionPointToStart(exitBlock);
2518 mlir::Value gHandle =
2521 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals())
2524 if (std::optional<FuncOp> dtor = buildHIPModuleDtor()) {
2525 cir::CIRBaseBuilderTy globalBuilder(getContext());
2526 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2527 FuncOp atexit = buildRuntimeFunction(
2528 globalBuilder,
"atexit", loc,
2529 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2530 mlir::Value dtorFunc = GetGlobalOp::create(
2531 builder, loc, PointerType::get(dtor->getFunctionType()),
2532 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2535 cir::ReturnOp::create(builder, loc);
2539 if (!astCtx->
getLangOpts().GPURelocatableDeviceCode) {
2547 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2548 cir::CallOp gpuBinaryHandleCall =
2550 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2552 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2553 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2556 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals()) {
2557 builder.
createCallOp(loc, *regGlobal, gpuBinaryHandle);
2566 cir::CIRBaseBuilderTy globalBuilder(getContext());
2567 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2569 buildRuntimeFunction(globalBuilder,
"__cudaRegisterFatBinaryEnd", loc,
2570 FuncType::get({voidPtrPtrTy}, voidTy));
2574 llvm_unreachable(
"GPU RDC NYI");
2579 if (std::optional<FuncOp> dtor = buildCUDAModuleDtor()) {
2582 cir::CIRBaseBuilderTy globalBuilder(getContext());
2583 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2584 FuncOp atexit = buildRuntimeFunction(
2585 globalBuilder,
"atexit", loc,
2586 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2587 mlir::Value dtorFunc = GetGlobalOp::create(
2588 builder, loc, PointerType::get(dtor->getFunctionType()),
2589 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2592 cir::ReturnOp::create(builder, loc);
2595std::optional<FuncOp> LoweringPreparePass::buildCUDAModuleDtor() {
2596 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2601 VoidType voidTy = VoidType::get(&getContext());
2602 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2604 mlir::Location loc = mlirModule.getLoc();
2606 cir::CIRBaseBuilderTy builder(getContext());
2607 builder.setInsertionPointToStart(mlirModule.getBody());
2610 std::string unregisterFuncName =
2612 FuncOp unregisterFunc = buildRuntimeFunction(
2613 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2622 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2623 GlobalLinkageKind::InternalLinkage);
2625 builder.setInsertionPointToStart(dtor.addEntryBlock());
2631 GlobalOp gpubinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2633 mlir::Value gpubin = builder.
createLoad(loc, gpubinAddress);
2635 ReturnOp::create(builder, loc);
2652std::optional<FuncOp> LoweringPreparePass::buildHIPModuleDtor() {
2653 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2658 VoidType voidTy = VoidType::get(&getContext());
2659 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2661 mlir::Location loc = mlirModule.getLoc();
2663 cir::CIRBaseBuilderTy builder(getContext());
2664 builder.setInsertionPointToStart(mlirModule.getBody());
2667 std::string unregisterFuncName =
2669 FuncOp unregisterFunc = buildRuntimeFunction(
2670 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2674 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2675 GlobalLinkageKind::InternalLinkage);
2678 GlobalOp gpuBinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2680 mlir::Block *entryBlock = dtor.addEntryBlock();
2681 mlir::Block *ifBlock = builder.createBlock(&dtor.getBody());
2682 mlir::Block *exitBlock = builder.createBlock(&dtor.getBody());
2684 mlir::OpBuilder::InsertionGuard guard(builder);
2685 builder.setInsertionPointToEnd(entryBlock);
2686 mlir::Value handle =
2688 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2689 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2690 mlir::Value isNotNull =
2691 builder.
createCompare(loc, cir::CmpOpKind::ne, handle, nullPtr);
2692 cir::BrCondOp::create(builder, loc, isNotNull, ifBlock, exitBlock);
2696 mlir::OpBuilder::InsertionGuard ifGuard(builder);
2697 builder.setInsertionPointToStart(ifBlock);
2700 cir::BrOp::create(builder, loc, exitBlock);
2703 mlir::OpBuilder::InsertionGuard exitGuard(builder);
2704 builder.setInsertionPointToStart(exitBlock);
2705 cir::ReturnOp::create(builder, loc);
2711std::optional<FuncOp> LoweringPreparePass::buildCUDARegisterGlobals() {
2712 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2715 cir::CIRBaseBuilderTy builder(getContext());
2716 builder.setInsertionPointToStart(mlirModule.getBody());
2718 mlir::Location loc = mlirModule.getLoc();
2721 auto voidTy = VoidType::get(&getContext());
2722 auto voidPtrTy = PointerType::get(voidTy);
2723 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2727 std::string regGlobalFuncName =
2729 auto regGlobalFuncTy = FuncType::get({voidPtrPtrTy}, voidTy);
2730 FuncOp regGlobalFunc =
2731 buildRuntimeFunction(builder, regGlobalFuncName, loc, regGlobalFuncTy,
2732 GlobalLinkageKind::InternalLinkage);
2733 builder.setInsertionPointToStart(regGlobalFunc.addEntryBlock());
2735 buildCUDARegisterGlobalFunctions(builder, regGlobalFunc);
2736 buildCUDARegisterVars(builder, regGlobalFunc);
2738 ReturnOp::create(builder, loc);
2739 return regGlobalFunc;
2742void LoweringPreparePass::buildCUDARegisterGlobalFunctions(
2743 cir::CIRBaseBuilderTy &builder, FuncOp regGlobalFunc) {
2744 mlir::Location loc = mlirModule.getLoc();
2746 cir::CIRDataLayout dataLayout(mlirModule);
2748 auto voidTy = VoidType::get(&getContext());
2749 auto voidPtrTy = PointerType::get(voidTy);
2750 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2752 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2756 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2758 cir::CIRBaseBuilderTy globalBuilder(getContext());
2759 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2773 FuncOp cudaRegisterFunction = buildRuntimeFunction(
2775 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2776 voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy},
2779 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2780 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2781 auto tmpString = cir::GlobalOp::create(
2782 globalBuilder, loc, (
".str" + str).str(), strType,
2784 cir::GlobalLinkageKind::PrivateLinkage);
2787 tmpString.setInitialValueAttr(
2788 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2789 tmpString.setPrivate();
2793 cir::ConstantOp cirNullPtr = builder.
getNullPtr(voidPtrTy, loc);
2795 for (
auto kernelName : cudaKernelMap.keys()) {
2796 FuncOp deviceStub = cudaKernelMap[kernelName];
2797 GlobalOp deviceFuncStr = makeConstantString(kernelName);
2801 mlir::Value hostFunc;
2808 auto funcHandle = cast<GlobalOp>(mlirModule.lookupSymbol(kernelName));
2813 GetGlobalOp::create(
2814 builder, loc, PointerType::get(deviceStub.getFunctionType()),
2815 mlir::FlatSymbolRefAttr::get(deviceStub.getSymNameAttr())),
2819 loc, cudaRegisterFunction,
2820 {fatbinHandle, hostFunc, deviceFunc, deviceFunc,
2821 ConstantOp::create(builder, loc, IntAttr::get(intTy, -1)), cirNullPtr,
2822 cirNullPtr, cirNullPtr, cirNullPtr, cirNullPtr});
2829void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
2830 FuncOp regGlobalFunc) {
2831 mlir::Location loc = mlirModule.getLoc();
2833 cir::CIRDataLayout dataLayout(mlirModule);
2836 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2840 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2843 if (cudaDeviceVars.empty())
2846 cir::CIRBaseBuilderTy globalBuilder(getContext());
2847 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2854 cir::VoidType voidTy = builder.
getVoidTy();
2855 FuncOp cudaRegisterVar = buildRuntimeFunction(
2857 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2858 sizeTy, intTy, intTy},
2861 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2862 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2863 auto tmpString = cir::GlobalOp::create(
2864 globalBuilder, loc, (
".str" + str).str(), strType,
2866 cir::GlobalLinkageKind::PrivateLinkage);
2867 tmpString.setInitialValueAttr(
2868 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2869 tmpString.setPrivate();
2873 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2875 for (
auto &[global, regAttr] : cudaDeviceVars) {
2876 switch (regAttr.getKind()) {
2877 case cir::CUDADeviceVarKind::Variable:
2879 case cir::CUDADeviceVarKind::Surface:
2880 llvm_unreachable(
"Surface registration NYI");
2881 case cir::CUDADeviceVarKind::Texture:
2882 llvm_unreachable(
"Texture registration NYI");
2885 if (regAttr.getIsManaged())
2886 llvm_unreachable(
"Managed variable registration NYI");
2888 GlobalOp deviceNameStr = makeConstantString(regAttr.getDeviceSideName());
2891 mlir::Value hostVar =
2894 auto isExtern = ConstantOp::create(
2895 builder, loc, IntAttr::get(intTy, regAttr.getIsExtern() ? 1 : 0));
2896 llvm::TypeSize size = dataLayout.getTypeAllocSize(global.getSymType());
2897 auto varSize = ConstantOp::create(
2898 builder, loc, IntAttr::get(sizeTy, size.getFixedValue()));
2899 auto isConstant = ConstantOp::create(
2900 builder, loc, IntAttr::get(intTy, regAttr.getIsConstant() ? 1 : 0));
2901 auto normalized = ConstantOp::create(builder, loc, IntAttr::get(intTy, 0));
2903 {fatbinHandle, hostVar, deviceName, deviceName,
2904 isExtern, varSize, isConstant, normalized});
2908void LoweringPreparePass::runOnOperation() {
2909 mlir::Operation *op = getOperation();
2910 if (isa<::mlir::ModuleOp>(op))
2911 mlirModule = cast<::mlir::ModuleOp>(op);
2913 llvm::SmallVector<mlir::Operation *> opsToTransform;
2915 op->walk([&](mlir::Operation *op) {
2916 if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
2917 cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
2918 cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
2919 cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
2920 cir::CmpThreeWayOp, cir::LocalInitOp, cir::StdOpInterface>(
2922 opsToTransform.push_back(op);
2925 for (mlir::Operation *o : opsToTransform)
2928 buildCXXGlobalInitFunc();
2929 buildCXXGlobalTlsFunc();
2931 buildCUDAModuleCtor();
2933 buildGlobalCtorDtorList();
2937 return std::make_unique<LoweringPreparePass>();
2940std::unique_ptr<Pass>
2942 auto pass = std::make_unique<LoweringPreparePass>();
2943 pass->setASTContext(astCtx);
2944 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.
const internal::VariadicAllOfMatcher< Attr > attr
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()