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))
817 return info.getHalfFormat();
819 if (mlir::isa<cir::BF16Type>(type))
820 return info.getBFloat16Format();
822 if (mlir::isa<cir::SingleType>(type))
823 return info.getFloatFormat();
825 if (mlir::isa<cir::DoubleType>(type))
826 return info.getDoubleFormat();
828 if (mlir::isa<cir::LongDoubleType>(type)) {
830 llvm_unreachable(
"NYI Float type semantics with OpenMP");
831 return info.getLongDoubleFormat();
834 if (mlir::isa<cir::FP128Type>(type)) {
836 llvm_unreachable(
"NYI Float type semantics with OpenMP");
837 return info.getFloat128Format();
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);
1179 if (op.getStrictfp()) {
1180 f->setAttr(cir::CIRDialect::getStrictFPAttrName(),
1181 mlir::UnitAttr::get(&getContext()));
1182 op.setStrictfp(
false);
1191 mlir::Block *entryBB = f.addEntryBlock();
1192 builder.setInsertionPointToStart(entryBB);
1196 bool needsTlsGuard = op.getTlsRefs() && op.getTlsRefs()->getGuardName();
1198 if (needsTlsGuard) {
1199 guardIf = buildGlobalTlsGuardCheck(
1200 builder, op.getLoc(),
1201 getOrCreateStaticLocalDeclGuardAddress(
1202 builder, op, op.getTlsRefs()->getGuardName().getValue(),
1204 op.hasInternalLinkage()));
1205 builder.setInsertionPointToEnd(&guardIf.getThenRegion().front());
1208 if (!op.getCtorRegion().empty()) {
1209 mlir::Block &block = op.getCtorRegion().front();
1210 mlir::Block *insertBlock = builder.getBlock();
1211 insertBlock->getOperations().splice(insertBlock->end(),
1212 block.getOperations(), block.begin(),
1213 std::prev(block.end()));
1217 mlir::Region &dtorRegion = op.getDtorRegion();
1218 if (!dtorRegion.empty()) {
1221 emitGlobalGuardedDtorRegion(builder, op, dtorRegion,
1222 op.getTlsModel().has_value(),
1223 *builder.getBlock());
1227 if (needsTlsGuard) {
1228 builder.setInsertionPointToEnd(&guardIf.getThenRegion().back());
1229 cir::YieldOp::create(builder, op.getLoc());
1233 builder.setInsertionPointToEnd(entryBB);
1234 mlir::Operation *yieldOp =
nullptr;
1235 if (!op.getCtorRegion().empty()) {
1236 mlir::Block &block = op.getCtorRegion().front();
1237 yieldOp = &block.getOperations().back();
1239 assert(!dtorRegion.empty());
1240 mlir::Block &block = dtorRegion.front();
1241 yieldOp = &block.getOperations().back();
1244 assert(isa<cir::YieldOp>(*yieldOp));
1245 cir::ReturnOp::create(builder, yieldOp->getLoc());
1250LoweringPreparePass::getGuardAcquireFn(cir::PointerType guardPtrTy) {
1252 CIRBaseBuilderTy builder(getContext());
1253 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1254 builder.setInsertionPointToStart(mlirModule.getBody());
1255 mlir::Location loc = mlirModule.getLoc();
1256 cir::IntType intTy = cir::IntType::get(&getContext(), 32,
true);
1257 auto fnType = cir::FuncType::get({guardPtrTy}, intTy);
1258 return buildRuntimeFunction(builder,
"__cxa_guard_acquire", loc, fnType);
1262LoweringPreparePass::getGuardReleaseFn(cir::PointerType guardPtrTy) {
1264 CIRBaseBuilderTy builder(getContext());
1265 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1266 builder.setInsertionPointToStart(mlirModule.getBody());
1267 mlir::Location loc = mlirModule.getLoc();
1268 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1269 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1270 return buildRuntimeFunction(builder,
"__cxa_guard_release", loc, fnType);
1273cir::FuncOp LoweringPreparePass::getTlsInitFn() {
1275 CIRBaseBuilderTy builder(getContext());
1276 mlir::OpBuilder::InsertionGuard _{builder};
1277 builder.setInsertionPointToStart(mlirModule.getBody());
1278 mlir::Location loc = mlirModule.getLoc();
1280 return buildRuntimeFunction(builder,
"__tls_init", loc, fnType,
1281 cir::GlobalLinkageKind::InternalLinkage);
1284cir::GlobalOp LoweringPreparePass::createGuardGlobalOp(
1285 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef name,
1286 cir::IntType guardTy, cir::GlobalLinkageKind linkage) {
1287 mlir::OpBuilder::InsertionGuard guard(builder);
1288 builder.setInsertionPointToStart(mlirModule.getBody());
1289 cir::GlobalOp g = cir::GlobalOp::create(builder, loc, name, guardTy);
1291 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1292 mlir::SymbolTable::setSymbolVisibility(
1293 g, mlir::SymbolTable::Visibility::Private);
1297void LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
1298 cir::LocalInitOp localInitOp) {
1299 CIRBaseBuilderTy builder(getContext());
1301 std::optional<cir::ASTVarDeclInterface> astOption = globalOp.getAst();
1302 assert(astOption.has_value());
1303 cir::ASTVarDeclInterface
varDecl = astOption.value();
1305 builder.setInsertionPointAfter(localInitOp);
1306 mlir::Block *localInitBlock = builder.getInsertionBlock();
1309 mlir::Operation *ret = localInitBlock->getTerminator();
1313 builder.setInsertionPointAfter(localInitOp);
1317 bool nonTemplateInline =
1323 if (nonTemplateInline) {
1324 globalOp->emitError(
1325 "NYI: guarded initialization for inline namespace-scope variables");
1332 bool threadsafe = astCtx->
getLangOpts().ThreadsafeStatics &&
1333 (
varDecl.isLocalVarDecl() || nonTemplateInline) &&
1338 bool useInt8GuardVariable = !threadsafe && globalOp.hasInternalLinkage();
1341 cir::GlobalOp guard = getOrCreateStaticLocalDeclGuardAddress(
1342 builder, globalOp, globalOp.getStaticLocalGuard()->getName().getValue(),
1343 varDecl.isLocalVarDecl(), useInt8GuardVariable);
1346 localInitBlock->push_back(ret);
1350 mlir::Value guardPtr = builder.
createGetGlobal(guard, localInitOp.getTls());
1372 unsigned maxInlineWidthInBits =
1375 if (!threadsafe || maxInlineWidthInBits) {
1377 auto bytePtrTy = cir::PointerType::get(builder.
getSIntNTy(8));
1378 mlir::Value bytePtr = builder.
createBitcast(guardPtr, bytePtrTy);
1380 localInitOp.getLoc(), bytePtr, *guard.getAlignment());
1389 auto loadOp = mlir::cast<cir::LoadOp>(guardLoad.getDefiningOp());
1390 loadOp.setMemOrder(cir::MemOrder::Acquire);
1391 loadOp.setSyncScope(cir::SyncScopeKind::System);
1414 if (useARMGuardVarABI() && !useInt8GuardVariable) {
1416 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()),
1418 guardLoad = builder.
createAnd(localInitOp.getLoc(), guardLoad, one);
1423 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()), 0);
1424 auto needsInit = builder.
createCompare(localInitOp.getLoc(),
1425 cir::CmpOpKind::eq, guardLoad, zero);
1429 builder, globalOp.getLoc(), needsInit,
1430 false, [&](mlir::OpBuilder &, mlir::Location) {
1431 emitCXXGuardedInitIf(builder, globalOp, localInitOp.getCtorRegion(),
1432 localInitOp.getDtorRegion(), varDecl, guardPtr,
1433 builder.getPointerTo(guard.getSymType()),
1439 globalOp->emitError(
"NYI: guarded init without inline atomics support");
1444 builder.getInsertionBlock()->push_back(ret);
1447void LoweringPreparePass::lowerLocalInitOp(cir::LocalInitOp initOp) {
1450 if (initOp.getCtorRegion().empty() && initOp.getDtorRegion().empty()) {
1455 cir::GlobalOp globalOp = initOp.getReferencedGlobal(symbolTables);
1456 assert(globalOp &&
"No global-op found");
1458 handleStaticLocal(globalOp, initOp);
1471static cir::GlobalLinkageKind
1474 return op.getLinkage();
1479 return op.getLinkage();
1483 if (op.isDeclaration())
1484 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1485 return cir::GlobalLinkageKind::WeakODRLinkage;
1489LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
1491 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1492 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1494 mlir::StringAttr wrapperName = op.getTlsRefs()->getWrapperName();
1496 auto existingWrapperIter = threadLocalWrappers.find(wrapperName.getValue());
1497 if (existingWrapperIter != threadLocalWrappers.end())
1498 return existingWrapperIter->second;
1501 auto funcType = cir::FuncType::get({}, builder.
getPointerTo(op.getSymType()));
1503 cir::FuncOp::create(builder, op.getLoc(), wrapperName, funcType);
1505 cir::GlobalLinkageKind linkageKind =
1507 func.setLinkageAttr(
1508 cir::GlobalLinkageKindAttr::get(&getContext(), linkageKind));
1513 func.isWeakForLinker())
1514 func.setComdat(
true);
1516 mlir::SymbolTable::setSymbolVisibility(
1517 func, mlir::SymbolTable::Visibility::Private);
1522 op.getGlobalVisibility() == cir::VisibilityKind::Hidden)
1523 func.setGlobalVisibility(cir::VisibilityKind::Hidden);
1526 op->emitError(
"Unhandled thread wrapper attributes for CC and Nounwind");
1528 threadLocalWrappers.insert({wrapperName.getValue(), func});
1532void LoweringPreparePass::defineGlobalThreadLocalWrapper(cir::GlobalOp op,
1533 cir::FuncOp initAlias,
1534 bool isVarDefinition) {
1535 CIRBaseBuilderTy builder(getContext());
1536 cir::FuncOp wrapper = getOrCreateThreadLocalWrapper(builder, op);
1537 mlir::Block *entryBB = wrapper.addEntryBlock();
1538 builder.setInsertionPointToStart(entryBB);
1542 mlir::Location aliasLoc = initAlias.getLoc();
1543 if (!isVarDefinition) {
1545 mlir::Value funcLoad = cir::GetGlobalOp::create(
1546 builder, aliasLoc, cir::PointerType::get(initAlias.getFunctionType()),
1547 initAlias.getSymName());
1548 mlir::Value nullCheck =
1550 mlir::Value cmp = cir::CmpOp::create(
1551 builder, aliasLoc, cir::CmpOpKind::ne, funcLoad, nullCheck);
1552 cir::IfOp::create(builder, aliasLoc, cmp,
false,
1553 [&](mlir::OpBuilder &, mlir::Location loc) {
1555 cir::YieldOp::create(builder, aliasLoc);
1564 cir::ReturnOp::create(builder, op.getLoc(), {get});
1568LoweringPreparePass::defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
1569 cir::FuncOp aliasee) {
1570 CIRBaseBuilderTy builder(getContext());
1571 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1572 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1573 mlir::StringAttr aliasName = op.getTlsRefs()->getInitName();
1574 auto existingAliasIter = threadLocalInitAliases.find(aliasName.getValue());
1576 if (existingAliasIter != threadLocalInitAliases.end())
1577 return existingAliasIter->second;
1581 cir::FuncOp::create(builder, op.getLoc(), aliasName, funcType);
1582 alias.setLinkage(op.getLinkage());
1585 alias.setAliasee(aliasee.getSymName());
1590 alias.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1591 mlir::SymbolTable::setSymbolVisibility(
1592 alias, mlir::SymbolTable::Visibility::Private);
1595 threadLocalInitAliases.insert({aliasName.getValue(), alias});
1599void LoweringPreparePass::lowerGlobalOp(GlobalOp op) {
1601 if (op.getStaticLocalGuard())
1604 mlir::Region &ctorRegion = op.getCtorRegion();
1605 mlir::Region &dtorRegion = op.getDtorRegion();
1606 cir::FuncOp initAlias;
1608 if (!ctorRegion.empty() || !dtorRegion.empty()) {
1611 cir::FuncOp f = buildCXXGlobalVarDeclInitFunc(op);
1614 ctorRegion.getBlocks().clear();
1615 dtorRegion.getBlocks().clear();
1618 if (op.getTlsModel() && !op.getStaticLocalGuard().has_value()) {
1630 if (op.getTlsRefs()->getGuardName()) {
1632 initAlias = defineGlobalThreadLocalInitAlias(op, f);
1635 initAlias = defineGlobalThreadLocalInitAlias(op, getTlsInitFn());
1639 globalThreadLocalInitializers.push_back(f);
1642 dynamicInitializers.push_back(f);
1644 }
else if (op.getTlsModel() && op.getTlsRefs() && op.isDeclaration()) {
1647 initAlias = defineGlobalThreadLocalInitAlias(op, {});
1653 if (op.getTlsModel() && op.getTlsRefs())
1654 defineGlobalThreadLocalWrapper(op, initAlias, !op.isDeclaration());
1659void LoweringPreparePass::lowerGetGlobalOp(GetGlobalOp op) {
1662 auto globalOp = mlir::cast<cir::GlobalOp>(
1663 symbolTables.lookupNearestSymbolFrom(op, op.getNameAttr()));
1669 if (!globalOp.getTlsModel() || !globalOp.getTlsRefs())
1687 mlir::Operation *parentOp = op->getParentOp();
1688 if (parentOp == globalOp) {
1689 mlir::Region *ctorRegion = &globalOp.getCtorRegion();
1690 mlir::Region *dtorRegion = &globalOp.getDtorRegion();
1692 if (!ctorRegion->empty() && &*ctorRegion->op_begin() == op.getOperation())
1694 if (!dtorRegion->empty() && &*dtorRegion->op_begin() == op.getOperation())
1698 CIRBaseBuilderTy builder(getContext());
1699 cir::FuncOp wrapperFunc = getOrCreateThreadLocalWrapper(builder, globalOp);
1701 builder.setInsertionPoint(op);
1703 wrapperFunc.getLoc(),
1704 mlir::FlatSymbolRefAttr::get(wrapperFunc.getSymNameAttr()),
1705 wrapperFunc.getFunctionType().getReturnType(), {});
1706 op->replaceAllUsesWith(call);
1710void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
1711 CIRBaseBuilderTy builder(getContext());
1712 builder.setInsertionPointAfter(op);
1714 mlir::Location loc = op->getLoc();
1715 cir::CmpThreeWayInfoAttr cmpInfo = op.getInfo();
1724 mlir::Value transformedResult;
1725 if (cmpInfo.getOrdering() != CmpOrdering::Partial) {
1728 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1729 mlir::Value selectOnLt = builder.
createSelect(loc, lt, ltRes, gtRes);
1731 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1732 transformedResult = builder.
createSelect(loc, eq, eqRes, selectOnLt);
1736 loc, op.getType(), cmpInfo.getUnordered().value());
1739 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1740 mlir::Value selectOnEq = builder.
createSelect(loc, eq, eqRes, unorderedRes);
1742 builder.
createCompare(loc, CmpOpKind::gt, op.getLhs(), op.getRhs());
1743 mlir::Value selectOnGt = builder.
createSelect(loc, gt, gtRes, selectOnEq);
1745 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1746 transformedResult = builder.
createSelect(loc, lt, ltRes, selectOnGt);
1749 op.replaceAllUsesWith(transformedResult);
1753template <
typename AttributeTy>
1754static llvm::SmallVector<mlir::Attribute>
1758 for (
const auto &[name, priority] : list)
1759 attrs.push_back(AttributeTy::get(context, name, priority));
1763void LoweringPreparePass::buildGlobalCtorDtorList() {
1764 if (!globalCtorList.empty()) {
1765 llvm::SmallVector<mlir::Attribute> globalCtors =
1769 mlirModule->setAttr(cir::CIRDialect::getGlobalCtorsAttrName(),
1770 mlir::ArrayAttr::get(&getContext(), globalCtors));
1773 if (!globalDtorList.empty()) {
1774 llvm::SmallVector<mlir::Attribute> globalDtors =
1777 mlirModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(),
1778 mlir::ArrayAttr::get(&getContext(), globalDtors));
1783LoweringPreparePass::createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
1784 mlir::Location loc) {
1785 mlir::OpBuilder::InsertionGuard guard(builder);
1786 builder.setInsertionPointToStart(mlirModule.getBody());
1789 cir::IntType guardTy = builder.
getSIntNTy(8);
1790 auto g = cir::GlobalOp::create(builder, loc,
"__tls_guard", guardTy);
1791 g.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
1792 builder.getContext(), cir::GlobalLinkageKind::InternalLinkage));
1795 if (
auto defTlsModel = mlirModule->getAttrOfType<TLSModelAttr>(
1796 cir::CIRDialect::getDefaultTlsModelAttrName())) {
1797 g.setTlsModel(defTlsModel.getValue());
1800 g.setTlsModel(TLSModel::GeneralDynamic);
1803 g.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
1807cir::IfOp LoweringPreparePass::buildGlobalTlsGuardCheck(
1808 CIRBaseBuilderTy &builder, mlir::Location loc, cir::GlobalOp guard) {
1810 mlir::Value getGuardValue = getGuard;
1815 if (guard.getSymType() != builder.
getSIntNTy(8))
1817 getGuard, cir::PointerType::get(builder.
getSIntNTy(8)));
1819 mlir::Value guardLoad =
1823 builder.
createCompare(loc, cir::CmpOpKind::eq, guardLoad, zero);
1824 return cir::IfOp::create(
1826 false, [&](mlir::OpBuilder &, mlir::Location loc) {
1830 loc, builder.
getConstantInt(loc, guard.getSymType(), 1), getGuard);
1834void LoweringPreparePass::buildCXXGlobalTlsFunc() {
1835 if (globalThreadLocalInitializers.empty())
1841 cir::FuncOp tlsInit = getTlsInitFn();
1842 mlir::Location loc = tlsInit.getLoc();
1843 CIRBaseBuilderTy builder(getContext());
1844 mlir::Block *entryBB = tlsInit.addEntryBlock();
1845 builder.setInsertionPointToStart(entryBB);
1847 cir::IfOp ifOperation = buildGlobalTlsGuardCheck(
1848 builder, loc, createGlobalThreadLocalGuard(builder, loc));
1851 builder.setInsertionPointToEnd(&ifOperation.getThenRegion().front());
1852 for (cir::FuncOp initFunc : globalThreadLocalInitializers)
1854 cir::YieldOp::create(builder, loc);
1856 builder.setInsertionPointAfter(ifOperation);
1857 cir::ReturnOp::create(builder, loc);
1860void LoweringPreparePass::buildCXXGlobalInitFunc() {
1861 if (dynamicInitializers.empty())
1868 SmallString<256> fnName;
1869 cir::GlobalLinkageKind linkage;
1877 llvm::raw_svector_ostream
out(fnName);
1878 std::unique_ptr<clang::MangleContext> mangleCtx(
1880 cast<clang::ItaniumMangleContext>(*mangleCtx)
1882 linkage = cir::GlobalLinkageKind::ExternalLinkage;
1884 fnName +=
"_GLOBAL__sub_I_";
1886 linkage = cir::GlobalLinkageKind::InternalLinkage;
1889 CIRBaseBuilderTy builder(getContext());
1890 builder.setInsertionPointToEnd(&mlirModule.getBodyRegion().back());
1891 auto fnType = cir::FuncType::get({}, builder.
getVoidTy());
1892 cir::FuncOp f = buildRuntimeFunction(builder, fnName, mlirModule.getLoc(),
1894 builder.setInsertionPointToStart(f.addEntryBlock());
1895 for (cir::FuncOp &f : dynamicInitializers)
1899 globalCtorList.emplace_back(fnName,
1900 cir::GlobalCtorAttr::getDefaultPriority());
1902 cir::ReturnOp::create(builder, f.getLoc());
1911 mlir::Operation *op, mlir::Type eltTy,
1913 mlir::Value numElements,
1914 uint64_t arrayLen,
bool isCtor) {
1915 mlir::Location loc = op->getLoc();
1916 bool isDynamic = numElements !=
nullptr;
1920 const unsigned sizeTypeSize =
1926 mlir::Value begin, end;
1929 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, numElements);
1931 mlir::Value endOffsetVal =
1933 begin = cir::CastOp::create(builder, loc, eltTy,
1934 cir::CastKind::array_to_ptrdecay, addr);
1935 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
1938 mlir::Value start = isCtor ? begin : end;
1939 mlir::Value stop = isCtor ? end : begin;
1945 mlir::Value guardCond;
1948 guardCond = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
1954 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, start, stop);
1956 ifOp = cir::IfOp::create(builder, loc, guardCond,
1958 [&](mlir::OpBuilder &, mlir::Location) {});
1959 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1962 mlir::Value tmpAddr =
1967 mlir::Block *bodyBlock = &op->getRegion(0).front();
1972 auto cloneRegionBodyInto = [&](mlir::Block *srcBlock,
1973 mlir::Value replacement) {
1974 mlir::IRMapping map;
1975 map.map(srcBlock->getArgument(0), replacement);
1976 for (mlir::Operation ®ionOp : *srcBlock) {
1977 if (!mlir::isa<cir::YieldOp>(®ionOp))
1978 builder.clone(regionOp, map);
1982 mlir::Block *partialDtorBlock =
nullptr;
1983 if (
auto arrayCtor = mlir::dyn_cast<cir::ArrayCtor>(op)) {
1984 mlir::Region &partialDtor = arrayCtor.getPartialDtor();
1985 if (!partialDtor.empty())
1986 partialDtorBlock = &partialDtor.front();
1987 }
else if (
auto arrayDtor = mlir::dyn_cast<cir::ArrayDtor>(op)) {
1996 if (arrayDtor.getDtorMayThrow())
1997 partialDtorBlock = bodyBlock;
2000 auto emitCtorDtorLoop = [&]() {
2004 [&](mlir::OpBuilder &b, mlir::Location loc) {
2005 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2006 auto cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
2007 currentElement, stop);
2011 [&](mlir::OpBuilder &b, mlir::Location loc) {
2012 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2014 cloneRegionBodyInto(bodyBlock, currentElement);
2015 mlir::Value stride = builder.
getUnsignedInt(loc, 1, sizeTypeSize);
2016 auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2017 currentElement, stride);
2020 mlir::Value stride = builder.
getSignedInt(loc, -1, sizeTypeSize);
2021 auto prevElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2022 currentElement, stride);
2024 cloneRegionBodyInto(bodyBlock, prevElement);
2027 cir::YieldOp::create(b, loc);
2031 if (partialDtorBlock) {
2032 cir::CleanupScopeOp::create(
2033 builder, loc, cir::CleanupKind::EH,
2035 [&](mlir::OpBuilder &b, mlir::Location loc) {
2037 cir::YieldOp::create(b, loc);
2040 [&](mlir::OpBuilder &b, mlir::Location loc) {
2041 auto cur = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2043 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, cur, begin);
2045 builder, loc, cmp,
false,
2046 [&](mlir::OpBuilder &b, mlir::Location loc) {
2050 [&](mlir::OpBuilder &b, mlir::Location loc) {
2051 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2052 auto neq = cir::CmpOp::create(
2053 builder, loc, cir::CmpOpKind::ne, el, begin);
2057 [&](mlir::OpBuilder &b, mlir::Location loc) {
2058 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2059 mlir::Value negOne =
2061 auto prev = cir::PtrStrideOp::create(builder, loc, eltTy,
2064 cloneRegionBodyInto(partialDtorBlock, prev);
2067 cir::YieldOp::create(builder, loc);
2069 cir::YieldOp::create(b, loc);
2076 cir::YieldOp::create(builder, loc);
2081void LoweringPreparePass::lowerArrayDtor(cir::ArrayDtor op) {
2082 CIRBaseBuilderTy builder(getContext());
2083 builder.setInsertionPointAfter(op.getOperation());
2085 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2087 if (op.getNumElements()) {
2089 op.getNumElements(), 0,
2095 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2101void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
2102 cir::CIRBaseBuilderTy builder(getContext());
2103 builder.setInsertionPointAfter(op.getOperation());
2105 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2107 if (op.getNumElements()) {
2109 op.getNumElements(), 0,
2115 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2121cir::FuncOp LoweringPreparePass::getCalledFunction(cir::CallOp callOp) {
2122 mlir::SymbolRefAttr sym = llvm::dyn_cast_if_present<mlir::SymbolRefAttr>(
2123 callOp.getCallableForCallee());
2126 return symbolTables.lookupNearestSymbolFrom<cir::FuncOp>(callOp, sym);
2129void LoweringPreparePass::lowerTrivialCopyCall(cir::CallOp op) {
2130 cir::FuncOp funcOp = getCalledFunction(op);
2134 std::optional<cir::CtorKind> ctorKind = funcOp.getCxxConstructorKind();
2135 if (ctorKind && *ctorKind == cir::CtorKind::Copy &&
2136 funcOp.isCxxTrivialMemberFunction()) {
2138 CIRBaseBuilderTy builder(getContext());
2139 mlir::ValueRange operands = op.getOperands();
2140 mlir::Value dest = operands[0];
2141 mlir::Value src = operands[1];
2142 builder.setInsertionPoint(op);
2148cir::GlobalOp LoweringPreparePass::getOrCreateConstAggregateGlobal(
2149 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef baseName,
2150 mlir::Type ty, mlir::TypedAttr constant) {
2152 llvm::SmallVector<cir::GlobalOp, 1> &versions =
2153 constAggregateGlobals[baseName];
2156 for (cir::GlobalOp gv : versions) {
2157 if (gv.getSymType() == ty && gv.getInitialValue() == constant)
2165 llvm::SmallString<128>
name(baseName);
2166 size_t baseLen =
name.size();
2167 unsigned version = versions.size();
2169 name.resize(baseLen);
2171 name.push_back(
'.');
2172 llvm::Twine(version).toVector(name);
2174 auto existingGv = symbolTables.lookupSymbolIn<cir::GlobalOp>(
2175 mlirModule, mlir::StringAttr::get(&getContext(), name));
2178 versions.push_back(existingGv);
2179 if (existingGv.getSymType() == ty &&
2180 existingGv.getInitialValue() == constant)
2186 mlir::OpBuilder::InsertionGuard guard(builder);
2187 builder.setInsertionPointToStart(mlirModule.getBody());
2189 cir::GlobalOp::create(builder, loc, name, ty,
2191 cir::LangAddressSpaceAttr::get(
2192 &getContext(), cir::LangAddressSpace::Default),
2193 cir::GlobalLinkageKind::PrivateLinkage);
2194 mlir::SymbolTable::setSymbolVisibility(
2195 gv, mlir::SymbolTable::Visibility::Private);
2196 gv.setInitialValueAttr(constant);
2200 symbolTables.getSymbolTable(mlirModule).insert(gv);
2202 versions.push_back(gv);
2206void LoweringPreparePass::lowerStoreOfConstAggregate(cir::StoreOp op) {
2208 auto constOp = op.getValue().getDefiningOp<cir::ConstantOp>();
2212 mlir::Type ty = constOp.getType();
2213 if (!mlir::isa<cir::ArrayType, cir::RecordType>(ty))
2219 auto alloca = op.getAddr().getDefiningOp<cir::AllocaOp>();
2223 mlir::TypedAttr constant = constOp.getValue();
2234 auto func = op->getParentOfType<cir::FuncOp>();
2237 llvm::StringRef funcName = func.getSymName();
2240 llvm::StringRef varName = alloca.getName();
2243 std::string baseName = (
"__const." + funcName +
"." + varName).str();
2244 CIRBaseBuilderTy builder(getContext());
2248 cir::GlobalOp gv = getOrCreateConstAggregateGlobal(builder, op.getLoc(),
2249 baseName, ty, constant);
2252 builder.setInsertionPoint(op);
2254 auto ptrTy = cir::PointerType::get(ty);
2255 mlir::Value globalPtr =
2256 cir::GetGlobalOp::create(builder, op.getLoc(), ptrTy, gv.getSymName());
2265 if (constOp.use_empty())
2272void LoweringPreparePass::lowerStdOp(cir::StdOpInterface typedOp) {
2273 mlir::Operation *op = typedOp.getOperation();
2274 cir::CIRBaseBuilderTy builder(getContext());
2275 builder.setInsertionPointAfter(op);
2276 mlir::Type resultType;
2277 if (op->getNumResults())
2278 resultType = op->getResult(0).getType();
2280 op->getLoc(), typedOp.getOriginalFnAttr(), resultType, op->getOperands());
2281 for (mlir::NamedAttribute attr : op->getAttrs())
2282 if (
attr.getName() != typedOp.getOriginalFnAttrName())
2283 call->setAttr(
attr.getName(),
attr.getValue());
2285 op->replaceAllUsesWith(call);
2289void LoweringPreparePass::runOnOp(mlir::Operation *op) {
2290 if (
auto arrayCtor = dyn_cast<cir::ArrayCtor>(op)) {
2291 lowerArrayCtor(arrayCtor);
2292 }
else if (
auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) {
2293 lowerArrayDtor(arrayDtor);
2294 }
else if (
auto stdOp = mlir::dyn_cast<cir::StdOpInterface>(op)) {
2296 }
else if (
auto cast = mlir::dyn_cast<cir::CastOp>(op)) {
2298 }
else if (
auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
2299 lowerComplexConjOp(complexConj);
2300 }
else if (
auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
2301 lowerComplexDivOp(complexDiv);
2302 }
else if (
auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
2303 lowerComplexMulOp(complexMul);
2304 }
else if (
auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) {
2305 lowerGlobalOp(glob);
2306 if (
auto regAttr = glob->getAttrOfType<CUDAVarRegistrationInfoAttr>(
2307 CUDAVarRegistrationInfoAttr::getMnemonic()))
2308 cudaDeviceVars.emplace_back(glob, regAttr);
2309 }
else if (
auto getGlob = mlir::dyn_cast<cir::GetGlobalOp>(op)) {
2310 lowerGetGlobalOp(getGlob);
2311 }
else if (
auto callOp = dyn_cast<cir::CallOp>(op)) {
2312 lowerTrivialCopyCall(callOp);
2313 }
else if (
auto storeOp = dyn_cast<cir::StoreOp>(op)) {
2314 lowerStoreOfConstAggregate(storeOp);
2315 }
else if (
auto fnOp = dyn_cast<cir::FuncOp>(op)) {
2316 if (
auto globalCtor = fnOp.getGlobalCtorPriority())
2317 globalCtorList.emplace_back(fnOp.getName(), globalCtor.value());
2318 else if (
auto globalDtor = fnOp.getGlobalDtorPriority())
2319 globalDtorList.emplace_back(fnOp.getName(), globalDtor.value());
2321 if (mlir::Attribute attr =
2322 fnOp->getAttr(cir::CUDAKernelNameAttr::getMnemonic())) {
2323 auto kernelNameAttr = dyn_cast<CUDAKernelNameAttr>(attr);
2324 llvm::StringRef kernelName = kernelNameAttr.getKernelName();
2325 cudaKernelMap[kernelName] = fnOp;
2327 }
else if (
auto threeWayCmp = dyn_cast<cir::CmpThreeWayOp>(op)) {
2328 lowerThreeWayCmpOp(threeWayCmp);
2329 }
else if (
auto initOp = dyn_cast<cir::LocalInitOp>(op)) {
2330 lowerLocalInitOp(initOp);
2341 llvm::StringRef name) {
2342 return (
"__" + prefix + name).str();
2364void LoweringPreparePass::buildCUDAModuleCtor() {
2367 if (astCtx->
getLangOpts().GPURelocatableDeviceCode)
2368 llvm_unreachable(
"GPU RDC NYI");
2372 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2377 mlir::Attribute cudaBinaryHandleAttr =
2378 mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName());
2379 if (!cudaBinaryHandleAttr) {
2385 llvm::StringRef cudaGPUBinaryName =
2386 mlir::cast<CUDABinaryHandleAttr>(cudaBinaryHandleAttr)
2390 llvm::vfs::FileSystem &vfs =
2392 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> gpuBinaryOrErr =
2393 vfs.getBufferForFile(cudaGPUBinaryName);
2394 if (std::error_code ec = gpuBinaryOrErr.getError()) {
2395 mlirModule->emitError(
"cannot open GPU binary file: " + cudaGPUBinaryName +
2396 ": " + ec.message());
2399 std::unique_ptr<llvm::MemoryBuffer> gpuBinary =
2400 std::move(gpuBinaryOrErr.get());
2404 mlir::Location loc = mlirModule->getLoc();
2405 CIRBaseBuilderTy builder(getContext());
2406 builder.setInsertionPointToStart(mlirModule.getBody());
2410 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2412 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2418 llvm::StringRef fatbinConstName =
2419 astCtx->
getLangOpts().HIP ?
".hip_fatbin" :
".nv_fatbin";
2421 llvm::StringRef fatbinSectionName =
2422 astCtx->
getLangOpts().HIP ?
".hipFatBinSegment" :
".nvFatBinSegment";
2426 ArrayType::get(&getContext(), charTy, gpuBinary->getBuffer().size());
2428 GlobalOp fatbinStr = GlobalOp::create(builder, loc, fatbinStrName, fatbinType,
2430 GlobalLinkageKind::PrivateLinkage);
2432 const unsigned HIPCodeObjectAlign = 4096;
2433 fatbinStr.setAlignment(HIPCodeObjectAlign);
2435 fatbinStr.setAlignment(8);
2438 fatbinStr.setInitialValueAttr(cir::ConstArrayAttr::get(
2439 fatbinType, StringAttr::get(gpuBinary->getBuffer(), fatbinType)));
2440 fatbinStr.setSection(fatbinConstName);
2441 fatbinStr.setPrivate();
2445 mlir::Type fatbinWrapperMembers[] = {intTy, intTy, voidPtrTy, voidPtrTy};
2446 auto fatbinWrapperType = cir::StructType::get(
2447 &getContext(), fatbinWrapperMembers,
false,
false,
2449 std::string fatbinWrapperName =
2451 GlobalOp fatbinWrapper = GlobalOp::create(
2452 builder, loc, fatbinWrapperName, fatbinWrapperType,
2453 true, {}, GlobalLinkageKind::PrivateLinkage);
2454 fatbinWrapper.setSection(fatbinSectionName);
2456 constexpr unsigned cudaFatMagic = 0x466243b1;
2457 constexpr unsigned hipFatMagic = 0x48495046;
2458 unsigned fatMagic =
isHIP ? hipFatMagic : cudaFatMagic;
2460 auto magicInit = IntAttr::get(intTy, fatMagic);
2461 auto versionInit = IntAttr::get(intTy, 1);
2462 auto fatbinStrSymbol =
2463 mlir::FlatSymbolRefAttr::get(fatbinStr.getSymNameAttr());
2464 auto fatbinInit = GlobalViewAttr::get(voidPtrTy, fatbinStrSymbol);
2466 fatbinWrapper.setInitialValueAttr(cir::ConstRecordAttr::get(
2468 mlir::ArrayAttr::get(&getContext(),
2469 {magicInit, versionInit, fatbinInit, unusedInit})));
2472 std::string gpubinHandleName =
2475 GlobalOp gpuBinHandle = GlobalOp::create(
2476 builder, loc, gpubinHandleName, voidPtrPtrTy,
2477 false, {}, cir::GlobalLinkageKind::InternalLinkage);
2479 gpuBinHandle.setPrivate();
2484 std::string regFuncName =
2486 FuncType regFuncType = FuncType::get({voidPtrTy}, voidPtrPtrTy);
2487 cir::FuncOp regFunc =
2488 buildRuntimeFunction(builder, regFuncName, loc, regFuncType);
2491 cir::FuncOp moduleCtor = buildRuntimeFunction(
2492 builder, moduleCtorName, loc, FuncType::get({}, voidTy),
2493 GlobalLinkageKind::InternalLinkage);
2495 globalCtorList.emplace_back(moduleCtorName,
2496 cir::GlobalCtorAttr::getDefaultPriority());
2497 builder.setInsertionPointToStart(moduleCtor.addEntryBlock());
2505 mlir::Block *entryBlock = builder.getInsertionBlock();
2506 mlir::Region *parent = entryBlock->getParent();
2507 mlir::Block *ifBlock = builder.createBlock(parent);
2508 mlir::Block *exitBlock = builder.createBlock(parent);
2510 mlir::OpBuilder::InsertionGuard guard(builder);
2511 builder.setInsertionPointToEnd(entryBlock);
2512 mlir::Value handle =
2514 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2515 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2516 mlir::Value isNull =
2517 builder.
createCompare(loc, cir::CmpOpKind::eq, handle, nullPtr);
2518 cir::BrCondOp::create(builder, loc, isNull, ifBlock, exitBlock);
2522 mlir::OpBuilder::InsertionGuard guard(builder);
2523 builder.setInsertionPointToStart(ifBlock);
2525 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2526 cir::CallOp gpuBinaryHandleCall =
2528 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2530 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2531 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2532 cir::BrOp::create(builder, loc, exitBlock);
2537 mlir::OpBuilder::InsertionGuard guard(builder);
2538 builder.setInsertionPointToStart(exitBlock);
2539 mlir::Value gHandle =
2542 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals())
2545 if (std::optional<FuncOp> dtor = buildHIPModuleDtor()) {
2546 cir::CIRBaseBuilderTy globalBuilder(getContext());
2547 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2548 FuncOp atexit = buildRuntimeFunction(
2549 globalBuilder,
"atexit", loc,
2550 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2551 mlir::Value dtorFunc = GetGlobalOp::create(
2552 builder, loc, PointerType::get(dtor->getFunctionType()),
2553 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2556 cir::ReturnOp::create(builder, loc);
2560 if (!astCtx->
getLangOpts().GPURelocatableDeviceCode) {
2568 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2569 cir::CallOp gpuBinaryHandleCall =
2571 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2573 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2574 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2577 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals()) {
2578 builder.
createCallOp(loc, *regGlobal, gpuBinaryHandle);
2587 cir::CIRBaseBuilderTy globalBuilder(getContext());
2588 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2590 buildRuntimeFunction(globalBuilder,
"__cudaRegisterFatBinaryEnd", loc,
2591 FuncType::get({voidPtrPtrTy}, voidTy));
2595 llvm_unreachable(
"GPU RDC NYI");
2600 if (std::optional<FuncOp> dtor = buildCUDAModuleDtor()) {
2603 cir::CIRBaseBuilderTy globalBuilder(getContext());
2604 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2605 FuncOp atexit = buildRuntimeFunction(
2606 globalBuilder,
"atexit", loc,
2607 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2608 mlir::Value dtorFunc = GetGlobalOp::create(
2609 builder, loc, PointerType::get(dtor->getFunctionType()),
2610 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2613 cir::ReturnOp::create(builder, loc);
2616std::optional<FuncOp> LoweringPreparePass::buildCUDAModuleDtor() {
2617 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2622 VoidType voidTy = VoidType::get(&getContext());
2623 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2625 mlir::Location loc = mlirModule.getLoc();
2627 cir::CIRBaseBuilderTy builder(getContext());
2628 builder.setInsertionPointToStart(mlirModule.getBody());
2631 std::string unregisterFuncName =
2633 FuncOp unregisterFunc = buildRuntimeFunction(
2634 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2643 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2644 GlobalLinkageKind::InternalLinkage);
2646 builder.setInsertionPointToStart(dtor.addEntryBlock());
2652 GlobalOp gpubinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2654 mlir::Value gpubin = builder.
createLoad(loc, gpubinAddress);
2656 ReturnOp::create(builder, loc);
2673std::optional<FuncOp> LoweringPreparePass::buildHIPModuleDtor() {
2674 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2679 VoidType voidTy = VoidType::get(&getContext());
2680 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2682 mlir::Location loc = mlirModule.getLoc();
2684 cir::CIRBaseBuilderTy builder(getContext());
2685 builder.setInsertionPointToStart(mlirModule.getBody());
2688 std::string unregisterFuncName =
2690 FuncOp unregisterFunc = buildRuntimeFunction(
2691 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2695 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2696 GlobalLinkageKind::InternalLinkage);
2699 GlobalOp gpuBinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2701 mlir::Block *entryBlock = dtor.addEntryBlock();
2702 mlir::Block *ifBlock = builder.createBlock(&dtor.getBody());
2703 mlir::Block *exitBlock = builder.createBlock(&dtor.getBody());
2705 mlir::OpBuilder::InsertionGuard guard(builder);
2706 builder.setInsertionPointToEnd(entryBlock);
2707 mlir::Value handle =
2709 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2710 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2711 mlir::Value isNotNull =
2712 builder.
createCompare(loc, cir::CmpOpKind::ne, handle, nullPtr);
2713 cir::BrCondOp::create(builder, loc, isNotNull, ifBlock, exitBlock);
2717 mlir::OpBuilder::InsertionGuard ifGuard(builder);
2718 builder.setInsertionPointToStart(ifBlock);
2721 cir::BrOp::create(builder, loc, exitBlock);
2724 mlir::OpBuilder::InsertionGuard exitGuard(builder);
2725 builder.setInsertionPointToStart(exitBlock);
2726 cir::ReturnOp::create(builder, loc);
2732std::optional<FuncOp> LoweringPreparePass::buildCUDARegisterGlobals() {
2733 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2736 cir::CIRBaseBuilderTy builder(getContext());
2737 builder.setInsertionPointToStart(mlirModule.getBody());
2739 mlir::Location loc = mlirModule.getLoc();
2742 auto voidTy = VoidType::get(&getContext());
2743 auto voidPtrTy = PointerType::get(voidTy);
2744 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2748 std::string regGlobalFuncName =
2750 auto regGlobalFuncTy = FuncType::get({voidPtrPtrTy}, voidTy);
2751 FuncOp regGlobalFunc =
2752 buildRuntimeFunction(builder, regGlobalFuncName, loc, regGlobalFuncTy,
2753 GlobalLinkageKind::InternalLinkage);
2754 builder.setInsertionPointToStart(regGlobalFunc.addEntryBlock());
2756 buildCUDARegisterGlobalFunctions(builder, regGlobalFunc);
2757 buildCUDARegisterVars(builder, regGlobalFunc);
2759 ReturnOp::create(builder, loc);
2760 return regGlobalFunc;
2763void LoweringPreparePass::buildCUDARegisterGlobalFunctions(
2764 cir::CIRBaseBuilderTy &builder, FuncOp regGlobalFunc) {
2765 mlir::Location loc = mlirModule.getLoc();
2767 cir::CIRDataLayout dataLayout(mlirModule);
2769 auto voidTy = VoidType::get(&getContext());
2770 auto voidPtrTy = PointerType::get(voidTy);
2771 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2773 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2777 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2779 cir::CIRBaseBuilderTy globalBuilder(getContext());
2780 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2794 FuncOp cudaRegisterFunction = buildRuntimeFunction(
2796 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2797 voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy},
2800 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2801 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2802 auto tmpString = cir::GlobalOp::create(
2803 globalBuilder, loc, (
".str" + str).str(), strType,
2805 cir::GlobalLinkageKind::PrivateLinkage);
2808 tmpString.setInitialValueAttr(
2809 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2810 tmpString.setPrivate();
2814 cir::ConstantOp cirNullPtr = builder.
getNullPtr(voidPtrTy, loc);
2816 for (
auto kernelName : cudaKernelMap.keys()) {
2817 FuncOp deviceStub = cudaKernelMap[kernelName];
2818 GlobalOp deviceFuncStr = makeConstantString(kernelName);
2822 mlir::Value hostFunc;
2829 auto funcHandle = cast<GlobalOp>(mlirModule.lookupSymbol(kernelName));
2834 GetGlobalOp::create(
2835 builder, loc, PointerType::get(deviceStub.getFunctionType()),
2836 mlir::FlatSymbolRefAttr::get(deviceStub.getSymNameAttr())),
2840 loc, cudaRegisterFunction,
2841 {fatbinHandle, hostFunc, deviceFunc, deviceFunc,
2842 ConstantOp::create(builder, loc, IntAttr::get(intTy, -1)), cirNullPtr,
2843 cirNullPtr, cirNullPtr, cirNullPtr, cirNullPtr});
2850void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
2851 FuncOp regGlobalFunc) {
2852 mlir::Location loc = mlirModule.getLoc();
2854 cir::CIRDataLayout dataLayout(mlirModule);
2857 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2861 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2864 if (cudaDeviceVars.empty())
2867 cir::CIRBaseBuilderTy globalBuilder(getContext());
2868 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2875 cir::VoidType voidTy = builder.
getVoidTy();
2876 FuncOp cudaRegisterVar = buildRuntimeFunction(
2878 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2879 sizeTy, intTy, intTy},
2882 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2883 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2884 auto tmpString = cir::GlobalOp::create(
2885 globalBuilder, loc, (
".str" + str).str(), strType,
2887 cir::GlobalLinkageKind::PrivateLinkage);
2888 tmpString.setInitialValueAttr(
2889 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2890 tmpString.setPrivate();
2894 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2896 for (
auto &[global, regAttr] : cudaDeviceVars) {
2897 switch (regAttr.getKind()) {
2898 case cir::CUDADeviceVarKind::Variable:
2900 case cir::CUDADeviceVarKind::Surface:
2901 llvm_unreachable(
"Surface registration NYI");
2902 case cir::CUDADeviceVarKind::Texture:
2903 llvm_unreachable(
"Texture registration NYI");
2906 if (regAttr.getIsManaged())
2907 llvm_unreachable(
"Managed variable registration NYI");
2909 GlobalOp deviceNameStr = makeConstantString(regAttr.getDeviceSideName());
2912 mlir::Value hostVar =
2915 auto isExtern = ConstantOp::create(
2916 builder, loc, IntAttr::get(intTy, regAttr.getIsExtern() ? 1 : 0));
2917 llvm::TypeSize size = dataLayout.getTypeAllocSize(global.getSymType());
2918 auto varSize = ConstantOp::create(
2919 builder, loc, IntAttr::get(sizeTy, size.getFixedValue()));
2920 auto isConstant = ConstantOp::create(
2921 builder, loc, IntAttr::get(intTy, regAttr.getIsConstant() ? 1 : 0));
2922 auto normalized = ConstantOp::create(builder, loc, IntAttr::get(intTy, 0));
2924 {fatbinHandle, hostVar, deviceName, deviceName,
2925 isExtern, varSize, isConstant, normalized});
2929void LoweringPreparePass::runOnOperation() {
2930 mlir::Operation *op = getOperation();
2931 if (isa<::mlir::ModuleOp>(op))
2932 mlirModule = cast<::mlir::ModuleOp>(op);
2934 llvm::SmallVector<mlir::Operation *> opsToTransform;
2936 op->walk([&](mlir::Operation *op) {
2937 if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
2938 cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
2939 cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
2940 cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
2941 cir::CmpThreeWayOp, cir::LocalInitOp, cir::StdOpInterface>(
2943 opsToTransform.push_back(op);
2946 for (mlir::Operation *o : opsToTransform)
2949 buildCXXGlobalInitFunc();
2950 buildCXXGlobalTlsFunc();
2952 buildCUDAModuleCtor();
2954 buildGlobalCtorDtorList();
2958 return std::make_unique<LoweringPreparePass>();
2961std::unique_ptr<Pass>
2963 auto pass = std::make_unique<LoweringPreparePass>();
2964 pass->setASTContext(astCtx);
2965 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 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 bool isThreadWrapperReplaceable(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)
static llvm::SmallVector< RecordMemberKind > getAllDataKinds(llvm::ArrayRef< mlir::Type > members)
One Data kind per member.
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...
virtual uint64_t getMaxPointerWidth() const
Return the maximum width of pointers on this target.
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()