11#include "mlir/IR/Attributes.h"
12#include "mlir/IR/BuiltinAttributeInterfaces.h"
13#include "mlir/IR/IRMapping.h"
14#include "mlir/IR/Location.h"
15#include "mlir/IR/Value.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/ADT/TypeSwitch.h"
33#include "llvm/IR/Instructions.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/Path.h"
36#include "llvm/Support/VersionTuple.h"
46#define GEN_PASS_DEF_LOWERINGPREPARE
47#include "clang/CIR/Dialect/Passes.h.inc"
51 SmallString<128> fileName;
53 if (mlirModule.getSymName())
54 fileName = llvm::sys::path::filename(mlirModule.getSymName()->str());
59 for (
size_t i = 0; i < fileName.size(); ++i) {
70struct LoweringPreparePass
71 :
public impl::LoweringPrepareBase<LoweringPreparePass> {
72 LoweringPreparePass() =
default;
82 LoweringPreparePass(
const LoweringPreparePass &other)
83 : impl::LoweringPrepareBase<LoweringPreparePass>(other) {}
85 void runOnOperation()
override;
87 void runOnOp(mlir::Operation *op);
88 void lowerCastOp(cir::CastOp op);
89 void lowerComplexConjOp(cir::ComplexConjOp op);
90 void lowerComplexDivOp(cir::ComplexDivOp op);
91 void lowerComplexMulOp(cir::ComplexMulOp op);
92 void lowerGetGlobalOp(cir::GetGlobalOp op);
93 void lowerGlobalOp(cir::GlobalOp op);
94 void lowerThreeWayCmpOp(cir::CmpThreeWayOp op);
95 void lowerArrayDtor(cir::ArrayDtor op);
96 void lowerArrayCtor(cir::ArrayCtor op);
97 void lowerTrivialCopyCall(cir::CallOp op);
98 void lowerStoreOfConstAggregate(cir::StoreOp op);
99 void lowerLocalInitOp(cir::LocalInitOp op);
100 void lowerStdOp(cir::StdOpInterface op);
105 cir::FuncOp getCalledFunction(cir::CallOp callOp);
115 getOrCreateConstAggregateGlobal(CIRBaseBuilderTy &builder, mlir::Location loc,
116 llvm::StringRef baseName, mlir::Type ty,
117 mlir::TypedAttr constant, uint64_t alignment);
120 cir::FuncOp buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op);
123 void defineGlobalThreadLocalWrapper(cir::GlobalOp op, cir::FuncOp initAlias,
124 bool isVarDefinition);
126 cir::FuncOp defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
127 cir::FuncOp aliasee);
129 cir::FuncOp getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
135 cir::IfOp buildGlobalTlsGuardCheck(CIRBaseBuilderTy &builder,
136 mlir::Location loc, cir::GlobalOp guard);
138 cir::FuncOp getOrCreateDtorFunc(CIRBaseBuilderTy &builder, cir::GlobalOp op,
139 mlir::Region &dtorRegion,
140 cir::CallOp &dtorCall);
147 cir::FuncOp buildGlobalInitCallerFunc(
148 llvm::StringRef fnName, cir::GlobalLinkageKind linkage,
149 llvm::ArrayRef<cir::FuncOp> initializers,
uint32_t priority);
152 void buildCXXGlobalInitFunc();
156 void buildCXXGlobalPriorityInitFuncs();
159 void buildCXXGlobalTlsFunc();
162 void buildGlobalCtorDtorList();
164 cir::FuncOp buildRuntimeFunction(
165 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
167 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage);
169 cir::GlobalOp getOrCreateRuntimeVariable(
170 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
172 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage,
173 cir::VisibilityKind visibility = cir::VisibilityKind::Default);
179 llvm::StringMap<FuncOp> cudaKernelMap;
180 llvm::SmallVector<std::pair<cir::GlobalOp, cir::CUDAVarRegistrationInfoAttr>>
185 void buildCUDAModuleCtor();
186 std::optional<FuncOp> buildCUDAModuleDtor();
187 std::optional<FuncOp> buildHIPModuleDtor();
188 std::optional<FuncOp> buildCUDARegisterGlobals();
189 void buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
190 FuncOp regGlobalFunc);
191 void buildCUDARegisterGlobalFunctions(cir::CIRBaseBuilderTy &builder,
192 FuncOp regGlobalFunc);
195 void handleStaticLocal(cir::GlobalOp globalOp, cir::LocalInitOp localInitOp);
207 cir::FuncOp getTlsInitFn();
210 cir::GlobalOp createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
214 cir::GlobalOp createGuardGlobalOp(CIRBaseBuilderTy &builder,
215 mlir::Location loc, llvm::StringRef name,
216 cir::IntType guardTy,
217 cir::GlobalLinkageKind linkage);
220 cir::GlobalOp getStaticLocalDeclGuardAddress(llvm::StringRef globalSymName) {
221 auto it = staticLocalDeclGuardMap.find(globalSymName);
222 if (it != staticLocalDeclGuardMap.end())
228 void setStaticLocalDeclGuardAddress(llvm::StringRef globalSymName,
229 cir::GlobalOp guard) {
230 staticLocalDeclGuardMap[globalSymName] = guard;
234 cir::GlobalOp getOrCreateStaticLocalDeclGuardAddress(
235 CIRBaseBuilderTy &builder, cir::GlobalOp globalOp, StringRef guardName,
236 bool isLocalVarDecl,
bool useInt8GuardVariable) {
238 cir::CIRDataLayout dataLayout(mlirModule);
239 cir::IntType guardTy;
240 clang::CharUnits guardAlignment;
243 if (useInt8GuardVariable) {
244 guardTy = cir::IntType::get(&getContext(), 8,
true);
246 }
else if (useARMGuardVarABI()) {
248 const unsigned sizeTypeSize =
249 getTargetInfo().getTypeWidth(getTargetInfo().getSignedSizeType());
251 cir::IntType::get(&getContext(), sizeTypeSize,
true);
255 guardTy = cir::IntType::get(&getContext(), 64,
true);
259 assert(guardTy && guardAlignment.
getQuantity() != 0);
261 llvm::StringRef globalSymName = globalOp.getSymName();
262 cir::GlobalOp guard = getStaticLocalDeclGuardAddress(globalSymName);
265 guard = createGuardGlobalOp(builder, globalOp->getLoc(), guardName,
266 guardTy, globalOp.getLinkage());
267 guard.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
268 guard.setDSOLocal(globalOp.getDsoLocal());
269 guard.setAlignment(guardAlignment.
getAsAlign().value());
270 guard.setTlsModel(globalOp.getTlsModel());
276 bool hasComdat = globalOp.getComdat();
277 const llvm::Triple &triple = getTargetInfo().getTriple();
280 if (!isLocalVarDecl && hasComdat &&
281 (triple.isOSBinFormatELF() || triple.isOSBinFormatWasm())) {
283 guard.setComdat(
true);
284 }
else if (hasComdat && globalOp.isWeakForLinker()) {
285 guard.setComdat(
true);
288 setStaticLocalDeclGuardAddress(globalSymName, guard);
297 clang::ASTContext *astCtx =
nullptr;
300 std::unique_ptr<cir::LowerModule> lowerModule;
302 const clang::TargetInfo &getTargetInfo()
const {
303 assert(lowerModule &&
"LoweringPrepare requires a module with a triple");
304 return lowerModule->getTarget();
307 const clang::LangOptions &getLangOpts()
const {
308 assert(lowerModule &&
"LoweringPrepare requires a module with LangOptions");
309 return lowerModule->getLangOpts();
318 std::optional<llvm::VersionTuple> getSDKVersion() {
319 auto sdkVersionAttr = mlirModule->getAttrOfType<mlir::StringAttr>(
320 CIRDialect::getSDKVersionAttrName());
322 return llvm::VersionTuple();
324 llvm::VersionTuple sdkVersion;
325 if (sdkVersion.tryParse(sdkVersionAttr.getValue())) {
326 mlirModule->emitError(
"cannot parse platform SDK version from ")
327 << CIRDialect::getSDKVersionAttrName() <<
" = '"
328 << sdkVersionAttr.getValue() <<
"'";
336 mlir::ModuleOp mlirModule;
356 mlir::SymbolTableCollection symbolTables;
359 llvm::StringMap<uint32_t> dynamicInitializerNames;
360 llvm::SmallVector<cir::FuncOp> dynamicInitializers;
365 std::map<unsigned, llvm::SmallVector<cir::FuncOp, 4>>
366 prioritizedDynamicInitializers;
367 llvm::SmallVector<cir::FuncOp> globalThreadLocalInitializers;
368 llvm::StringMap<cir::FuncOp> threadLocalWrappers;
369 llvm::StringMap<cir::FuncOp> threadLocalInitAliases;
372 llvm::StringMap<cir::GlobalOp> staticLocalDeclGuardMap;
374 llvm::StringMap<llvm::SmallVector<cir::GlobalOp, 1>> constAggregateGlobals;
377 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList;
379 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalDtorList;
383 bool useARMGuardVarABI()
const {
384 switch (lowerModule->getCXXABIKind()) {
385 case clang::TargetCXXABI::GenericARM:
386 case clang::TargetCXXABI::iOS:
387 case clang::TargetCXXABI::WatchOS:
388 case clang::TargetCXXABI::GenericAArch64:
389 case clang::TargetCXXABI::WebAssembly:
396 void emitGlobalGuardedDtorRegion(CIRBaseBuilderTy &builder,
397 cir::GlobalOp global,
398 mlir::Region &dtorRegion,
bool tls,
399 mlir::Block &entryBB) {
401 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
402 cir::GlobalOp handle = getOrCreateRuntimeVariable(
403 builder,
"__dso_handle", global.getLoc(), builder.
getUIntNTy(8),
404 cir::GlobalLinkageKind::ExternalLinkage, cir::VisibilityKind::Hidden);
410 cir::CallOp dtorCall;
411 cir::FuncOp dtorFunc =
412 getOrCreateDtorFunc(builder, global, dtorRegion, dtorCall);
417 cir::PointerType voidFnPtrTy = builder.
getVoidFnPtrTy({voidPtrTy});
418 cir::PointerType handlePtrTy = builder.
getPointerTo(handle.getSymType());
421 cir::FuncType::get({voidFnPtrTy, voidPtrTy, handlePtrTy}, intTy);
423 llvm::StringLiteral nameAtExit =
"__cxa_atexit";
425 nameAtExit = getTargetInfo().getTriple().isOSDarwin()
426 ? llvm::StringLiteral(
"_tlv_atexit")
427 : llvm::StringLiteral(
"__cxa_thread_atexit");
429 cir::FuncOp fnAtExit = buildRuntimeFunction(builder, nameAtExit,
430 global.getLoc(), fnAtExitType);
434 builder.setInsertionPointAfter(dtorCall);
436 auto dtorPtrTy = cir::PointerType::get(dtorFunc.getFunctionType());
437 args[0] = cir::GetGlobalOp::create(builder, dtorCall.getLoc(), dtorPtrTy,
438 dtorFunc.getSymName());
439 args[0] = cir::CastOp::create(builder, dtorCall.getLoc(), voidFnPtrTy,
440 cir::CastKind::bitcast, args[0]);
442 cir::CastOp::create(builder, dtorCall.getLoc(), voidPtrTy,
443 cir::CastKind::bitcast, dtorCall.getArgOperand(0));
444 args[2] = cir::GetGlobalOp::create(builder, handle.getLoc(), handlePtrTy,
445 handle.getSymName());
446 builder.
createCallOp(dtorCall.getLoc(), fnAtExit, args);
448 mlir::Block &dtorBlock = dtorRegion.front();
449 entryBB.getOperations().splice(entryBB.end(), dtorBlock.getOperations(),
451 std::prev(dtorBlock.end()));
454 builder.setInsertionPointToEnd(&entryBB);
460 void emitCXXGuardedInitIf(CIRBaseBuilderTy &builder, cir::GlobalOp globalOp,
461 mlir::Region &ctorRegion, mlir::Region &dtorRegion,
462 bool isLocalVarDecl, mlir::Value guardPtr,
463 cir::PointerType guardPtrTy,
bool threadsafe) {
464 auto loc = globalOp->getLoc();
484 mlir::Block *insertBlock = builder.getInsertionBlock();
485 if (!ctorRegion.empty()) {
486 assert(ctorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
488 mlir::Block &block = ctorRegion.front();
489 insertBlock->getOperations().splice(
490 insertBlock->end(), block.getOperations(), block.begin(),
491 std::prev(block.end()));
494 if (!dtorRegion.empty()) {
495 assert(dtorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
497 emitGlobalGuardedDtorRegion(builder, globalOp, dtorRegion, !threadsafe,
500 builder.setInsertionPointToEnd(insertBlock);
501 ctorRegion.getBlocks().clear();
509 mlir::Value acquireResult = acquireCall.getResult();
512 loc, mlir::cast<cir::IntType>(acquireResult.getType()), 0);
513 auto shouldInit = builder.
createCompare(loc, cir::CmpOpKind::ne,
514 acquireResult, acquireZero);
519 cir::IfOp::create(builder, loc, shouldInit,
false,
520 [](mlir::OpBuilder &, mlir::Location) {});
521 mlir::OpBuilder::InsertionGuard insertGuard(builder);
522 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
534 if (getLangOpts().Exceptions) {
535 cir::CleanupScopeOp::create(
536 builder, loc, cir::CleanupKind::EH,
537 [&](mlir::OpBuilder &, mlir::Location bodyLoc) {
541 [&](mlir::OpBuilder &, mlir::Location cleanupLoc) {
542 cir::CallOp abortCall =
544 mlir::ValueRange{guardPtr});
548 abortCall.setNothrowAttr(builder.getUnitAttr());
551 builder.setInsertionPointToEnd(&ifOp.getThenRegion().front());
558 mlir::ValueRange{guardPtr});
561 }
else if (!isLocalVarDecl) {
567 globalOp->emitError(
"NYI: non-threadsafe init for non-local variables");
582 void setASTContext(clang::ASTContext *c) { astCtx = c; }
587cir::GlobalOp LoweringPreparePass::getOrCreateRuntimeVariable(
588 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
589 mlir::Type type, cir::GlobalLinkageKind linkage,
590 cir::VisibilityKind visibility) {
591 cir::GlobalOp g = dyn_cast_or_null<cir::GlobalOp>(
592 mlir::SymbolTable::lookupNearestSymbolFrom(
593 mlirModule, mlir::StringAttr::get(mlirModule->getContext(), name)));
595 g = cir::GlobalOp::create(builder, loc, name, type);
597 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
598 mlir::SymbolTable::setSymbolVisibility(
599 g, mlir::SymbolTable::Visibility::Private);
600 g.setGlobalVisibility(visibility);
605cir::FuncOp LoweringPreparePass::buildRuntimeFunction(
606 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
607 cir::FuncType type, cir::GlobalLinkageKind linkage) {
608 cir::FuncOp f = dyn_cast_or_null<FuncOp>(SymbolTable::lookupNearestSymbolFrom(
609 mlirModule, StringAttr::get(mlirModule->getContext(), name)));
611 f = cir::FuncOp::create(builder, loc, name, type);
613 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
614 mlir::SymbolTable::setSymbolVisibility(
615 f, mlir::SymbolTable::Visibility::Private);
625 builder.setInsertionPoint(op);
627 mlir::Value src = op.getSrc();
628 mlir::Value imag = builder.
getNullValue(src.getType(), op.getLoc());
634 cir::CastKind elemToBoolKind) {
636 builder.setInsertionPoint(op);
638 mlir::Value src = op.getSrc();
639 if (!mlir::isa<cir::BoolType>(op.getType()))
646 cir::BoolType boolTy = builder.
getBoolTy();
647 mlir::Value srcRealToBool =
648 builder.
createCast(op.getLoc(), elemToBoolKind, srcReal, boolTy);
649 mlir::Value srcImagToBool =
650 builder.
createCast(op.getLoc(), elemToBoolKind, srcImag, boolTy);
651 return builder.
createLogicalOr(op.getLoc(), srcRealToBool, srcImagToBool);
656 cir::CastKind scalarCastKind) {
658 builder.setInsertionPoint(op);
660 mlir::Value src = op.getSrc();
661 auto dstComplexElemTy =
662 mlir::cast<cir::ComplexType>(op.getType()).getElementType();
667 mlir::Value dstReal = builder.
createCast(op.getLoc(), scalarCastKind, srcReal,
669 mlir::Value dstImag = builder.
createCast(op.getLoc(), scalarCastKind, srcImag,
674void LoweringPreparePass::lowerCastOp(cir::CastOp op) {
675 mlir::MLIRContext &ctx = getContext();
676 mlir::Value loweredValue = [&]() -> mlir::Value {
677 switch (op.getKind()) {
678 case cir::CastKind::float_to_complex:
679 case cir::CastKind::int_to_complex:
681 case cir::CastKind::float_complex_to_real:
682 case cir::CastKind::int_complex_to_real:
684 case cir::CastKind::float_complex_to_bool:
686 case cir::CastKind::int_complex_to_bool:
688 case cir::CastKind::float_complex:
690 case cir::CastKind::float_complex_to_int_complex:
692 case cir::CastKind::int_complex:
694 case cir::CastKind::int_complex_to_float_complex:
702 op.replaceAllUsesWith(loweredValue);
709 llvm::StringRef (*libFuncNameGetter)(llvm::APFloat::Semantics),
710 mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal,
711 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag) {
712 cir::FPTypeInterface elementTy =
713 mlir::cast<cir::FPTypeInterface>(ty.getElementType());
715 llvm::StringRef libFuncName = libFuncNameGetter(
716 llvm::APFloat::SemanticsToEnum(elementTy.getFloatSemantics()));
719 cir::FuncType libFuncTy = cir::FuncType::get(libFuncInputTypes, ty);
725 mlir::OpBuilder::InsertionGuard ipGuard{builder};
726 builder.setInsertionPointToStart(pass.mlirModule.getBody());
727 libFunc = pass.buildRuntimeFunction(builder, libFuncName, loc, libFuncTy);
731 builder.
createCallOp(loc, libFunc, {lhsReal, lhsImag, rhsReal, rhsImag});
732 return call.getResult();
735static llvm::StringRef
738 case llvm::APFloat::S_IEEEhalf:
740 case llvm::APFloat::S_IEEEsingle:
742 case llvm::APFloat::S_IEEEdouble:
744 case llvm::APFloat::S_PPCDoubleDouble:
746 case llvm::APFloat::S_x87DoubleExtended:
748 case llvm::APFloat::S_IEEEquad:
751 llvm_unreachable(
"unsupported floating point type");
757 mlir::Value lhsReal, mlir::Value lhsImag,
758 mlir::Value rhsReal, mlir::Value rhsImag) {
760 mlir::Value &a = lhsReal;
761 mlir::Value &b = lhsImag;
762 mlir::Value &c = rhsReal;
763 mlir::Value &d = rhsImag;
767 bool isFP = cir::isFPOrVectorOfFPType(a.getType());
768 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
771 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
774 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
777 auto div = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
781 mlir::Value ac = mul(loc, a, c);
782 mlir::Value bd = mul(loc, b, d);
783 mlir::Value cc = mul(loc, c, c);
784 mlir::Value dd = mul(loc, d, d);
785 mlir::Value acbd = add(loc, ac, bd);
786 mlir::Value ccdd = add(loc, cc, dd);
787 mlir::Value resultReal = div(loc, acbd, ccdd);
789 mlir::Value bc = mul(loc, b, c);
790 mlir::Value ad = mul(loc, a, d);
791 mlir::Value bcad = sub(loc, bc, ad);
792 mlir::Value resultImag = div(loc, bcad, ccdd);
798 mlir::Value lhsReal, mlir::Value lhsImag,
799 mlir::Value rhsReal, mlir::Value rhsImag) {
820 mlir::Value &a = lhsReal;
821 mlir::Value &b = lhsImag;
822 mlir::Value &c = rhsReal;
823 mlir::Value &d = rhsImag;
826 assert(cir::isFPOrVectorOfFPType(a.getType()) &&
827 "range-reduction complex divide expects floating-point operands");
829 auto trueBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
830 mlir::Value r = builder.
createFDiv(loc, d, c);
831 mlir::Value rd = builder.
createFMul(loc, r, d);
832 mlir::Value tmp = builder.
createFAdd(loc, c, rd);
834 mlir::Value br = builder.
createFMul(loc, b, r);
835 mlir::Value abr = builder.
createFAdd(loc, a, br);
836 mlir::Value e = builder.
createFDiv(loc, abr, tmp);
838 mlir::Value ar = builder.
createFMul(loc, a, r);
839 mlir::Value bar = builder.
createFSub(loc, b, ar);
840 mlir::Value f = builder.
createFDiv(loc, bar, tmp);
846 auto falseBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
847 mlir::Value r = builder.
createFDiv(loc, c, d);
848 mlir::Value rc = builder.
createFMul(loc, r, c);
849 mlir::Value tmp = builder.
createFAdd(loc, d, rc);
851 mlir::Value ar = builder.
createFMul(loc, a, r);
852 mlir::Value arb = builder.
createFAdd(loc, ar, b);
853 mlir::Value e = builder.
createFDiv(loc, arb, tmp);
855 mlir::Value br = builder.
createFMul(loc, b, r);
856 mlir::Value bra = builder.
createFSub(loc, br, a);
857 mlir::Value f = builder.
createFDiv(loc, bra, tmp);
863 auto cFabs = cir::FAbsOp::create(builder, loc, c);
864 auto dFabs = cir::FAbsOp::create(builder, loc, d);
865 cir::CmpOp cmpResult =
866 builder.
createCompare(loc, cir::CmpOpKind::ge, cFabs, dFabs);
867 auto ternary = cir::TernaryOp::create(builder, loc, cmpResult,
868 trueBranchBuilder, falseBranchBuilder);
870 return ternary.getResult();
876 mlir::Type elementType) {
878 auto getHigherPrecisionFPType = [&context](mlir::Type type) -> mlir::Type {
879 if (mlir::isa<cir::FP16Type>(type))
880 return cir::SingleType::get(&context);
882 if (mlir::isa<cir::SingleType>(type) || mlir::isa<cir::BF16Type>(type))
883 return cir::DoubleType::get(&context);
885 if (mlir::isa<cir::DoubleType>(type))
886 return cir::LongDoubleType::get(&context, type);
891 auto getFloatTypeSemantics =
892 [&langOpts, &targetInfo](mlir::Type type) ->
const llvm::fltSemantics & {
894 if (mlir::isa<cir::FP16Type>(type))
895 return info.getHalfFormat();
897 if (mlir::isa<cir::BF16Type>(type))
898 return info.getBFloat16Format();
900 if (mlir::isa<cir::SingleType>(type))
901 return info.getFloatFormat();
903 if (mlir::isa<cir::DoubleType>(type))
904 return info.getDoubleFormat();
906 if (mlir::isa<cir::LongDoubleType>(type)) {
907 if (langOpts.OpenMP && langOpts.OpenMPIsTargetDevice)
908 llvm_unreachable(
"NYI Float type semantics with OpenMP");
909 return info.getLongDoubleFormat();
912 if (mlir::isa<cir::FP128Type>(type)) {
913 if (langOpts.OpenMP && langOpts.OpenMPIsTargetDevice)
914 llvm_unreachable(
"NYI Float type semantics with OpenMP");
915 return info.getFloat128Format();
918 llvm_unreachable(
"Unsupported float type semantics");
921 const mlir::Type higherElementType = getHigherPrecisionFPType(elementType);
922 const llvm::fltSemantics &elementTypeSemantics =
923 getFloatTypeSemantics(elementType);
924 const llvm::fltSemantics &higherElementTypeSemantics =
925 getFloatTypeSemantics(higherElementType);
934 if (llvm::APFloat::semanticsMaxExponent(elementTypeSemantics) * 2 + 1 <=
935 llvm::APFloat::semanticsMaxExponent(higherElementTypeSemantics)) {
936 return higherElementType;
946 mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal,
947 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag,
948 mlir::MLIRContext &mlirCx,
950 cir::ComplexType complexTy = op.getType();
951 if (mlir::isa<cir::FPTypeInterface>(complexTy.getElementType())) {
952 cir::ComplexRangeKind range = op.getRange();
953 if (range == cir::ComplexRangeKind::Improved)
957 if (range == cir::ComplexRangeKind::Full)
959 loc, complexTy, lhsReal, lhsImag, rhsReal,
962 if (range == cir::ComplexRangeKind::Promoted) {
963 mlir::Type originalElementType = complexTy.getElementType();
964 mlir::Type higherPrecisionElementType =
966 mlirCx, targetInfo, pass.getLangOpts(), builder,
967 originalElementType);
969 if (!higherPrecisionElementType)
973 cir::CastKind floatingCastKind = cir::CastKind::floating;
974 lhsReal = builder.
createCast(floatingCastKind, lhsReal,
975 higherPrecisionElementType);
976 lhsImag = builder.
createCast(floatingCastKind, lhsImag,
977 higherPrecisionElementType);
978 rhsReal = builder.
createCast(floatingCastKind, rhsReal,
979 higherPrecisionElementType);
980 rhsImag = builder.
createCast(floatingCastKind, rhsImag,
981 higherPrecisionElementType);
984 builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
989 mlir::Value finalReal =
990 builder.
createCast(floatingCastKind, resultReal, originalElementType);
991 mlir::Value finalImag =
992 builder.
createCast(floatingCastKind, resultImag, originalElementType);
1001void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) {
1002 cir::CIRBaseBuilderTy builder(getContext());
1003 builder.setInsertionPointAfter(op);
1004 mlir::Location loc = op.getLoc();
1005 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
1006 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
1012 mlir::Value loweredResult =
1014 rhsImag, getContext(), getTargetInfo());
1015 op.replaceAllUsesWith(loweredResult);
1019static llvm::StringRef
1021 switch (semantics) {
1022 case llvm::APFloat::S_IEEEhalf:
1024 case llvm::APFloat::S_IEEEsingle:
1026 case llvm::APFloat::S_IEEEdouble:
1028 case llvm::APFloat::S_PPCDoubleDouble:
1030 case llvm::APFloat::S_x87DoubleExtended:
1032 case llvm::APFloat::S_IEEEquad:
1035 llvm_unreachable(
"unsupported floating point type");
1041 mlir::Location loc, cir::ComplexMulOp op,
1042 mlir::Value lhsReal, mlir::Value lhsImag,
1043 mlir::Value rhsReal, mlir::Value rhsImag) {
1045 bool isFP = cir::isFPOrVectorOfFPType(lhsReal.getType());
1046 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
1049 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
1052 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
1056 mlir::Value resultRealLhs = mul(loc, lhsReal, rhsReal);
1057 mlir::Value resultRealRhs = mul(loc, lhsImag, rhsImag);
1058 mlir::Value resultImagLhs = mul(loc, lhsReal, rhsImag);
1059 mlir::Value resultImagRhs = mul(loc, lhsImag, rhsReal);
1060 mlir::Value resultReal = sub(loc, resultRealLhs, resultRealRhs);
1061 mlir::Value resultImag = add(loc, resultImagLhs, resultImagRhs);
1062 mlir::Value algebraicResult =
1065 cir::ComplexType complexTy = op.getType();
1066 cir::ComplexRangeKind rangeKind = op.getRange();
1067 if (mlir::isa<cir::IntType>(complexTy.getElementType()) ||
1068 rangeKind == cir::ComplexRangeKind::Basic ||
1069 rangeKind == cir::ComplexRangeKind::Improved ||
1070 rangeKind == cir::ComplexRangeKind::Promoted)
1071 return algebraicResult;
1078 mlir::Value resultRealIsNaN = builder.
createIsNaN(loc, resultReal);
1079 mlir::Value resultImagIsNaN = builder.
createIsNaN(loc, resultImag);
1080 mlir::Value resultRealAndImagAreNaN =
1083 return cir::TernaryOp::create(
1084 builder, loc, resultRealAndImagAreNaN,
1085 [&](mlir::OpBuilder &, mlir::Location) {
1088 lhsReal, lhsImag, rhsReal, rhsImag);
1091 [&](mlir::OpBuilder &, mlir::Location) {
1097void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
1098 cir::CIRBaseBuilderTy builder(getContext());
1099 builder.setInsertionPointAfter(op);
1100 mlir::Location loc = op.getLoc();
1101 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
1102 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
1107 mlir::Value loweredResult =
lowerComplexMul(*
this, builder, loc, op, lhsReal,
1108 lhsImag, rhsReal, rhsImag);
1109 op.replaceAllUsesWith(loweredResult);
1113void LoweringPreparePass::lowerComplexConjOp(cir::ComplexConjOp op) {
1114 mlir::Location loc = op.getLoc();
1115 CIRBaseBuilderTy builder(getContext());
1116 builder.setInsertionPointAfter(op);
1118 mlir::Value operand = op.getOperand();
1123 const bool isFP = cir::isFPOrVectorOfFPType(operandReal.getType());
1124 mlir::Value resultImag = isFP ? builder.
createFNeg(loc, operandImag)
1127 mlir::Value result =
1129 op->replaceAllUsesWith(mlir::ValueRange{result});
1133cir::FuncOp LoweringPreparePass::getOrCreateDtorFunc(CIRBaseBuilderTy &builder,
1135 mlir::Region &dtorRegion,
1136 cir::CallOp &dtorCall) {
1137 mlir::OpBuilder::InsertionGuard guard(builder);
1140 cir::VoidType voidTy = builder.
getVoidTy();
1141 auto voidPtrTy = cir::PointerType::get(voidTy);
1144 mlir::Block &dtorBlock = dtorRegion.front();
1148 auto opIt = dtorBlock.getOperations().begin();
1149 cir::GetGlobalOp ggop = mlir::cast<cir::GetGlobalOp>(*opIt);
1160 if (dtorBlock.getOperations().size() == 3) {
1161 auto callOp = mlir::dyn_cast<cir::CallOp>(&*(++opIt));
1162 auto yieldOp = mlir::dyn_cast<cir::YieldOp>(&*(++opIt));
1163 if (yieldOp && callOp && callOp.getNumOperands() == 1 &&
1164 callOp.getArgOperand(0) == ggop) {
1166 return getCalledFunction(callOp);
1173 builder.setInsertionPointAfter(op);
1174 SmallString<256> fnName(
"__cxx_global_array_dtor");
1175 uint32_t cnt = dynamicInitializerNames[fnName]++;
1177 fnName +=
"." + std::to_string(cnt);
1180 auto fnType = cir::FuncType::get({voidPtrTy}, voidTy);
1181 cir::FuncOp dtorFunc =
1182 buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1183 cir::GlobalLinkageKind::InternalLinkage);
1185 SmallVector<mlir::NamedAttribute> paramAttrs;
1186 paramAttrs.push_back(
1187 builder.getNamedAttr(
"llvm.noundef", builder.getUnitAttr()));
1188 SmallVector<mlir::Attribute> argAttrDicts;
1189 argAttrDicts.push_back(
1190 mlir::DictionaryAttr::get(builder.getContext(), paramAttrs));
1191 dtorFunc.setArgAttrsAttr(
1192 mlir::ArrayAttr::get(builder.getContext(), argAttrDicts));
1194 mlir::Block *entryBB = dtorFunc.addEntryBlock();
1197 entryBB->getOperations().splice(entryBB->begin(), dtorBlock.getOperations(),
1198 dtorBlock.begin(), dtorBlock.end());
1201 cir::GetGlobalOp dtorGGop =
1202 mlir::cast<cir::GetGlobalOp>(entryBB->getOperations().front());
1203 builder.setInsertionPointToStart(&dtorBlock);
1204 builder.clone(*dtorGGop.getOperation());
1208 mlir::Value dtorArg = entryBB->getArgument(0);
1209 dtorGGop.replaceAllUsesWith(dtorArg);
1213 mlir::Block &finalBlock = dtorFunc.getBody().back();
1214 auto yieldOp = cast<cir::YieldOp>(finalBlock.getTerminator());
1215 builder.setInsertionPoint(yieldOp);
1216 cir::ReturnOp::create(builder, yieldOp->getLoc());
1221 cir::GetGlobalOp origGGop =
1222 mlir::cast<cir::GetGlobalOp>(dtorBlock.getOperations().front());
1223 builder.setInsertionPointAfter(origGGop);
1224 mlir::Value ggopResult = origGGop.getResult();
1225 dtorCall = builder.
createCallOp(op.getLoc(), dtorFunc, ggopResult);
1228 auto finalYield = cir::YieldOp::create(builder, op.getLoc());
1231 dtorBlock.getOperations().erase(std::next(mlir::Block::iterator(finalYield)),
1233 dtorRegion.getBlocks().erase(std::next(dtorRegion.begin()), dtorRegion.end());
1239LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op) {
1242 SmallString<256> fnName(
"__cxx_global_var_init");
1244 uint32_t cnt = dynamicInitializerNames[fnName]++;
1246 fnName +=
"." + std::to_string(cnt);
1249 CIRBaseBuilderTy builder(getContext());
1250 builder.setInsertionPointAfter(op);
1251 cir::VoidType voidTy = builder.
getVoidTy();
1252 auto fnType = cir::FuncType::get({}, voidTy);
1253 FuncOp f = buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1254 cir::GlobalLinkageKind::InternalLinkage);
1259 if (op.getStrictfp()) {
1260 f->setAttr(cir::CIRDialect::getStrictFPAttrName(),
1261 mlir::UnitAttr::get(&getContext()));
1262 op.setStrictfp(
false);
1271 mlir::Block *entryBB = f.addEntryBlock();
1272 builder.setInsertionPointToStart(entryBB);
1276 bool needsTlsGuard = op.getTlsRefs() && op.getTlsRefs()->getGuardName();
1278 if (needsTlsGuard) {
1279 guardIf = buildGlobalTlsGuardCheck(
1280 builder, op.getLoc(),
1281 getOrCreateStaticLocalDeclGuardAddress(
1282 builder, op, op.getTlsRefs()->getGuardName().getValue(),
1284 op.hasInternalLinkage()));
1285 builder.setInsertionPointToEnd(&guardIf.getThenRegion().front());
1288 if (!op.getCtorRegion().empty()) {
1289 mlir::Block &block = op.getCtorRegion().front();
1290 mlir::Block *insertBlock = builder.getBlock();
1291 insertBlock->getOperations().splice(insertBlock->end(),
1292 block.getOperations(), block.begin(),
1293 std::prev(block.end()));
1297 mlir::Region &dtorRegion = op.getDtorRegion();
1298 if (!dtorRegion.empty()) {
1301 emitGlobalGuardedDtorRegion(builder, op, dtorRegion,
1302 op.getTlsModel().has_value(),
1303 *builder.getBlock());
1307 if (needsTlsGuard) {
1308 builder.setInsertionPointToEnd(&guardIf.getThenRegion().back());
1309 cir::YieldOp::create(builder, op.getLoc());
1313 builder.setInsertionPointToEnd(entryBB);
1314 mlir::Operation *yieldOp =
nullptr;
1315 if (!op.getCtorRegion().empty()) {
1316 mlir::Block &block = op.getCtorRegion().front();
1317 yieldOp = &block.getOperations().back();
1319 assert(!dtorRegion.empty());
1320 mlir::Block &block = dtorRegion.front();
1321 yieldOp = &block.getOperations().back();
1324 assert(isa<cir::YieldOp>(*yieldOp));
1325 cir::ReturnOp::create(builder, yieldOp->getLoc());
1330LoweringPreparePass::getGuardAcquireFn(cir::PointerType guardPtrTy) {
1332 CIRBaseBuilderTy builder(getContext());
1333 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1334 builder.setInsertionPointToStart(mlirModule.getBody());
1335 mlir::Location loc = mlirModule.getLoc();
1336 cir::IntType intTy = cir::IntType::get(&getContext(), 32,
true);
1337 auto fnType = cir::FuncType::get({guardPtrTy}, intTy);
1338 return buildRuntimeFunction(builder,
"__cxa_guard_acquire", loc, fnType);
1342LoweringPreparePass::getGuardReleaseFn(cir::PointerType guardPtrTy) {
1344 CIRBaseBuilderTy builder(getContext());
1345 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1346 builder.setInsertionPointToStart(mlirModule.getBody());
1347 mlir::Location loc = mlirModule.getLoc();
1348 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1349 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1350 return buildRuntimeFunction(builder,
"__cxa_guard_release", loc, fnType);
1353cir::FuncOp LoweringPreparePass::getGuardAbortFn(cir::PointerType guardPtrTy) {
1355 CIRBaseBuilderTy builder(getContext());
1356 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1357 builder.setInsertionPointToStart(mlirModule.getBody());
1358 mlir::Location loc = mlirModule.getLoc();
1359 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1360 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1361 return buildRuntimeFunction(builder,
"__cxa_guard_abort", loc, fnType);
1364cir::FuncOp LoweringPreparePass::getTlsInitFn() {
1366 CIRBaseBuilderTy builder(getContext());
1367 mlir::OpBuilder::InsertionGuard _{builder};
1368 builder.setInsertionPointToStart(mlirModule.getBody());
1369 mlir::Location loc = mlirModule.getLoc();
1371 return buildRuntimeFunction(builder,
"__tls_init", loc, fnType,
1372 cir::GlobalLinkageKind::InternalLinkage);
1375cir::GlobalOp LoweringPreparePass::createGuardGlobalOp(
1376 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef name,
1377 cir::IntType guardTy, cir::GlobalLinkageKind linkage) {
1378 mlir::OpBuilder::InsertionGuard guard(builder);
1379 builder.setInsertionPointToStart(mlirModule.getBody());
1380 cir::GlobalOp g = cir::GlobalOp::create(builder, loc, name, guardTy);
1382 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1383 mlir::SymbolTable::setSymbolVisibility(
1384 g, mlir::SymbolTable::Visibility::Private);
1388void LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
1389 cir::LocalInitOp localInitOp) {
1390 CIRBaseBuilderTy builder(getContext());
1394 std::optional<cir::StaticLocalInfoAttr> infoOption =
1395 globalOp.getStaticLocalInfo();
1399 if (!infoOption.has_value()) {
1400 globalOp->emitError(
1401 "static-local global with a guard is missing 'static_local_info'");
1404 cir::StaticLocalInfoAttr
info = infoOption.value();
1406 builder.setInsertionPointAfter(localInitOp);
1407 mlir::Block *localInitBlock = builder.getInsertionBlock();
1410 mlir::Operation *ret = localInitBlock->getTerminator();
1414 builder.setInsertionPointAfter(localInitOp);
1418 cir::TemplateSpecializationKind tsk =
info.getTsk();
1420 tsk == cir::TemplateSpecializationKind::ImplicitInstantiation ||
1422 cir::TemplateSpecializationKind::ExplicitInstantiationDeclaration ||
1423 tsk == cir::TemplateSpecializationKind::ExplicitInstantiationDefinition;
1428 if (nonTemplateInline) {
1429 globalOp->emitError(
1430 "NYI: guarded initialization for inline namespace-scope variables");
1437 bool threadsafe = getLangOpts().ThreadsafeStatics &&
1438 (
info.getLocal() || nonTemplateInline) &&
1439 info.getTls() == cir::TLSKind::None;
1443 bool useInt8GuardVariable = !threadsafe && globalOp.hasInternalLinkage();
1446 cir::GlobalOp guard = getOrCreateStaticLocalDeclGuardAddress(
1447 builder, globalOp, globalOp.getStaticLocalGuard()->getName().getValue(),
1448 info.getLocal(), useInt8GuardVariable);
1451 localInitBlock->push_back(ret);
1455 mlir::Value guardPtr = builder.
createGetGlobal(guard, localInitOp.getTls());
1477 unsigned maxInlineWidthInBits = getTargetInfo().getMaxAtomicInlineWidth();
1479 if (!threadsafe || maxInlineWidthInBits) {
1481 auto bytePtrTy = cir::PointerType::get(builder.
getSIntNTy(8));
1482 mlir::Value bytePtr = builder.
createBitcast(guardPtr, bytePtrTy);
1484 localInitOp.getLoc(), bytePtr, *guard.getAlignment());
1493 auto loadOp = mlir::cast<cir::LoadOp>(guardLoad.getDefiningOp());
1494 loadOp.setMemOrder(cir::MemOrder::Acquire);
1495 loadOp.setSyncScope(cir::SyncScopeKind::System);
1518 if (useARMGuardVarABI() && !useInt8GuardVariable) {
1520 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()),
1522 guardLoad = builder.
createAnd(localInitOp.getLoc(), guardLoad, one);
1527 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()), 0);
1528 auto needsInit = builder.
createCompare(localInitOp.getLoc(),
1529 cir::CmpOpKind::eq, guardLoad, zero);
1533 builder, globalOp.getLoc(), needsInit,
1534 false, [&](mlir::OpBuilder &, mlir::Location) {
1535 emitCXXGuardedInitIf(
1536 builder, globalOp, localInitOp.getCtorRegion(),
1537 localInitOp.getDtorRegion(), info.getLocal(), guardPtr,
1538 builder.getPointerTo(guard.getSymType()), threadsafe);
1543 globalOp->emitError(
"NYI: guarded init without inline atomics support");
1548 builder.getInsertionBlock()->push_back(ret);
1551void LoweringPreparePass::lowerLocalInitOp(cir::LocalInitOp initOp) {
1554 if (initOp.getCtorRegion().empty() && initOp.getDtorRegion().empty()) {
1559 cir::GlobalOp globalOp = initOp.getReferencedGlobal(symbolTables);
1560 assert(globalOp &&
"No global-op found");
1562 handleStaticLocal(globalOp, initOp);
1572 return targetInfo.
getTriple().isOSDarwin();
1575static cir::GlobalLinkageKind
1578 return op.getLinkage();
1583 return op.getLinkage();
1587 if (op.isDeclaration())
1588 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1589 return cir::GlobalLinkageKind::WeakODRLinkage;
1593LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
1595 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1596 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1598 mlir::StringAttr wrapperName = op.getTlsRefs()->getWrapperName();
1600 auto existingWrapperIter = threadLocalWrappers.find(wrapperName.getValue());
1601 if (existingWrapperIter != threadLocalWrappers.end())
1602 return existingWrapperIter->second;
1605 auto funcType = cir::FuncType::get({}, builder.
getPointerTo(op.getSymType()));
1607 cir::FuncOp::create(builder, op.getLoc(), wrapperName, funcType);
1609 cir::GlobalLinkageKind linkageKind =
1611 func.setLinkageAttr(
1612 cir::GlobalLinkageKindAttr::get(&getContext(), linkageKind));
1616 if (getTargetInfo().
getTriple().supportsCOMDAT() && func.isWeakForLinker())
1617 func.setComdat(
true);
1619 mlir::SymbolTable::setSymbolVisibility(
1620 func, mlir::SymbolTable::Visibility::Private);
1625 op.getGlobalVisibility() == cir::VisibilityKind::Hidden)
1626 func.setGlobalVisibility(cir::VisibilityKind::Hidden);
1629 op->emitError(
"Unhandled thread wrapper attributes for CC and Nounwind");
1631 threadLocalWrappers.insert({wrapperName.getValue(), func});
1635void LoweringPreparePass::defineGlobalThreadLocalWrapper(cir::GlobalOp op,
1636 cir::FuncOp initAlias,
1637 bool isVarDefinition) {
1638 CIRBaseBuilderTy builder(getContext());
1639 cir::FuncOp wrapper = getOrCreateThreadLocalWrapper(builder, op);
1640 mlir::Block *entryBB = wrapper.addEntryBlock();
1641 builder.setInsertionPointToStart(entryBB);
1645 mlir::Location aliasLoc = initAlias.getLoc();
1646 if (!isVarDefinition) {
1648 mlir::Value funcLoad = cir::GetGlobalOp::create(
1649 builder, aliasLoc, cir::PointerType::get(initAlias.getFunctionType()),
1650 initAlias.getSymName());
1651 mlir::Value nullCheck =
1653 mlir::Value cmp = cir::CmpOp::create(
1654 builder, aliasLoc, cir::CmpOpKind::ne, funcLoad, nullCheck);
1655 cir::IfOp::create(builder, aliasLoc, cmp,
false,
1656 [&](mlir::OpBuilder &, mlir::Location loc) {
1658 cir::YieldOp::create(builder, aliasLoc);
1667 cir::ReturnOp::create(builder, op.getLoc(), {get});
1671LoweringPreparePass::defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
1672 cir::FuncOp aliasee) {
1673 CIRBaseBuilderTy builder(getContext());
1674 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1675 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1676 mlir::StringAttr aliasName = op.getTlsRefs()->getInitName();
1677 auto existingAliasIter = threadLocalInitAliases.find(aliasName.getValue());
1679 if (existingAliasIter != threadLocalInitAliases.end())
1680 return existingAliasIter->second;
1684 cir::FuncOp::create(builder, op.getLoc(), aliasName, funcType);
1685 alias.setLinkage(op.getLinkage());
1688 alias.setAliasee(aliasee.getSymName());
1693 alias.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1694 mlir::SymbolTable::setSymbolVisibility(
1695 alias, mlir::SymbolTable::Visibility::Private);
1698 threadLocalInitAliases.insert({aliasName.getValue(), alias});
1702void LoweringPreparePass::lowerGlobalOp(GlobalOp op) {
1704 if (op.getStaticLocalGuard())
1707 mlir::Region &ctorRegion = op.getCtorRegion();
1708 mlir::Region &dtorRegion = op.getDtorRegion();
1709 cir::FuncOp initAlias;
1711 if (!ctorRegion.empty() || !dtorRegion.empty()) {
1714 cir::FuncOp f = buildCXXGlobalVarDeclInitFunc(op);
1717 ctorRegion.getBlocks().clear();
1718 dtorRegion.getBlocks().clear();
1721 if (op.getTlsModel() && !op.getStaticLocalGuard().has_value()) {
1733 if (op.getTlsRefs()->getGuardName()) {
1735 initAlias = defineGlobalThreadLocalInitAlias(op, f);
1738 initAlias = defineGlobalThreadLocalInitAlias(op, getTlsInitFn());
1742 globalThreadLocalInitializers.push_back(f);
1744 }
else if (std::optional<uint32_t> priority = op.getInitPriority()) {
1745 prioritizedDynamicInitializers[*priority].push_back(f);
1747 dynamicInitializers.push_back(f);
1749 }
else if (op.getTlsModel() && op.getTlsRefs() && op.isDeclaration()) {
1752 initAlias = defineGlobalThreadLocalInitAlias(op, {});
1758 if (op.getTlsModel() && op.getTlsRefs())
1759 defineGlobalThreadLocalWrapper(op, initAlias, !op.isDeclaration());
1764void LoweringPreparePass::lowerGetGlobalOp(GetGlobalOp op) {
1767 auto globalOp = mlir::cast<cir::GlobalOp>(
1768 symbolTables.lookupNearestSymbolFrom(op, op.getNameAttr()));
1774 if (!globalOp.getTlsModel() || !globalOp.getTlsRefs())
1792 mlir::Operation *parentOp = op->getParentOp();
1793 if (parentOp == globalOp) {
1794 mlir::Region *ctorRegion = &globalOp.getCtorRegion();
1795 mlir::Region *dtorRegion = &globalOp.getDtorRegion();
1797 if (!ctorRegion->empty() && &*ctorRegion->op_begin() == op.getOperation())
1799 if (!dtorRegion->empty() && &*dtorRegion->op_begin() == op.getOperation())
1803 CIRBaseBuilderTy builder(getContext());
1804 cir::FuncOp wrapperFunc = getOrCreateThreadLocalWrapper(builder, globalOp);
1806 builder.setInsertionPoint(op);
1808 wrapperFunc.getLoc(),
1809 mlir::FlatSymbolRefAttr::get(wrapperFunc.getSymNameAttr()),
1810 wrapperFunc.getFunctionType().getReturnType(), {});
1811 op->replaceAllUsesWith(call);
1815void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
1816 CIRBaseBuilderTy builder(getContext());
1817 builder.setInsertionPointAfter(op);
1819 mlir::Location loc = op->getLoc();
1820 cir::CmpThreeWayInfoAttr cmpInfo = op.getInfo();
1829 mlir::Value transformedResult;
1830 if (cmpInfo.getOrdering() != CmpOrdering::Partial) {
1833 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1834 mlir::Value selectOnLt = builder.
createSelect(loc, lt, ltRes, gtRes);
1836 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1837 transformedResult = builder.
createSelect(loc, eq, eqRes, selectOnLt);
1841 loc, op.getType(), cmpInfo.getUnordered().value());
1844 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1845 mlir::Value selectOnEq = builder.
createSelect(loc, eq, eqRes, unorderedRes);
1847 builder.
createCompare(loc, CmpOpKind::gt, op.getLhs(), op.getRhs());
1848 mlir::Value selectOnGt = builder.
createSelect(loc, gt, gtRes, selectOnEq);
1850 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1851 transformedResult = builder.
createSelect(loc, lt, ltRes, selectOnGt);
1854 op.replaceAllUsesWith(transformedResult);
1858template <
typename AttributeTy>
1859static llvm::SmallVector<mlir::Attribute>
1863 for (
const auto &[name, priority] : list)
1864 attrs.push_back(AttributeTy::get(context, name, priority));
1868void LoweringPreparePass::buildGlobalCtorDtorList() {
1869 if (!globalCtorList.empty()) {
1870 llvm::SmallVector<mlir::Attribute> globalCtors =
1874 mlirModule->setAttr(cir::CIRDialect::getGlobalCtorsAttrName(),
1875 mlir::ArrayAttr::get(&getContext(), globalCtors));
1878 if (!globalDtorList.empty()) {
1879 llvm::SmallVector<mlir::Attribute> globalDtors =
1882 mlirModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(),
1883 mlir::ArrayAttr::get(&getContext(), globalDtors));
1888LoweringPreparePass::createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
1889 mlir::Location loc) {
1890 mlir::OpBuilder::InsertionGuard guard(builder);
1891 builder.setInsertionPointToStart(mlirModule.getBody());
1894 cir::IntType guardTy = builder.
getSIntNTy(8);
1895 auto g = cir::GlobalOp::create(builder, loc,
"__tls_guard", guardTy);
1896 g.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
1897 builder.getContext(), cir::GlobalLinkageKind::InternalLinkage));
1900 if (
auto defTlsModel = mlirModule->getAttrOfType<TLSModelAttr>(
1901 cir::CIRDialect::getDefaultTlsModelAttrName())) {
1902 g.setTlsModel(defTlsModel.getValue());
1905 g.setTlsModel(TLSModel::GeneralDynamic);
1908 g.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
1912cir::IfOp LoweringPreparePass::buildGlobalTlsGuardCheck(
1913 CIRBaseBuilderTy &builder, mlir::Location loc, cir::GlobalOp guard) {
1915 mlir::Value getGuardValue = getGuard;
1920 if (guard.getSymType() != builder.
getSIntNTy(8))
1922 getGuard, cir::PointerType::get(builder.
getSIntNTy(8)));
1924 mlir::Value guardLoad =
1928 builder.
createCompare(loc, cir::CmpOpKind::eq, guardLoad, zero);
1929 return cir::IfOp::create(
1931 false, [&](mlir::OpBuilder &, mlir::Location loc) {
1935 loc, builder.
getConstantInt(loc, guard.getSymType(), 1), getGuard);
1939void LoweringPreparePass::buildCXXGlobalTlsFunc() {
1940 if (globalThreadLocalInitializers.empty())
1946 cir::FuncOp tlsInit = getTlsInitFn();
1947 mlir::Location loc = tlsInit.getLoc();
1948 CIRBaseBuilderTy builder(getContext());
1949 mlir::Block *entryBB = tlsInit.addEntryBlock();
1950 builder.setInsertionPointToStart(entryBB);
1952 cir::IfOp ifOperation = buildGlobalTlsGuardCheck(
1953 builder, loc, createGlobalThreadLocalGuard(builder, loc));
1956 builder.setInsertionPointToEnd(&ifOperation.getThenRegion().front());
1957 for (cir::FuncOp initFunc : globalThreadLocalInitializers)
1959 cir::YieldOp::create(builder, loc);
1961 builder.setInsertionPointAfter(ifOperation);
1962 cir::ReturnOp::create(builder, loc);
1969 assert(priority <= 65535 &&
"Priority should always be <= 65535.");
1970 std::string prioritySuffix = llvm::utostr(priority);
1971 assert(prioritySuffix.size() < 6);
1972 prioritySuffix = std::string(6 - prioritySuffix.size(),
'0') + prioritySuffix;
1973 return prioritySuffix;
1976cir::FuncOp LoweringPreparePass::buildGlobalInitCallerFunc(
1977 llvm::StringRef fnName, cir::GlobalLinkageKind linkage,
1978 llvm::ArrayRef<cir::FuncOp> initializers,
uint32_t priority) {
1979 CIRBaseBuilderTy builder(getContext());
1980 builder.setInsertionPointToEnd(&mlirModule.getBodyRegion().back());
1981 auto fnType = cir::FuncType::get({}, builder.
getVoidTy());
1982 cir::FuncOp fn = buildRuntimeFunction(builder, fnName, mlirModule.getLoc(),
1984 builder.setInsertionPointToStart(fn.addEntryBlock());
1985 for (cir::FuncOp init : initializers)
1987 cir::ReturnOp::create(builder, fn.getLoc());
1988 globalCtorList.emplace_back(fnName, priority);
1992void LoweringPreparePass::buildCXXGlobalPriorityInitFuncs() {
1996 for (
const auto &[priority, initializers] : prioritizedDynamicInitializers) {
1997 SmallString<256> fnName;
1998 fnName +=
"_GLOBAL__I_";
2001 buildGlobalInitCallerFunc(fnName, cir::GlobalLinkageKind::InternalLinkage,
2002 initializers, priority);
2006void LoweringPreparePass::buildCXXGlobalInitFunc() {
2007 buildCXXGlobalPriorityInitFuncs();
2009 if (dynamicInitializers.empty())
2012 SmallString<256> fnName;
2013 cir::GlobalLinkageKind linkage;
2024 if (
auto fnNameAttr = mlirModule->getAttrOfType<mlir::StringAttr>(
2025 cir::CIRDialect::getCXXModuleInitFnNameAttrName())) {
2026 fnName += fnNameAttr.getValue();
2027 linkage = cir::GlobalLinkageKind::ExternalLinkage;
2029 fnName +=
"_GLOBAL__sub_I_";
2031 linkage = cir::GlobalLinkageKind::InternalLinkage;
2034 buildGlobalInitCallerFunc(fnName, linkage, dynamicInitializers,
2035 cir::GlobalCtorAttr::getDefaultPriority());
2044 mlir::Operation *op, mlir::Type eltTy,
2046 mlir::Value numElements,
2047 uint64_t arrayLen,
bool isCtor) {
2048 mlir::Location loc = op->getLoc();
2049 bool isDynamic = numElements !=
nullptr;
2053 const unsigned sizeTypeSize =
2059 mlir::Value begin, end;
2062 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, numElements);
2064 mlir::Value endOffsetVal =
2066 begin = cir::CastOp::create(builder, loc, eltTy,
2067 cir::CastKind::array_to_ptrdecay, addr);
2068 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
2071 mlir::Value start = isCtor ? begin : end;
2072 mlir::Value stop = isCtor ? end : begin;
2078 mlir::Value guardCond;
2081 guardCond = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
2087 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, start, stop);
2089 ifOp = cir::IfOp::create(builder, loc, guardCond,
2091 [&](mlir::OpBuilder &, mlir::Location) {});
2092 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
2095 mlir::Value tmpAddr =
2100 mlir::Block *bodyBlock = &op->getRegion(0).front();
2105 auto cloneRegionBodyInto = [&](mlir::Block *srcBlock,
2106 mlir::Value replacement) {
2107 mlir::IRMapping map;
2108 map.map(srcBlock->getArgument(0), replacement);
2109 for (mlir::Operation ®ionOp : *srcBlock) {
2110 if (!mlir::isa<cir::YieldOp>(®ionOp))
2111 builder.clone(regionOp, map);
2115 mlir::Block *partialDtorBlock =
nullptr;
2116 if (
auto arrayCtor = mlir::dyn_cast<cir::ArrayCtor>(op)) {
2117 mlir::Region &partialDtor = arrayCtor.getPartialDtor();
2118 if (!partialDtor.empty())
2119 partialDtorBlock = &partialDtor.front();
2120 }
else if (
auto arrayDtor = mlir::dyn_cast<cir::ArrayDtor>(op)) {
2129 if (arrayDtor.getDtorMayThrow())
2130 partialDtorBlock = bodyBlock;
2133 auto emitCtorDtorLoop = [&]() {
2137 [&](mlir::OpBuilder &b, mlir::Location loc) {
2138 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2139 auto cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
2140 currentElement, stop);
2144 [&](mlir::OpBuilder &b, mlir::Location loc) {
2145 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2147 cloneRegionBodyInto(bodyBlock, currentElement);
2148 mlir::Value stride = builder.
getUnsignedInt(loc, 1, sizeTypeSize);
2149 auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2150 currentElement, stride);
2153 mlir::Value stride = builder.
getSignedInt(loc, -1, sizeTypeSize);
2154 auto prevElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2155 currentElement, stride);
2157 cloneRegionBodyInto(bodyBlock, prevElement);
2160 cir::YieldOp::create(b, loc);
2164 if (partialDtorBlock) {
2165 cir::CleanupScopeOp::create(
2166 builder, loc, cir::CleanupKind::EH,
2168 [&](mlir::OpBuilder &b, mlir::Location loc) {
2170 cir::YieldOp::create(b, loc);
2173 [&](mlir::OpBuilder &b, mlir::Location loc) {
2174 auto cur = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2176 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, cur, begin);
2178 builder, loc, cmp,
false,
2179 [&](mlir::OpBuilder &b, mlir::Location loc) {
2183 [&](mlir::OpBuilder &b, mlir::Location loc) {
2184 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2185 auto neq = cir::CmpOp::create(
2186 builder, loc, cir::CmpOpKind::ne, el, begin);
2190 [&](mlir::OpBuilder &b, mlir::Location loc) {
2191 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2192 mlir::Value negOne =
2194 auto prev = cir::PtrStrideOp::create(builder, loc, eltTy,
2197 cloneRegionBodyInto(partialDtorBlock, prev);
2200 cir::YieldOp::create(builder, loc);
2202 cir::YieldOp::create(b, loc);
2209 cir::YieldOp::create(builder, loc);
2214void LoweringPreparePass::lowerArrayDtor(cir::ArrayDtor op) {
2215 CIRBaseBuilderTy builder(getContext());
2216 builder.setInsertionPointAfter(op.getOperation());
2218 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2220 if (op.getNumElements()) {
2222 op.getAddr(), op.getNumElements(),
2229 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2235void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
2236 cir::CIRBaseBuilderTy builder(getContext());
2237 builder.setInsertionPointAfter(op.getOperation());
2239 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2241 if (op.getNumElements()) {
2243 op.getAddr(), op.getNumElements(),
2250 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2256cir::FuncOp LoweringPreparePass::getCalledFunction(cir::CallOp callOp) {
2257 mlir::SymbolRefAttr sym = llvm::dyn_cast_if_present<mlir::SymbolRefAttr>(
2258 callOp.getCallableForCallee());
2261 return symbolTables.lookupNearestSymbolFrom<cir::FuncOp>(callOp, sym);
2264void LoweringPreparePass::lowerTrivialCopyCall(cir::CallOp op) {
2265 cir::FuncOp funcOp = getCalledFunction(op);
2269 std::optional<cir::CtorKind> ctorKind = funcOp.getCxxConstructorKind();
2270 if (ctorKind && *ctorKind == cir::CtorKind::Copy &&
2271 funcOp.isCxxTrivialMemberFunction()) {
2273 CIRBaseBuilderTy builder(getContext());
2274 mlir::ValueRange operands = op.getOperands();
2275 mlir::Value dest = operands[0];
2276 mlir::Value src = operands[1];
2277 builder.setInsertionPoint(op);
2283cir::GlobalOp LoweringPreparePass::getOrCreateConstAggregateGlobal(
2284 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef baseName,
2285 mlir::Type ty, mlir::TypedAttr constant, uint64_t alignment) {
2287 llvm::SmallVector<cir::GlobalOp, 1> &versions =
2288 constAggregateGlobals[baseName];
2291 for (cir::GlobalOp gv : versions) {
2292 if (gv.getSymType() == ty && gv.getInitialValue() == constant &&
2293 gv.getAlignment() == alignment)
2301 llvm::SmallString<128>
name(baseName);
2302 size_t baseLen =
name.size();
2303 unsigned version = versions.size();
2305 name.resize(baseLen);
2307 name.push_back(
'.');
2308 llvm::Twine(version).toVector(name);
2310 auto existingGv = symbolTables.lookupSymbolIn<cir::GlobalOp>(
2311 mlirModule, mlir::StringAttr::get(&getContext(), name));
2314 versions.push_back(existingGv);
2315 if (existingGv.getSymType() == ty &&
2316 existingGv.getInitialValue() == constant &&
2317 existingGv.getAlignment() == alignment)
2323 mlir::OpBuilder::InsertionGuard guard(builder);
2324 builder.setInsertionPointToStart(mlirModule.getBody());
2326 cir::GlobalOp::create(builder, loc, name, ty,
2328 cir::LangAddressSpaceAttr::get(
2329 &getContext(), cir::LangAddressSpace::Default),
2330 cir::GlobalLinkageKind::PrivateLinkage);
2331 mlir::SymbolTable::setSymbolVisibility(
2332 gv, mlir::SymbolTable::Visibility::Private);
2333 gv.setInitialValueAttr(constant);
2334 gv.setAlignment(alignment);
2338 symbolTables.getSymbolTable(mlirModule).insert(gv);
2340 versions.push_back(gv);
2344void LoweringPreparePass::lowerStoreOfConstAggregate(cir::StoreOp op) {
2346 auto constOp = op.getValue().getDefiningOp<cir::ConstantOp>();
2350 mlir::Type ty = constOp.getType();
2351 if (!mlir::isa<cir::ArrayType, cir::RecordType>(ty))
2357 auto alloca = op.getAddr().getDefiningOp<cir::AllocaOp>();
2361 mlir::TypedAttr constant = constOp.getValue();
2372 auto func = op->getParentOfType<cir::FuncOp>();
2375 llvm::StringRef funcName = func.getSymName();
2378 llvm::StringRef varName = alloca.getName();
2381 std::string baseName = (
"__const." + funcName +
"." + varName).str();
2382 CIRBaseBuilderTy builder(getContext());
2386 cir::GlobalOp gv = getOrCreateConstAggregateGlobal(
2387 builder, op.getLoc(), baseName, ty, constant, alloca.getAlignment());
2390 builder.setInsertionPoint(op);
2392 auto ptrTy = cir::PointerType::get(ty);
2393 mlir::Value globalPtr =
2394 cir::GetGlobalOp::create(builder, op.getLoc(), ptrTy, gv.getSymName());
2397 cir::CopyOp copyOp = builder.
createCopy(op.getAddr(), globalPtr);
2399 cir::CIRDataLayout dataLayout(mlirModule);
2400 uint64_t naturalAlign = dataLayout.getABITypeAlign(ty).value();
2401 if (alloca.getAlignment() != naturalAlign)
2402 copyOp.setDstAlignment(alloca.getAlignment());
2403 uint64_t srcAlign = gv.getAlignment().value_or(naturalAlign);
2404 if (srcAlign != naturalAlign)
2405 copyOp.setSrcAlignment(srcAlign);
2411 if (constOp.use_empty())
2418void LoweringPreparePass::lowerStdOp(cir::StdOpInterface typedOp) {
2419 mlir::Operation *op = typedOp.getOperation();
2420 cir::CIRBaseBuilderTy builder(getContext());
2421 builder.setInsertionPointAfter(op);
2422 mlir::Type resultType;
2423 if (op->getNumResults())
2424 resultType = op->getResult(0).getType();
2426 op->getLoc(), typedOp.getOriginalFnAttr(), resultType, op->getOperands());
2440 for (mlir::NamedAttribute attr : op->getDiscardableAttrs()) {
2441 if (call->getInherentAttr(
attr.getName()).has_value())
2442 call->setInherentAttr(
attr.getName(),
attr.getValue());
2444 call->setDiscardableAttr(
attr.getName(),
attr.getValue());
2447 op->replaceAllUsesWith(call);
2451void LoweringPreparePass::runOnOp(mlir::Operation *op) {
2452 if (
auto arrayCtor = dyn_cast<cir::ArrayCtor>(op)) {
2453 lowerArrayCtor(arrayCtor);
2454 }
else if (
auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) {
2455 lowerArrayDtor(arrayDtor);
2456 }
else if (
auto stdOp = mlir::dyn_cast<cir::StdOpInterface>(op)) {
2458 }
else if (
auto cast = mlir::dyn_cast<cir::CastOp>(op)) {
2460 }
else if (
auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
2461 lowerComplexConjOp(complexConj);
2462 }
else if (
auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
2463 lowerComplexDivOp(complexDiv);
2464 }
else if (
auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
2465 lowerComplexMulOp(complexMul);
2466 }
else if (
auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) {
2467 lowerGlobalOp(glob);
2468 if (
auto regAttr = glob->getAttrOfType<CUDAVarRegistrationInfoAttr>(
2469 CUDAVarRegistrationInfoAttr::getMnemonic()))
2470 cudaDeviceVars.emplace_back(glob, regAttr);
2471 }
else if (
auto getGlob = mlir::dyn_cast<cir::GetGlobalOp>(op)) {
2472 lowerGetGlobalOp(getGlob);
2473 }
else if (
auto callOp = dyn_cast<cir::CallOp>(op)) {
2474 lowerTrivialCopyCall(callOp);
2475 }
else if (
auto storeOp = dyn_cast<cir::StoreOp>(op)) {
2476 lowerStoreOfConstAggregate(storeOp);
2477 }
else if (
auto fnOp = dyn_cast<cir::FuncOp>(op)) {
2478 if (
auto globalCtor = fnOp.getGlobalCtorPriority())
2479 globalCtorList.emplace_back(fnOp.getName(), globalCtor.value());
2480 else if (
auto globalDtor = fnOp.getGlobalDtorPriority())
2481 globalDtorList.emplace_back(fnOp.getName(), globalDtor.value());
2483 if (mlir::Attribute attr =
2484 fnOp->getAttr(cir::CUDAKernelNameAttr::getMnemonic())) {
2485 auto kernelNameAttr = dyn_cast<CUDAKernelNameAttr>(attr);
2486 llvm::StringRef kernelName = kernelNameAttr.getKernelName();
2487 cudaKernelMap[kernelName] = fnOp;
2489 }
else if (
auto threeWayCmp = dyn_cast<cir::CmpThreeWayOp>(op)) {
2490 lowerThreeWayCmpOp(threeWayCmp);
2491 }
else if (
auto initOp = dyn_cast<cir::LocalInitOp>(op)) {
2492 lowerLocalInitOp(initOp);
2503 llvm::StringRef name) {
2504 return (
"__" + prefix + name).str();
2526void LoweringPreparePass::buildCUDAModuleCtor() {
2527 bool isHIP = getLangOpts().HIP;
2529 if (getLangOpts().GPURelocatableDeviceCode)
2530 llvm_unreachable(
"GPU RDC NYI");
2534 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2539 auto deviceBinaryAttr = mlirModule->getAttrOfType<mlir::StringAttr>(
2540 CIRDialect::getCUDADeviceBinaryAttrName());
2541 if (!deviceBinaryAttr) {
2549 mlir::Location loc = mlirModule->getLoc();
2550 CIRBaseBuilderTy builder(getContext());
2551 builder.setInsertionPointToStart(mlirModule.getBody());
2555 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2561 llvm::StringRef fatbinConstName =
2562 getLangOpts().HIP ?
".hip_fatbin" :
".nv_fatbin";
2564 llvm::StringRef fatbinSectionName =
2565 getLangOpts().HIP ?
".hipFatBinSegment" :
".nvFatBinSegment";
2569 auto fatbinType = mlir::cast<ArrayType>(deviceBinaryAttr.getType());
2571 GlobalOp fatbinStr = GlobalOp::create(builder, loc, fatbinStrName, fatbinType,
2573 GlobalLinkageKind::PrivateLinkage);
2575 const unsigned HIPCodeObjectAlign = 4096;
2576 fatbinStr.setAlignment(HIPCodeObjectAlign);
2578 fatbinStr.setAlignment(8);
2581 fatbinStr.setInitialValueAttr(
2582 cir::ConstArrayAttr::get(fatbinType, deviceBinaryAttr));
2583 fatbinStr.setSection(fatbinConstName);
2584 fatbinStr.setPrivate();
2588 mlir::Type fatbinWrapperMembers[] = {intTy, intTy, voidPtrTy, voidPtrTy};
2589 auto fatbinWrapperType = cir::StructType::get(
2590 &getContext(), fatbinWrapperMembers,
false,
false,
2592 std::string fatbinWrapperName =
2594 GlobalOp fatbinWrapper = GlobalOp::create(
2595 builder, loc, fatbinWrapperName, fatbinWrapperType,
2596 true, {}, GlobalLinkageKind::PrivateLinkage);
2597 fatbinWrapper.setSection(fatbinSectionName);
2599 constexpr unsigned cudaFatMagic = 0x466243b1;
2600 constexpr unsigned hipFatMagic = 0x48495046;
2601 unsigned fatMagic =
isHIP ? hipFatMagic : cudaFatMagic;
2603 auto magicInit = IntAttr::get(intTy, fatMagic);
2604 auto versionInit = IntAttr::get(intTy, 1);
2605 auto fatbinStrSymbol =
2606 mlir::FlatSymbolRefAttr::get(fatbinStr.getSymNameAttr());
2607 auto fatbinInit = GlobalViewAttr::get(voidPtrTy, fatbinStrSymbol);
2609 fatbinWrapper.setInitialValueAttr(cir::ConstRecordAttr::get(
2611 mlir::ArrayAttr::get(&getContext(),
2612 {magicInit, versionInit, fatbinInit, unusedInit})));
2615 std::string gpubinHandleName =
2618 GlobalOp gpuBinHandle = GlobalOp::create(
2619 builder, loc, gpubinHandleName, voidPtrPtrTy,
2620 false, {}, cir::GlobalLinkageKind::InternalLinkage);
2622 gpuBinHandle.setPrivate();
2627 std::string regFuncName =
2629 FuncType regFuncType = FuncType::get({voidPtrTy}, voidPtrPtrTy);
2630 cir::FuncOp regFunc =
2631 buildRuntimeFunction(builder, regFuncName, loc, regFuncType);
2634 cir::FuncOp moduleCtor = buildRuntimeFunction(
2635 builder, moduleCtorName, loc, FuncType::get({}, voidTy),
2636 GlobalLinkageKind::InternalLinkage);
2638 globalCtorList.emplace_back(moduleCtorName,
2639 cir::GlobalCtorAttr::getDefaultPriority());
2640 builder.setInsertionPointToStart(moduleCtor.addEntryBlock());
2648 mlir::Block *entryBlock = builder.getInsertionBlock();
2649 mlir::Region *parent = entryBlock->getParent();
2650 mlir::Block *ifBlock = builder.createBlock(parent);
2651 mlir::Block *exitBlock = builder.createBlock(parent);
2653 mlir::OpBuilder::InsertionGuard guard(builder);
2654 builder.setInsertionPointToEnd(entryBlock);
2655 mlir::Value handle =
2657 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2658 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2659 mlir::Value isNull =
2660 builder.
createCompare(loc, cir::CmpOpKind::eq, handle, nullPtr);
2661 cir::BrCondOp::create(builder, loc, isNull, ifBlock, exitBlock);
2665 mlir::OpBuilder::InsertionGuard guard(builder);
2666 builder.setInsertionPointToStart(ifBlock);
2668 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2669 cir::CallOp gpuBinaryHandleCall =
2671 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2673 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2674 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2675 cir::BrOp::create(builder, loc, exitBlock);
2680 mlir::OpBuilder::InsertionGuard guard(builder);
2681 builder.setInsertionPointToStart(exitBlock);
2682 mlir::Value gHandle =
2685 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals())
2688 if (std::optional<FuncOp> dtor = buildHIPModuleDtor()) {
2689 cir::CIRBaseBuilderTy globalBuilder(getContext());
2690 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2691 FuncOp atexit = buildRuntimeFunction(
2692 globalBuilder,
"atexit", loc,
2693 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2694 mlir::Value dtorFunc = GetGlobalOp::create(
2695 builder, loc, PointerType::get(dtor->getFunctionType()),
2696 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2699 cir::ReturnOp::create(builder, loc);
2703 if (!getLangOpts().GPURelocatableDeviceCode) {
2711 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2712 cir::CallOp gpuBinaryHandleCall =
2714 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2716 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2717 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2720 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals()) {
2721 builder.
createCallOp(loc, *regGlobal, gpuBinaryHandle);
2727 std::optional<llvm::VersionTuple> sdkVersion = getSDKVersion();
2732 cir::CIRBaseBuilderTy globalBuilder(getContext());
2733 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2735 buildRuntimeFunction(globalBuilder,
"__cudaRegisterFatBinaryEnd", loc,
2736 FuncType::get({voidPtrPtrTy}, voidTy));
2740 llvm_unreachable(
"GPU RDC NYI");
2745 if (std::optional<FuncOp> dtor = buildCUDAModuleDtor()) {
2748 cir::CIRBaseBuilderTy globalBuilder(getContext());
2749 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2750 FuncOp atexit = buildRuntimeFunction(
2751 globalBuilder,
"atexit", loc,
2752 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2753 mlir::Value dtorFunc = GetGlobalOp::create(
2754 builder, loc, PointerType::get(dtor->getFunctionType()),
2755 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2758 cir::ReturnOp::create(builder, loc);
2761std::optional<FuncOp> LoweringPreparePass::buildCUDAModuleDtor() {
2762 if (!mlirModule->getAttr(CIRDialect::getCUDADeviceBinaryAttrName()))
2767 VoidType voidTy = VoidType::get(&getContext());
2768 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2770 mlir::Location loc = mlirModule.getLoc();
2772 cir::CIRBaseBuilderTy builder(getContext());
2773 builder.setInsertionPointToStart(mlirModule.getBody());
2776 std::string unregisterFuncName =
2778 FuncOp unregisterFunc = buildRuntimeFunction(
2779 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2788 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2789 GlobalLinkageKind::InternalLinkage);
2791 builder.setInsertionPointToStart(dtor.addEntryBlock());
2797 GlobalOp gpubinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2799 mlir::Value gpubin = builder.
createLoad(loc, gpubinAddress);
2801 ReturnOp::create(builder, loc);
2818std::optional<FuncOp> LoweringPreparePass::buildHIPModuleDtor() {
2819 if (!mlirModule->getAttr(CIRDialect::getCUDADeviceBinaryAttrName()))
2824 VoidType voidTy = VoidType::get(&getContext());
2825 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2827 mlir::Location loc = mlirModule.getLoc();
2829 cir::CIRBaseBuilderTy builder(getContext());
2830 builder.setInsertionPointToStart(mlirModule.getBody());
2833 std::string unregisterFuncName =
2835 FuncOp unregisterFunc = buildRuntimeFunction(
2836 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2840 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2841 GlobalLinkageKind::InternalLinkage);
2844 GlobalOp gpuBinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2846 mlir::Block *entryBlock = dtor.addEntryBlock();
2847 mlir::Block *ifBlock = builder.createBlock(&dtor.getBody());
2848 mlir::Block *exitBlock = builder.createBlock(&dtor.getBody());
2850 mlir::OpBuilder::InsertionGuard guard(builder);
2851 builder.setInsertionPointToEnd(entryBlock);
2852 mlir::Value handle =
2854 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2855 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2856 mlir::Value isNotNull =
2857 builder.
createCompare(loc, cir::CmpOpKind::ne, handle, nullPtr);
2858 cir::BrCondOp::create(builder, loc, isNotNull, ifBlock, exitBlock);
2862 mlir::OpBuilder::InsertionGuard ifGuard(builder);
2863 builder.setInsertionPointToStart(ifBlock);
2866 cir::BrOp::create(builder, loc, exitBlock);
2869 mlir::OpBuilder::InsertionGuard exitGuard(builder);
2870 builder.setInsertionPointToStart(exitBlock);
2871 cir::ReturnOp::create(builder, loc);
2877std::optional<FuncOp> LoweringPreparePass::buildCUDARegisterGlobals() {
2878 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2881 cir::CIRBaseBuilderTy builder(getContext());
2882 builder.setInsertionPointToStart(mlirModule.getBody());
2884 mlir::Location loc = mlirModule.getLoc();
2887 auto voidTy = VoidType::get(&getContext());
2888 auto voidPtrTy = PointerType::get(voidTy);
2889 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2893 std::string regGlobalFuncName =
2895 auto regGlobalFuncTy = FuncType::get({voidPtrPtrTy}, voidTy);
2896 FuncOp regGlobalFunc =
2897 buildRuntimeFunction(builder, regGlobalFuncName, loc, regGlobalFuncTy,
2898 GlobalLinkageKind::InternalLinkage);
2899 builder.setInsertionPointToStart(regGlobalFunc.addEntryBlock());
2901 buildCUDARegisterGlobalFunctions(builder, regGlobalFunc);
2902 buildCUDARegisterVars(builder, regGlobalFunc);
2904 ReturnOp::create(builder, loc);
2905 return regGlobalFunc;
2908void LoweringPreparePass::buildCUDARegisterGlobalFunctions(
2909 cir::CIRBaseBuilderTy &builder, FuncOp regGlobalFunc) {
2910 mlir::Location loc = mlirModule.getLoc();
2912 cir::CIRDataLayout dataLayout(mlirModule);
2914 auto voidTy = VoidType::get(&getContext());
2915 auto voidPtrTy = PointerType::get(voidTy);
2916 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2919 cir::IntType::get(&getContext(), getTargetInfo().
getCharWidth(),
2923 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2925 cir::CIRBaseBuilderTy globalBuilder(getContext());
2926 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2940 FuncOp cudaRegisterFunction = buildRuntimeFunction(
2942 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2943 voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy},
2946 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2947 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2948 auto tmpString = cir::GlobalOp::create(
2949 globalBuilder, loc, (
".str" + str).str(), strType,
2951 cir::GlobalLinkageKind::PrivateLinkage);
2954 tmpString.setInitialValueAttr(
2955 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2956 tmpString.setPrivate();
2960 cir::ConstantOp cirNullPtr = builder.
getNullPtr(voidPtrTy, loc);
2961 bool isHIP = getLangOpts().HIP;
2962 for (
auto kernelName : cudaKernelMap.keys()) {
2963 FuncOp deviceStub = cudaKernelMap[kernelName];
2964 GlobalOp deviceFuncStr = makeConstantString(kernelName);
2968 mlir::Value hostFunc;
2975 auto funcHandle = cast<GlobalOp>(mlirModule.lookupSymbol(kernelName));
2980 GetGlobalOp::create(
2981 builder, loc, PointerType::get(deviceStub.getFunctionType()),
2982 mlir::FlatSymbolRefAttr::get(deviceStub.getSymNameAttr())),
2986 loc, cudaRegisterFunction,
2987 {fatbinHandle, hostFunc, deviceFunc, deviceFunc,
2988 ConstantOp::create(builder, loc, IntAttr::get(intTy, -1)), cirNullPtr,
2989 cirNullPtr, cirNullPtr, cirNullPtr, cirNullPtr});
2996void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
2997 FuncOp regGlobalFunc) {
2998 mlir::Location loc = mlirModule.getLoc();
3000 cir::CIRDataLayout dataLayout(mlirModule);
3003 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
3005 IntType sizeTy = builder.
getUIntNTy(getTargetInfo().getMaxPointerWidth());
3007 cir::IntType::get(&getContext(), getTargetInfo().
getCharWidth(),
3010 if (cudaDeviceVars.empty())
3013 cir::CIRBaseBuilderTy globalBuilder(getContext());
3014 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
3021 cir::VoidType voidTy = builder.
getVoidTy();
3022 FuncOp cudaRegisterVar = buildRuntimeFunction(
3024 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
3025 sizeTy, intTy, intTy},
3028 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
3029 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
3030 auto tmpString = cir::GlobalOp::create(
3031 globalBuilder, loc, (
".str" + str).str(), strType,
3033 cir::GlobalLinkageKind::PrivateLinkage);
3034 tmpString.setInitialValueAttr(
3035 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
3036 tmpString.setPrivate();
3040 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
3042 for (
auto &[global, regAttr] : cudaDeviceVars) {
3043 switch (regAttr.getKind()) {
3044 case cir::CUDADeviceVarKind::Variable:
3046 case cir::CUDADeviceVarKind::Surface:
3047 llvm_unreachable(
"Surface registration NYI");
3048 case cir::CUDADeviceVarKind::Texture:
3049 llvm_unreachable(
"Texture registration NYI");
3052 if (regAttr.getIsManaged())
3053 llvm_unreachable(
"Managed variable registration NYI");
3055 GlobalOp deviceNameStr = makeConstantString(regAttr.getDeviceSideName());
3058 mlir::Value hostVar =
3061 auto isExtern = ConstantOp::create(
3062 builder, loc, IntAttr::get(intTy, regAttr.getIsExtern() ? 1 : 0));
3063 llvm::TypeSize size = dataLayout.getTypeAllocSize(global.getSymType());
3064 auto varSize = ConstantOp::create(
3065 builder, loc, IntAttr::get(sizeTy, size.getFixedValue()));
3066 auto isConstant = ConstantOp::create(
3067 builder, loc, IntAttr::get(intTy, regAttr.getIsConstant() ? 1 : 0));
3068 auto normalized = ConstantOp::create(builder, loc, IntAttr::get(intTy, 0));
3070 {fatbinHandle, hostVar, deviceName, deviceName,
3071 isExtern, varSize, isConstant, normalized});
3075void LoweringPreparePass::runOnOperation() {
3076 mlirModule = getOperation();
3080 assert(lowerModule &&
"requires a module with a triple");
3082 llvm::SmallVector<mlir::Operation *> opsToTransform;
3084 mlirModule->walk([&](mlir::Operation *op) {
3085 if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
3086 cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
3087 cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
3088 cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
3089 cir::CmpThreeWayOp, cir::LocalInitOp, cir::StdOpInterface>(
3091 opsToTransform.push_back(op);
3094 for (mlir::Operation *o : opsToTransform)
3097 buildCXXGlobalInitFunc();
3098 buildCXXGlobalTlsFunc();
3099 if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice) {
3100 buildCUDAModuleCtor();
3105 mlirModule->removeAttr(CIRDialect::getCUDADeviceBinaryAttrName());
3108 buildGlobalCtorDtorList();
3112 return std::make_unique<LoweringPreparePass>();
3115std::unique_ptr<Pass>
3117 auto pass = std::make_unique<LoweringPreparePass>();
3118 pass->setASTContext(astCtx);
3119 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 getGuardAbortFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
static mlir::Value buildRangeReductionComplexDiv(CIRBaseBuilderTy &builder, mlir::Location loc, mlir::Value lhsReal, mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag)
static cir::GlobalLinkageKind getThreadLocalWrapperLinkage(GlobalOp op, const clang::TargetInfo &targetInfo)
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 std::string getPrioritySuffix(unsigned priority)
Compute the zero-padded priority suffix used to name priority-specific global init functions,...
static bool isThreadWrapperReplaceable(const clang::TargetInfo &targetInfo)
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 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, const clang::TargetInfo &targetInfo)
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(const clang::LangOptions &langOpts)
static mlir::Type higherPrecisionElementTypeForComplexArithmetic(mlir::MLIRContext &context, const clang::TargetInfo &targetInfo, const clang::LangOptions &langOpts, CIRBaseBuilderTy &builder, mlir::Type elementType)
static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder, const clang::TargetInfo &targetInfo, 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 lowerScalarToComplexCast(mlir::MLIRContext &ctx, cir::CastOp op)
static StringRef getTriple(const Command &Job)
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 ...
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.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getTypeWidth(IntType T) const
Return the width (in bits) of the specified integer type enum.
IntType getSignedSizeType() const
Defines the clang::TargetInfo interface.
static bool isLocalLinkage(GlobalLinkageKind linkage)
static bool isWeakODRLinkage(GlobalLinkageKind linkage)
static bool isLinkOnceLinkage(GlobalLinkageKind linkage)
std::unique_ptr< LowerModule > createLowerModule(mlir::ModuleOp module)
const internal::VariadicAllOfMatcher< Attr > attr
bool isHIP(ID Id)
isHIP - Is this a HIP input.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
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()
__builtin_elementwise_add_sat __builtin_elementwise_sub_sat uint32_t __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 opGlobalAnnotations()
static bool opGlobalCtorPriority()
static bool shouldSplitConstantStore()
static bool shouldUseMemSetToInitialize()
static bool opFuncExtraAttrs()
static bool shouldUseBZeroPlusStoresToInitialize()
static bool fastMathFlags()
static bool astVarDeclInterface()