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"
48#define GEN_PASS_DEF_LOWERINGPREPARE
49#include "clang/CIR/Dialect/Passes.h.inc"
53 SmallString<128> fileName;
55 if (mlirModule.getSymName())
56 fileName = llvm::sys::path::filename(mlirModule.getSymName()->str());
61 for (
size_t i = 0; i < fileName.size(); ++i) {
72struct LoweringPreparePass
73 :
public impl::LoweringPrepareBase<LoweringPreparePass> {
74 LoweringPreparePass() =
default;
84 LoweringPreparePass(
const LoweringPreparePass &other)
85 : impl::LoweringPrepareBase<LoweringPreparePass>(other) {}
87 void runOnOperation()
override;
89 void runOnOp(mlir::Operation *op);
90 void lowerCastOp(cir::CastOp op);
91 void lowerComplexConjOp(cir::ComplexConjOp op);
92 void lowerComplexDivOp(cir::ComplexDivOp op);
93 void lowerComplexMulOp(cir::ComplexMulOp op);
94 void lowerGetGlobalOp(cir::GetGlobalOp op);
95 void lowerGlobalOp(cir::GlobalOp op);
96 void lowerThreeWayCmpOp(cir::CmpThreeWayOp op);
97 void lowerArrayDtor(cir::ArrayDtor op);
98 void lowerArrayCtor(cir::ArrayCtor op);
99 void lowerTrivialCopyCall(cir::CallOp op);
100 void lowerStoreOfConstAggregate(cir::StoreOp op);
101 void lowerLocalInitOp(cir::LocalInitOp op);
102 void lowerStdOp(cir::StdOpInterface op);
107 cir::FuncOp getCalledFunction(cir::CallOp callOp);
117 getOrCreateConstAggregateGlobal(CIRBaseBuilderTy &builder, mlir::Location loc,
118 llvm::StringRef baseName, mlir::Type ty,
119 mlir::TypedAttr constant, uint64_t alignment);
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);
149 cir::FuncOp buildGlobalInitCallerFunc(
150 llvm::StringRef fnName, cir::GlobalLinkageKind linkage,
151 llvm::ArrayRef<cir::FuncOp> initializers,
uint32_t priority);
154 void buildCXXGlobalInitFunc();
158 void buildCXXGlobalPriorityInitFuncs();
161 void buildCXXGlobalTlsFunc();
164 void buildGlobalCtorDtorList();
166 cir::FuncOp buildRuntimeFunction(
167 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
169 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage);
171 cir::GlobalOp getOrCreateRuntimeVariable(
172 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
174 cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage,
175 cir::VisibilityKind visibility = cir::VisibilityKind::Default);
181 llvm::StringMap<FuncOp> cudaKernelMap;
182 llvm::SmallVector<std::pair<cir::GlobalOp, cir::CUDAVarRegistrationInfoAttr>>
187 void buildCUDAModuleCtor();
188 std::optional<FuncOp> buildCUDAModuleDtor();
189 std::optional<FuncOp> buildHIPModuleDtor();
190 std::optional<FuncOp> buildCUDARegisterGlobals();
191 void buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
192 FuncOp regGlobalFunc);
193 void buildCUDARegisterGlobalFunctions(cir::CIRBaseBuilderTy &builder,
194 FuncOp regGlobalFunc);
197 void handleStaticLocal(cir::GlobalOp globalOp, cir::LocalInitOp localInitOp);
209 cir::FuncOp getTlsInitFn();
212 cir::GlobalOp createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
216 cir::GlobalOp createGuardGlobalOp(CIRBaseBuilderTy &builder,
217 mlir::Location loc, llvm::StringRef name,
218 cir::IntType guardTy,
219 cir::GlobalLinkageKind linkage);
222 cir::GlobalOp getStaticLocalDeclGuardAddress(llvm::StringRef globalSymName) {
223 auto it = staticLocalDeclGuardMap.find(globalSymName);
224 if (it != staticLocalDeclGuardMap.end())
230 void setStaticLocalDeclGuardAddress(llvm::StringRef globalSymName,
231 cir::GlobalOp guard) {
232 staticLocalDeclGuardMap[globalSymName] = guard;
236 cir::GlobalOp getOrCreateStaticLocalDeclGuardAddress(
237 CIRBaseBuilderTy &builder, cir::GlobalOp globalOp, StringRef guardName,
238 bool isLocalVarDecl,
bool useInt8GuardVariable) {
240 cir::CIRDataLayout dataLayout(mlirModule);
241 cir::IntType guardTy;
242 clang::CharUnits guardAlignment;
245 if (useInt8GuardVariable) {
246 guardTy = cir::IntType::get(&getContext(), 8,
true);
248 }
else if (useARMGuardVarABI()) {
250 const unsigned sizeTypeSize =
251 astCtx->getTypeSize(astCtx->getSignedSizeType());
253 cir::IntType::get(&getContext(), sizeTypeSize,
true);
257 guardTy = cir::IntType::get(&getContext(), 64,
true);
261 assert(guardTy && guardAlignment.
getQuantity() != 0);
263 llvm::StringRef globalSymName = globalOp.getSymName();
264 cir::GlobalOp guard = getStaticLocalDeclGuardAddress(globalSymName);
267 guard = createGuardGlobalOp(builder, globalOp->getLoc(), guardName,
268 guardTy, globalOp.getLinkage());
269 guard.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
270 guard.setDSOLocal(globalOp.getDsoLocal());
271 guard.setAlignment(guardAlignment.
getAsAlign().value());
272 guard.setTlsModel(globalOp.getTlsModel());
278 bool hasComdat = globalOp.getComdat();
279 const llvm::Triple &triple = astCtx->getTargetInfo().getTriple();
282 if (!isLocalVarDecl && hasComdat &&
283 (triple.isOSBinFormatELF() || triple.isOSBinFormatWasm())) {
285 guard.setComdat(
true);
286 }
else if (hasComdat && globalOp.isWeakForLinker()) {
287 guard.setComdat(
true);
290 setStaticLocalDeclGuardAddress(globalSymName, guard);
299 clang::ASTContext *astCtx;
302 mlir::ModuleOp mlirModule;
322 mlir::SymbolTableCollection symbolTables;
325 llvm::StringMap<uint32_t> dynamicInitializerNames;
326 llvm::SmallVector<cir::FuncOp> dynamicInitializers;
331 std::map<unsigned, llvm::SmallVector<cir::FuncOp, 4>>
332 prioritizedDynamicInitializers;
333 llvm::SmallVector<cir::FuncOp> globalThreadLocalInitializers;
334 llvm::StringMap<cir::FuncOp> threadLocalWrappers;
335 llvm::StringMap<cir::FuncOp> threadLocalInitAliases;
338 llvm::StringMap<cir::GlobalOp> staticLocalDeclGuardMap;
340 llvm::StringMap<llvm::SmallVector<cir::GlobalOp, 1>> constAggregateGlobals;
343 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList;
345 llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalDtorList;
349 bool useARMGuardVarABI()
const {
350 switch (astCtx->getCXXABIKind()) {
351 case clang::TargetCXXABI::GenericARM:
352 case clang::TargetCXXABI::iOS:
353 case clang::TargetCXXABI::WatchOS:
354 case clang::TargetCXXABI::GenericAArch64:
355 case clang::TargetCXXABI::WebAssembly:
362 void emitGlobalGuardedDtorRegion(CIRBaseBuilderTy &builder,
363 cir::GlobalOp global,
364 mlir::Region &dtorRegion,
bool tls,
365 mlir::Block &entryBB) {
367 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
368 cir::GlobalOp handle = getOrCreateRuntimeVariable(
369 builder,
"__dso_handle", global.getLoc(), builder.
getUIntNTy(8),
370 cir::GlobalLinkageKind::ExternalLinkage, cir::VisibilityKind::Hidden);
376 cir::CallOp dtorCall;
377 cir::FuncOp dtorFunc =
378 getOrCreateDtorFunc(builder, global, dtorRegion, dtorCall);
383 cir::PointerType voidFnPtrTy = builder.
getVoidFnPtrTy({voidPtrTy});
384 cir::PointerType handlePtrTy = builder.
getPointerTo(handle.getSymType());
387 cir::FuncType::get({voidFnPtrTy, voidPtrTy, handlePtrTy}, intTy);
389 llvm::StringLiteral nameAtExit =
"__cxa_atexit";
391 nameAtExit = astCtx->getTargetInfo().getTriple().isOSDarwin()
392 ? llvm::StringLiteral(
"_tlv_atexit")
393 : llvm::StringLiteral(
"__cxa_thread_atexit");
395 cir::FuncOp fnAtExit = buildRuntimeFunction(builder, nameAtExit,
396 global.getLoc(), fnAtExitType);
400 builder.setInsertionPointAfter(dtorCall);
402 auto dtorPtrTy = cir::PointerType::get(dtorFunc.getFunctionType());
403 args[0] = cir::GetGlobalOp::create(builder, dtorCall.getLoc(), dtorPtrTy,
404 dtorFunc.getSymName());
405 args[0] = cir::CastOp::create(builder, dtorCall.getLoc(), voidFnPtrTy,
406 cir::CastKind::bitcast, args[0]);
408 cir::CastOp::create(builder, dtorCall.getLoc(), voidPtrTy,
409 cir::CastKind::bitcast, dtorCall.getArgOperand(0));
410 args[2] = cir::GetGlobalOp::create(builder, handle.getLoc(), handlePtrTy,
411 handle.getSymName());
412 builder.
createCallOp(dtorCall.getLoc(), fnAtExit, args);
414 mlir::Block &dtorBlock = dtorRegion.front();
415 entryBB.getOperations().splice(entryBB.end(), dtorBlock.getOperations(),
417 std::prev(dtorBlock.end()));
420 builder.setInsertionPointToEnd(&entryBB);
426 void emitCXXGuardedInitIf(CIRBaseBuilderTy &builder, cir::GlobalOp globalOp,
427 mlir::Region &ctorRegion, mlir::Region &dtorRegion,
428 bool isLocalVarDecl, mlir::Value guardPtr,
429 cir::PointerType guardPtrTy,
bool threadsafe) {
430 auto loc = globalOp->getLoc();
450 mlir::Block *insertBlock = builder.getInsertionBlock();
451 if (!ctorRegion.empty()) {
452 assert(ctorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
454 mlir::Block &block = ctorRegion.front();
455 insertBlock->getOperations().splice(
456 insertBlock->end(), block.getOperations(), block.begin(),
457 std::prev(block.end()));
460 if (!dtorRegion.empty()) {
461 assert(dtorRegion.hasOneBlock() &&
"Enforced by MaxSizedRegion<1>");
463 emitGlobalGuardedDtorRegion(builder, globalOp, dtorRegion, !threadsafe,
466 builder.setInsertionPointToEnd(insertBlock);
467 ctorRegion.getBlocks().clear();
475 mlir::Value acquireResult = acquireCall.getResult();
478 loc, mlir::cast<cir::IntType>(acquireResult.getType()), 0);
479 auto shouldInit = builder.
createCompare(loc, cir::CmpOpKind::ne,
480 acquireResult, acquireZero);
485 cir::IfOp::create(builder, loc, shouldInit,
false,
486 [](mlir::OpBuilder &, mlir::Location) {});
487 mlir::OpBuilder::InsertionGuard insertGuard(builder);
488 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
500 if (astCtx->getLangOpts().Exceptions) {
501 cir::CleanupScopeOp::create(
502 builder, loc, cir::CleanupKind::EH,
503 [&](mlir::OpBuilder &, mlir::Location bodyLoc) {
507 [&](mlir::OpBuilder &, mlir::Location cleanupLoc) {
508 cir::CallOp abortCall =
510 mlir::ValueRange{guardPtr});
514 abortCall.setNothrowAttr(builder.getUnitAttr());
517 builder.setInsertionPointToEnd(&ifOp.getThenRegion().front());
524 mlir::ValueRange{guardPtr});
527 }
else if (!isLocalVarDecl) {
533 globalOp->emitError(
"NYI: non-threadsafe init for non-local variables");
548 void setASTContext(clang::ASTContext *c) { astCtx = c; }
553cir::GlobalOp LoweringPreparePass::getOrCreateRuntimeVariable(
554 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
555 mlir::Type type, cir::GlobalLinkageKind linkage,
556 cir::VisibilityKind visibility) {
557 cir::GlobalOp g = dyn_cast_or_null<cir::GlobalOp>(
558 mlir::SymbolTable::lookupNearestSymbolFrom(
559 mlirModule, mlir::StringAttr::get(mlirModule->getContext(), name)));
561 g = cir::GlobalOp::create(builder, loc, name, type);
563 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
564 mlir::SymbolTable::setSymbolVisibility(
565 g, mlir::SymbolTable::Visibility::Private);
566 g.setGlobalVisibility(visibility);
571cir::FuncOp LoweringPreparePass::buildRuntimeFunction(
572 mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
573 cir::FuncType type, cir::GlobalLinkageKind linkage) {
574 cir::FuncOp f = dyn_cast_or_null<FuncOp>(SymbolTable::lookupNearestSymbolFrom(
575 mlirModule, StringAttr::get(mlirModule->getContext(), name)));
577 f = cir::FuncOp::create(builder, loc, name, type);
579 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
580 mlir::SymbolTable::setSymbolVisibility(
581 f, mlir::SymbolTable::Visibility::Private);
591 builder.setInsertionPoint(op);
593 mlir::Value src = op.getSrc();
594 mlir::Value imag = builder.
getNullValue(src.getType(), op.getLoc());
600 cir::CastKind elemToBoolKind) {
602 builder.setInsertionPoint(op);
604 mlir::Value src = op.getSrc();
605 if (!mlir::isa<cir::BoolType>(op.getType()))
612 cir::BoolType boolTy = builder.
getBoolTy();
613 mlir::Value srcRealToBool =
614 builder.
createCast(op.getLoc(), elemToBoolKind, srcReal, boolTy);
615 mlir::Value srcImagToBool =
616 builder.
createCast(op.getLoc(), elemToBoolKind, srcImag, boolTy);
617 return builder.
createLogicalOr(op.getLoc(), srcRealToBool, srcImagToBool);
622 cir::CastKind scalarCastKind) {
624 builder.setInsertionPoint(op);
626 mlir::Value src = op.getSrc();
627 auto dstComplexElemTy =
628 mlir::cast<cir::ComplexType>(op.getType()).getElementType();
633 mlir::Value dstReal = builder.
createCast(op.getLoc(), scalarCastKind, srcReal,
635 mlir::Value dstImag = builder.
createCast(op.getLoc(), scalarCastKind, srcImag,
640void LoweringPreparePass::lowerCastOp(cir::CastOp op) {
641 mlir::MLIRContext &ctx = getContext();
642 mlir::Value loweredValue = [&]() -> mlir::Value {
643 switch (op.getKind()) {
644 case cir::CastKind::float_to_complex:
645 case cir::CastKind::int_to_complex:
647 case cir::CastKind::float_complex_to_real:
648 case cir::CastKind::int_complex_to_real:
650 case cir::CastKind::float_complex_to_bool:
652 case cir::CastKind::int_complex_to_bool:
654 case cir::CastKind::float_complex:
656 case cir::CastKind::float_complex_to_int_complex:
658 case cir::CastKind::int_complex:
660 case cir::CastKind::int_complex_to_float_complex:
668 op.replaceAllUsesWith(loweredValue);
675 llvm::StringRef (*libFuncNameGetter)(llvm::APFloat::Semantics),
676 mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal,
677 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag) {
678 cir::FPTypeInterface elementTy =
679 mlir::cast<cir::FPTypeInterface>(ty.getElementType());
681 llvm::StringRef libFuncName = libFuncNameGetter(
682 llvm::APFloat::SemanticsToEnum(elementTy.getFloatSemantics()));
685 cir::FuncType libFuncTy = cir::FuncType::get(libFuncInputTypes, ty);
691 mlir::OpBuilder::InsertionGuard ipGuard{builder};
692 builder.setInsertionPointToStart(pass.mlirModule.getBody());
693 libFunc = pass.buildRuntimeFunction(builder, libFuncName, loc, libFuncTy);
697 builder.
createCallOp(loc, libFunc, {lhsReal, lhsImag, rhsReal, rhsImag});
698 return call.getResult();
701static llvm::StringRef
704 case llvm::APFloat::S_IEEEhalf:
706 case llvm::APFloat::S_IEEEsingle:
708 case llvm::APFloat::S_IEEEdouble:
710 case llvm::APFloat::S_PPCDoubleDouble:
712 case llvm::APFloat::S_x87DoubleExtended:
714 case llvm::APFloat::S_IEEEquad:
717 llvm_unreachable(
"unsupported floating point type");
723 mlir::Value lhsReal, mlir::Value lhsImag,
724 mlir::Value rhsReal, mlir::Value rhsImag) {
726 mlir::Value &a = lhsReal;
727 mlir::Value &b = lhsImag;
728 mlir::Value &c = rhsReal;
729 mlir::Value &d = rhsImag;
733 bool isFP = cir::isFPOrVectorOfFPType(a.getType());
734 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
737 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
740 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
743 auto div = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
747 mlir::Value ac = mul(loc, a, c);
748 mlir::Value bd = mul(loc, b, d);
749 mlir::Value cc = mul(loc, c, c);
750 mlir::Value dd = mul(loc, d, d);
751 mlir::Value acbd = add(loc, ac, bd);
752 mlir::Value ccdd = add(loc, cc, dd);
753 mlir::Value resultReal = div(loc, acbd, ccdd);
755 mlir::Value bc = mul(loc, b, c);
756 mlir::Value ad = mul(loc, a, d);
757 mlir::Value bcad = sub(loc, bc, ad);
758 mlir::Value resultImag = div(loc, bcad, ccdd);
764 mlir::Value lhsReal, mlir::Value lhsImag,
765 mlir::Value rhsReal, mlir::Value rhsImag) {
786 mlir::Value &a = lhsReal;
787 mlir::Value &b = lhsImag;
788 mlir::Value &c = rhsReal;
789 mlir::Value &d = rhsImag;
792 assert(cir::isFPOrVectorOfFPType(a.getType()) &&
793 "range-reduction complex divide expects floating-point operands");
795 auto trueBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
796 mlir::Value r = builder.
createFDiv(loc, d, c);
797 mlir::Value rd = builder.
createFMul(loc, r, d);
798 mlir::Value tmp = builder.
createFAdd(loc, c, rd);
800 mlir::Value br = builder.
createFMul(loc, b, r);
801 mlir::Value abr = builder.
createFAdd(loc, a, br);
802 mlir::Value e = builder.
createFDiv(loc, abr, tmp);
804 mlir::Value ar = builder.
createFMul(loc, a, r);
805 mlir::Value bar = builder.
createFSub(loc, b, ar);
806 mlir::Value f = builder.
createFDiv(loc, bar, tmp);
812 auto falseBranchBuilder = [&](mlir::OpBuilder &, mlir::Location) {
813 mlir::Value r = builder.
createFDiv(loc, c, d);
814 mlir::Value rc = builder.
createFMul(loc, r, c);
815 mlir::Value tmp = builder.
createFAdd(loc, d, rc);
817 mlir::Value ar = builder.
createFMul(loc, a, r);
818 mlir::Value arb = builder.
createFAdd(loc, ar, b);
819 mlir::Value e = builder.
createFDiv(loc, arb, tmp);
821 mlir::Value br = builder.
createFMul(loc, b, r);
822 mlir::Value bra = builder.
createFSub(loc, br, a);
823 mlir::Value f = builder.
createFDiv(loc, bra, tmp);
829 auto cFabs = cir::FAbsOp::create(builder, loc, c);
830 auto dFabs = cir::FAbsOp::create(builder, loc, d);
831 cir::CmpOp cmpResult =
832 builder.
createCompare(loc, cir::CmpOpKind::ge, cFabs, dFabs);
833 auto ternary = cir::TernaryOp::create(builder, loc, cmpResult,
834 trueBranchBuilder, falseBranchBuilder);
836 return ternary.getResult();
843 auto getHigherPrecisionFPType = [&context](mlir::Type type) -> mlir::Type {
844 if (mlir::isa<cir::FP16Type>(type))
845 return cir::SingleType::get(&context);
847 if (mlir::isa<cir::SingleType>(type) || mlir::isa<cir::BF16Type>(type))
848 return cir::DoubleType::get(&context);
850 if (mlir::isa<cir::DoubleType>(type))
851 return cir::LongDoubleType::get(&context, type);
856 auto getFloatTypeSemantics =
857 [&cc](mlir::Type type) ->
const llvm::fltSemantics & {
859 if (mlir::isa<cir::FP16Type>(type))
860 return info.getHalfFormat();
862 if (mlir::isa<cir::BF16Type>(type))
863 return info.getBFloat16Format();
865 if (mlir::isa<cir::SingleType>(type))
866 return info.getFloatFormat();
868 if (mlir::isa<cir::DoubleType>(type))
869 return info.getDoubleFormat();
871 if (mlir::isa<cir::LongDoubleType>(type)) {
873 llvm_unreachable(
"NYI Float type semantics with OpenMP");
874 return info.getLongDoubleFormat();
877 if (mlir::isa<cir::FP128Type>(type)) {
879 llvm_unreachable(
"NYI Float type semantics with OpenMP");
880 return info.getFloat128Format();
883 llvm_unreachable(
"Unsupported float type semantics");
886 const mlir::Type higherElementType = getHigherPrecisionFPType(elementType);
887 const llvm::fltSemantics &elementTypeSemantics =
888 getFloatTypeSemantics(elementType);
889 const llvm::fltSemantics &higherElementTypeSemantics =
890 getFloatTypeSemantics(higherElementType);
899 if (llvm::APFloat::semanticsMaxExponent(elementTypeSemantics) * 2 + 1 <=
900 llvm::APFloat::semanticsMaxExponent(higherElementTypeSemantics)) {
901 return higherElementType;
911 mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal,
912 mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag,
914 cir::ComplexType complexTy = op.getType();
915 if (mlir::isa<cir::FPTypeInterface>(complexTy.getElementType())) {
916 cir::ComplexRangeKind range = op.getRange();
917 if (range == cir::ComplexRangeKind::Improved)
921 if (range == cir::ComplexRangeKind::Full)
923 loc, complexTy, lhsReal, lhsImag, rhsReal,
926 if (range == cir::ComplexRangeKind::Promoted) {
927 mlir::Type originalElementType = complexTy.getElementType();
928 mlir::Type higherPrecisionElementType =
930 originalElementType);
932 if (!higherPrecisionElementType)
936 cir::CastKind floatingCastKind = cir::CastKind::floating;
937 lhsReal = builder.
createCast(floatingCastKind, lhsReal,
938 higherPrecisionElementType);
939 lhsImag = builder.
createCast(floatingCastKind, lhsImag,
940 higherPrecisionElementType);
941 rhsReal = builder.
createCast(floatingCastKind, rhsReal,
942 higherPrecisionElementType);
943 rhsImag = builder.
createCast(floatingCastKind, rhsImag,
944 higherPrecisionElementType);
947 builder, loc, lhsReal, lhsImag, rhsReal, rhsImag);
952 mlir::Value finalReal =
953 builder.
createCast(floatingCastKind, resultReal, originalElementType);
954 mlir::Value finalImag =
955 builder.
createCast(floatingCastKind, resultImag, originalElementType);
964void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) {
965 cir::CIRBaseBuilderTy builder(getContext());
966 builder.setInsertionPointAfter(op);
967 mlir::Location loc = op.getLoc();
968 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
969 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
975 mlir::Value loweredResult =
977 rhsImag, getContext(), *astCtx);
978 op.replaceAllUsesWith(loweredResult);
982static llvm::StringRef
985 case llvm::APFloat::S_IEEEhalf:
987 case llvm::APFloat::S_IEEEsingle:
989 case llvm::APFloat::S_IEEEdouble:
991 case llvm::APFloat::S_PPCDoubleDouble:
993 case llvm::APFloat::S_x87DoubleExtended:
995 case llvm::APFloat::S_IEEEquad:
998 llvm_unreachable(
"unsupported floating point type");
1004 mlir::Location loc, cir::ComplexMulOp op,
1005 mlir::Value lhsReal, mlir::Value lhsImag,
1006 mlir::Value rhsReal, mlir::Value rhsImag) {
1008 bool isFP = cir::isFPOrVectorOfFPType(lhsReal.getType());
1009 auto mul = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
1012 auto add = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
1015 auto sub = [&](mlir::Location l, mlir::Value x, mlir::Value y) {
1019 mlir::Value resultRealLhs = mul(loc, lhsReal, rhsReal);
1020 mlir::Value resultRealRhs = mul(loc, lhsImag, rhsImag);
1021 mlir::Value resultImagLhs = mul(loc, lhsReal, rhsImag);
1022 mlir::Value resultImagRhs = mul(loc, lhsImag, rhsReal);
1023 mlir::Value resultReal = sub(loc, resultRealLhs, resultRealRhs);
1024 mlir::Value resultImag = add(loc, resultImagLhs, resultImagRhs);
1025 mlir::Value algebraicResult =
1028 cir::ComplexType complexTy = op.getType();
1029 cir::ComplexRangeKind rangeKind = op.getRange();
1030 if (mlir::isa<cir::IntType>(complexTy.getElementType()) ||
1031 rangeKind == cir::ComplexRangeKind::Basic ||
1032 rangeKind == cir::ComplexRangeKind::Improved ||
1033 rangeKind == cir::ComplexRangeKind::Promoted)
1034 return algebraicResult;
1041 mlir::Value resultRealIsNaN = builder.
createIsNaN(loc, resultReal);
1042 mlir::Value resultImagIsNaN = builder.
createIsNaN(loc, resultImag);
1043 mlir::Value resultRealAndImagAreNaN =
1046 return cir::TernaryOp::create(
1047 builder, loc, resultRealAndImagAreNaN,
1048 [&](mlir::OpBuilder &, mlir::Location) {
1051 lhsReal, lhsImag, rhsReal, rhsImag);
1054 [&](mlir::OpBuilder &, mlir::Location) {
1060void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
1061 cir::CIRBaseBuilderTy builder(getContext());
1062 builder.setInsertionPointAfter(op);
1063 mlir::Location loc = op.getLoc();
1064 mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
1065 mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
1070 mlir::Value loweredResult =
lowerComplexMul(*
this, builder, loc, op, lhsReal,
1071 lhsImag, rhsReal, rhsImag);
1072 op.replaceAllUsesWith(loweredResult);
1076void LoweringPreparePass::lowerComplexConjOp(cir::ComplexConjOp op) {
1077 mlir::Location loc = op.getLoc();
1078 CIRBaseBuilderTy builder(getContext());
1079 builder.setInsertionPointAfter(op);
1081 mlir::Value operand = op.getOperand();
1086 const bool isFP = cir::isFPOrVectorOfFPType(operandReal.getType());
1087 mlir::Value resultImag = isFP ? builder.
createFNeg(loc, operandImag)
1090 mlir::Value result =
1092 op->replaceAllUsesWith(mlir::ValueRange{result});
1096cir::FuncOp LoweringPreparePass::getOrCreateDtorFunc(CIRBaseBuilderTy &builder,
1098 mlir::Region &dtorRegion,
1099 cir::CallOp &dtorCall) {
1100 mlir::OpBuilder::InsertionGuard guard(builder);
1103 cir::VoidType voidTy = builder.
getVoidTy();
1104 auto voidPtrTy = cir::PointerType::get(voidTy);
1107 mlir::Block &dtorBlock = dtorRegion.front();
1111 auto opIt = dtorBlock.getOperations().begin();
1112 cir::GetGlobalOp ggop = mlir::cast<cir::GetGlobalOp>(*opIt);
1123 if (dtorBlock.getOperations().size() == 3) {
1124 auto callOp = mlir::dyn_cast<cir::CallOp>(&*(++opIt));
1125 auto yieldOp = mlir::dyn_cast<cir::YieldOp>(&*(++opIt));
1126 if (yieldOp && callOp && callOp.getNumOperands() == 1 &&
1127 callOp.getArgOperand(0) == ggop) {
1129 return getCalledFunction(callOp);
1136 builder.setInsertionPointAfter(op);
1137 SmallString<256> fnName(
"__cxx_global_array_dtor");
1138 uint32_t cnt = dynamicInitializerNames[fnName]++;
1140 fnName +=
"." + std::to_string(cnt);
1143 auto fnType = cir::FuncType::get({voidPtrTy}, voidTy);
1144 cir::FuncOp dtorFunc =
1145 buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1146 cir::GlobalLinkageKind::InternalLinkage);
1148 SmallVector<mlir::NamedAttribute> paramAttrs;
1149 paramAttrs.push_back(
1150 builder.getNamedAttr(
"llvm.noundef", builder.getUnitAttr()));
1151 SmallVector<mlir::Attribute> argAttrDicts;
1152 argAttrDicts.push_back(
1153 mlir::DictionaryAttr::get(builder.getContext(), paramAttrs));
1154 dtorFunc.setArgAttrsAttr(
1155 mlir::ArrayAttr::get(builder.getContext(), argAttrDicts));
1157 mlir::Block *entryBB = dtorFunc.addEntryBlock();
1160 entryBB->getOperations().splice(entryBB->begin(), dtorBlock.getOperations(),
1161 dtorBlock.begin(), dtorBlock.end());
1164 cir::GetGlobalOp dtorGGop =
1165 mlir::cast<cir::GetGlobalOp>(entryBB->getOperations().front());
1166 builder.setInsertionPointToStart(&dtorBlock);
1167 builder.clone(*dtorGGop.getOperation());
1171 mlir::Value dtorArg = entryBB->getArgument(0);
1172 dtorGGop.replaceAllUsesWith(dtorArg);
1176 mlir::Block &finalBlock = dtorFunc.getBody().back();
1177 auto yieldOp = cast<cir::YieldOp>(finalBlock.getTerminator());
1178 builder.setInsertionPoint(yieldOp);
1179 cir::ReturnOp::create(builder, yieldOp->getLoc());
1184 cir::GetGlobalOp origGGop =
1185 mlir::cast<cir::GetGlobalOp>(dtorBlock.getOperations().front());
1186 builder.setInsertionPointAfter(origGGop);
1187 mlir::Value ggopResult = origGGop.getResult();
1188 dtorCall = builder.
createCallOp(op.getLoc(), dtorFunc, ggopResult);
1191 auto finalYield = cir::YieldOp::create(builder, op.getLoc());
1194 dtorBlock.getOperations().erase(std::next(mlir::Block::iterator(finalYield)),
1196 dtorRegion.getBlocks().erase(std::next(dtorRegion.begin()), dtorRegion.end());
1202LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op) {
1205 SmallString<256> fnName(
"__cxx_global_var_init");
1207 uint32_t cnt = dynamicInitializerNames[fnName]++;
1209 fnName +=
"." + std::to_string(cnt);
1212 CIRBaseBuilderTy builder(getContext());
1213 builder.setInsertionPointAfter(op);
1214 cir::VoidType voidTy = builder.
getVoidTy();
1215 auto fnType = cir::FuncType::get({}, voidTy);
1216 FuncOp f = buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
1217 cir::GlobalLinkageKind::InternalLinkage);
1222 if (op.getStrictfp()) {
1223 f->setAttr(cir::CIRDialect::getStrictFPAttrName(),
1224 mlir::UnitAttr::get(&getContext()));
1225 op.setStrictfp(
false);
1234 mlir::Block *entryBB = f.addEntryBlock();
1235 builder.setInsertionPointToStart(entryBB);
1239 bool needsTlsGuard = op.getTlsRefs() && op.getTlsRefs()->getGuardName();
1241 if (needsTlsGuard) {
1242 guardIf = buildGlobalTlsGuardCheck(
1243 builder, op.getLoc(),
1244 getOrCreateStaticLocalDeclGuardAddress(
1245 builder, op, op.getTlsRefs()->getGuardName().getValue(),
1247 op.hasInternalLinkage()));
1248 builder.setInsertionPointToEnd(&guardIf.getThenRegion().front());
1251 if (!op.getCtorRegion().empty()) {
1252 mlir::Block &block = op.getCtorRegion().front();
1253 mlir::Block *insertBlock = builder.getBlock();
1254 insertBlock->getOperations().splice(insertBlock->end(),
1255 block.getOperations(), block.begin(),
1256 std::prev(block.end()));
1260 mlir::Region &dtorRegion = op.getDtorRegion();
1261 if (!dtorRegion.empty()) {
1264 emitGlobalGuardedDtorRegion(builder, op, dtorRegion,
1265 op.getTlsModel().has_value(),
1266 *builder.getBlock());
1270 if (needsTlsGuard) {
1271 builder.setInsertionPointToEnd(&guardIf.getThenRegion().back());
1272 cir::YieldOp::create(builder, op.getLoc());
1276 builder.setInsertionPointToEnd(entryBB);
1277 mlir::Operation *yieldOp =
nullptr;
1278 if (!op.getCtorRegion().empty()) {
1279 mlir::Block &block = op.getCtorRegion().front();
1280 yieldOp = &block.getOperations().back();
1282 assert(!dtorRegion.empty());
1283 mlir::Block &block = dtorRegion.front();
1284 yieldOp = &block.getOperations().back();
1287 assert(isa<cir::YieldOp>(*yieldOp));
1288 cir::ReturnOp::create(builder, yieldOp->getLoc());
1293LoweringPreparePass::getGuardAcquireFn(cir::PointerType guardPtrTy) {
1295 CIRBaseBuilderTy builder(getContext());
1296 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1297 builder.setInsertionPointToStart(mlirModule.getBody());
1298 mlir::Location loc = mlirModule.getLoc();
1299 cir::IntType intTy = cir::IntType::get(&getContext(), 32,
true);
1300 auto fnType = cir::FuncType::get({guardPtrTy}, intTy);
1301 return buildRuntimeFunction(builder,
"__cxa_guard_acquire", loc, fnType);
1305LoweringPreparePass::getGuardReleaseFn(cir::PointerType guardPtrTy) {
1307 CIRBaseBuilderTy builder(getContext());
1308 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1309 builder.setInsertionPointToStart(mlirModule.getBody());
1310 mlir::Location loc = mlirModule.getLoc();
1311 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1312 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1313 return buildRuntimeFunction(builder,
"__cxa_guard_release", loc, fnType);
1316cir::FuncOp LoweringPreparePass::getGuardAbortFn(cir::PointerType guardPtrTy) {
1318 CIRBaseBuilderTy builder(getContext());
1319 mlir::OpBuilder::InsertionGuard ipGuard{builder};
1320 builder.setInsertionPointToStart(mlirModule.getBody());
1321 mlir::Location loc = mlirModule.getLoc();
1322 cir::VoidType voidTy = cir::VoidType::get(&getContext());
1323 auto fnType = cir::FuncType::get({guardPtrTy}, voidTy);
1324 return buildRuntimeFunction(builder,
"__cxa_guard_abort", loc, fnType);
1327cir::FuncOp LoweringPreparePass::getTlsInitFn() {
1329 CIRBaseBuilderTy builder(getContext());
1330 mlir::OpBuilder::InsertionGuard _{builder};
1331 builder.setInsertionPointToStart(mlirModule.getBody());
1332 mlir::Location loc = mlirModule.getLoc();
1334 return buildRuntimeFunction(builder,
"__tls_init", loc, fnType,
1335 cir::GlobalLinkageKind::InternalLinkage);
1338cir::GlobalOp LoweringPreparePass::createGuardGlobalOp(
1339 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef name,
1340 cir::IntType guardTy, cir::GlobalLinkageKind linkage) {
1341 mlir::OpBuilder::InsertionGuard guard(builder);
1342 builder.setInsertionPointToStart(mlirModule.getBody());
1343 cir::GlobalOp g = cir::GlobalOp::create(builder, loc, name, guardTy);
1345 cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1346 mlir::SymbolTable::setSymbolVisibility(
1347 g, mlir::SymbolTable::Visibility::Private);
1351void LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
1352 cir::LocalInitOp localInitOp) {
1353 CIRBaseBuilderTy builder(getContext());
1357 std::optional<cir::StaticLocalInfoAttr> infoOption =
1358 globalOp.getStaticLocalInfo();
1359 assert(infoOption.has_value());
1360 cir::StaticLocalInfoAttr
info = infoOption.value();
1362 builder.setInsertionPointAfter(localInitOp);
1363 mlir::Block *localInitBlock = builder.getInsertionBlock();
1366 mlir::Operation *ret = localInitBlock->getTerminator();
1370 builder.setInsertionPointAfter(localInitOp);
1374 cir::TemplateSpecializationKind tsk =
info.getTsk();
1376 tsk == cir::TemplateSpecializationKind::ImplicitInstantiation ||
1378 cir::TemplateSpecializationKind::ExplicitInstantiationDeclaration ||
1379 tsk == cir::TemplateSpecializationKind::ExplicitInstantiationDefinition;
1384 if (nonTemplateInline) {
1385 globalOp->emitError(
1386 "NYI: guarded initialization for inline namespace-scope variables");
1393 bool threadsafe = astCtx->
getLangOpts().ThreadsafeStatics &&
1394 (
info.getLocal() || nonTemplateInline) &&
1395 info.getTls() == cir::TLSKind::None;
1399 bool useInt8GuardVariable = !threadsafe && globalOp.hasInternalLinkage();
1402 cir::GlobalOp guard = getOrCreateStaticLocalDeclGuardAddress(
1403 builder, globalOp, globalOp.getStaticLocalGuard()->getName().getValue(),
1404 info.getLocal(), useInt8GuardVariable);
1407 localInitBlock->push_back(ret);
1411 mlir::Value guardPtr = builder.
createGetGlobal(guard, localInitOp.getTls());
1433 unsigned maxInlineWidthInBits =
1436 if (!threadsafe || maxInlineWidthInBits) {
1438 auto bytePtrTy = cir::PointerType::get(builder.
getSIntNTy(8));
1439 mlir::Value bytePtr = builder.
createBitcast(guardPtr, bytePtrTy);
1441 localInitOp.getLoc(), bytePtr, *guard.getAlignment());
1450 auto loadOp = mlir::cast<cir::LoadOp>(guardLoad.getDefiningOp());
1451 loadOp.setMemOrder(cir::MemOrder::Acquire);
1452 loadOp.setSyncScope(cir::SyncScopeKind::System);
1475 if (useARMGuardVarABI() && !useInt8GuardVariable) {
1477 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()),
1479 guardLoad = builder.
createAnd(localInitOp.getLoc(), guardLoad, one);
1484 localInitOp.getLoc(), mlir::cast<cir::IntType>(guardLoad.getType()), 0);
1485 auto needsInit = builder.
createCompare(localInitOp.getLoc(),
1486 cir::CmpOpKind::eq, guardLoad, zero);
1490 builder, globalOp.getLoc(), needsInit,
1491 false, [&](mlir::OpBuilder &, mlir::Location) {
1492 emitCXXGuardedInitIf(
1493 builder, globalOp, localInitOp.getCtorRegion(),
1494 localInitOp.getDtorRegion(), info.getLocal(), guardPtr,
1495 builder.getPointerTo(guard.getSymType()), threadsafe);
1500 globalOp->emitError(
"NYI: guarded init without inline atomics support");
1505 builder.getInsertionBlock()->push_back(ret);
1508void LoweringPreparePass::lowerLocalInitOp(cir::LocalInitOp initOp) {
1511 if (initOp.getCtorRegion().empty() && initOp.getDtorRegion().empty()) {
1516 cir::GlobalOp globalOp = initOp.getReferencedGlobal(symbolTables);
1517 assert(globalOp &&
"No global-op found");
1519 handleStaticLocal(globalOp, initOp);
1532static cir::GlobalLinkageKind
1535 return op.getLinkage();
1540 return op.getLinkage();
1544 if (op.isDeclaration())
1545 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1546 return cir::GlobalLinkageKind::WeakODRLinkage;
1550LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder,
1552 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1553 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1555 mlir::StringAttr wrapperName = op.getTlsRefs()->getWrapperName();
1557 auto existingWrapperIter = threadLocalWrappers.find(wrapperName.getValue());
1558 if (existingWrapperIter != threadLocalWrappers.end())
1559 return existingWrapperIter->second;
1562 auto funcType = cir::FuncType::get({}, builder.
getPointerTo(op.getSymType()));
1564 cir::FuncOp::create(builder, op.getLoc(), wrapperName, funcType);
1566 cir::GlobalLinkageKind linkageKind =
1568 func.setLinkageAttr(
1569 cir::GlobalLinkageKindAttr::get(&getContext(), linkageKind));
1574 func.isWeakForLinker())
1575 func.setComdat(
true);
1577 mlir::SymbolTable::setSymbolVisibility(
1578 func, mlir::SymbolTable::Visibility::Private);
1583 op.getGlobalVisibility() == cir::VisibilityKind::Hidden)
1584 func.setGlobalVisibility(cir::VisibilityKind::Hidden);
1587 op->emitError(
"Unhandled thread wrapper attributes for CC and Nounwind");
1589 threadLocalWrappers.insert({wrapperName.getValue(), func});
1593void LoweringPreparePass::defineGlobalThreadLocalWrapper(cir::GlobalOp op,
1594 cir::FuncOp initAlias,
1595 bool isVarDefinition) {
1596 CIRBaseBuilderTy builder(getContext());
1597 cir::FuncOp wrapper = getOrCreateThreadLocalWrapper(builder, op);
1598 mlir::Block *entryBB = wrapper.addEntryBlock();
1599 builder.setInsertionPointToStart(entryBB);
1603 mlir::Location aliasLoc = initAlias.getLoc();
1604 if (!isVarDefinition) {
1606 mlir::Value funcLoad = cir::GetGlobalOp::create(
1607 builder, aliasLoc, cir::PointerType::get(initAlias.getFunctionType()),
1608 initAlias.getSymName());
1609 mlir::Value nullCheck =
1611 mlir::Value cmp = cir::CmpOp::create(
1612 builder, aliasLoc, cir::CmpOpKind::ne, funcLoad, nullCheck);
1613 cir::IfOp::create(builder, aliasLoc, cmp,
false,
1614 [&](mlir::OpBuilder &, mlir::Location loc) {
1616 cir::YieldOp::create(builder, aliasLoc);
1625 cir::ReturnOp::create(builder, op.getLoc(), {get});
1629LoweringPreparePass::defineGlobalThreadLocalInitAlias(cir::GlobalOp op,
1630 cir::FuncOp aliasee) {
1631 CIRBaseBuilderTy builder(getContext());
1632 mlir::OpBuilder::InsertionGuard insertGuard(builder);
1633 builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
1634 mlir::StringAttr aliasName = op.getTlsRefs()->getInitName();
1635 auto existingAliasIter = threadLocalInitAliases.find(aliasName.getValue());
1637 if (existingAliasIter != threadLocalInitAliases.end())
1638 return existingAliasIter->second;
1642 cir::FuncOp::create(builder, op.getLoc(), aliasName, funcType);
1643 alias.setLinkage(op.getLinkage());
1646 alias.setAliasee(aliasee.getSymName());
1651 alias.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1652 mlir::SymbolTable::setSymbolVisibility(
1653 alias, mlir::SymbolTable::Visibility::Private);
1656 threadLocalInitAliases.insert({aliasName.getValue(), alias});
1660void LoweringPreparePass::lowerGlobalOp(GlobalOp op) {
1662 if (op.getStaticLocalGuard())
1665 mlir::Region &ctorRegion = op.getCtorRegion();
1666 mlir::Region &dtorRegion = op.getDtorRegion();
1667 cir::FuncOp initAlias;
1669 if (!ctorRegion.empty() || !dtorRegion.empty()) {
1672 cir::FuncOp f = buildCXXGlobalVarDeclInitFunc(op);
1675 ctorRegion.getBlocks().clear();
1676 dtorRegion.getBlocks().clear();
1679 if (op.getTlsModel() && !op.getStaticLocalGuard().has_value()) {
1691 if (op.getTlsRefs()->getGuardName()) {
1693 initAlias = defineGlobalThreadLocalInitAlias(op, f);
1696 initAlias = defineGlobalThreadLocalInitAlias(op, getTlsInitFn());
1700 globalThreadLocalInitializers.push_back(f);
1702 }
else if (std::optional<uint32_t> priority = op.getInitPriority()) {
1703 prioritizedDynamicInitializers[*priority].push_back(f);
1705 dynamicInitializers.push_back(f);
1707 }
else if (op.getTlsModel() && op.getTlsRefs() && op.isDeclaration()) {
1710 initAlias = defineGlobalThreadLocalInitAlias(op, {});
1716 if (op.getTlsModel() && op.getTlsRefs())
1717 defineGlobalThreadLocalWrapper(op, initAlias, !op.isDeclaration());
1722void LoweringPreparePass::lowerGetGlobalOp(GetGlobalOp op) {
1725 auto globalOp = mlir::cast<cir::GlobalOp>(
1726 symbolTables.lookupNearestSymbolFrom(op, op.getNameAttr()));
1732 if (!globalOp.getTlsModel() || !globalOp.getTlsRefs())
1750 mlir::Operation *parentOp = op->getParentOp();
1751 if (parentOp == globalOp) {
1752 mlir::Region *ctorRegion = &globalOp.getCtorRegion();
1753 mlir::Region *dtorRegion = &globalOp.getDtorRegion();
1755 if (!ctorRegion->empty() && &*ctorRegion->op_begin() == op.getOperation())
1757 if (!dtorRegion->empty() && &*dtorRegion->op_begin() == op.getOperation())
1761 CIRBaseBuilderTy builder(getContext());
1762 cir::FuncOp wrapperFunc = getOrCreateThreadLocalWrapper(builder, globalOp);
1764 builder.setInsertionPoint(op);
1766 wrapperFunc.getLoc(),
1767 mlir::FlatSymbolRefAttr::get(wrapperFunc.getSymNameAttr()),
1768 wrapperFunc.getFunctionType().getReturnType(), {});
1769 op->replaceAllUsesWith(call);
1773void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
1774 CIRBaseBuilderTy builder(getContext());
1775 builder.setInsertionPointAfter(op);
1777 mlir::Location loc = op->getLoc();
1778 cir::CmpThreeWayInfoAttr cmpInfo = op.getInfo();
1787 mlir::Value transformedResult;
1788 if (cmpInfo.getOrdering() != CmpOrdering::Partial) {
1791 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1792 mlir::Value selectOnLt = builder.
createSelect(loc, lt, ltRes, gtRes);
1794 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1795 transformedResult = builder.
createSelect(loc, eq, eqRes, selectOnLt);
1799 loc, op.getType(), cmpInfo.getUnordered().value());
1802 builder.
createCompare(loc, CmpOpKind::eq, op.getLhs(), op.getRhs());
1803 mlir::Value selectOnEq = builder.
createSelect(loc, eq, eqRes, unorderedRes);
1805 builder.
createCompare(loc, CmpOpKind::gt, op.getLhs(), op.getRhs());
1806 mlir::Value selectOnGt = builder.
createSelect(loc, gt, gtRes, selectOnEq);
1808 builder.
createCompare(loc, CmpOpKind::lt, op.getLhs(), op.getRhs());
1809 transformedResult = builder.
createSelect(loc, lt, ltRes, selectOnGt);
1812 op.replaceAllUsesWith(transformedResult);
1816template <
typename AttributeTy>
1817static llvm::SmallVector<mlir::Attribute>
1821 for (
const auto &[name, priority] : list)
1822 attrs.push_back(AttributeTy::get(context, name, priority));
1826void LoweringPreparePass::buildGlobalCtorDtorList() {
1827 if (!globalCtorList.empty()) {
1828 llvm::SmallVector<mlir::Attribute> globalCtors =
1832 mlirModule->setAttr(cir::CIRDialect::getGlobalCtorsAttrName(),
1833 mlir::ArrayAttr::get(&getContext(), globalCtors));
1836 if (!globalDtorList.empty()) {
1837 llvm::SmallVector<mlir::Attribute> globalDtors =
1840 mlirModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(),
1841 mlir::ArrayAttr::get(&getContext(), globalDtors));
1846LoweringPreparePass::createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder,
1847 mlir::Location loc) {
1848 mlir::OpBuilder::InsertionGuard guard(builder);
1849 builder.setInsertionPointToStart(mlirModule.getBody());
1852 cir::IntType guardTy = builder.
getSIntNTy(8);
1853 auto g = cir::GlobalOp::create(builder, loc,
"__tls_guard", guardTy);
1854 g.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
1855 builder.getContext(), cir::GlobalLinkageKind::InternalLinkage));
1858 if (
auto defTlsModel = mlirModule->getAttrOfType<TLSModelAttr>(
1859 cir::CIRDialect::getDefaultTlsModelAttrName())) {
1860 g.setTlsModel(defTlsModel.getValue());
1863 g.setTlsModel(TLSModel::GeneralDynamic);
1866 g.setInitialValueAttr(cir::IntAttr::get(guardTy, 0));
1870cir::IfOp LoweringPreparePass::buildGlobalTlsGuardCheck(
1871 CIRBaseBuilderTy &builder, mlir::Location loc, cir::GlobalOp guard) {
1873 mlir::Value getGuardValue = getGuard;
1878 if (guard.getSymType() != builder.
getSIntNTy(8))
1880 getGuard, cir::PointerType::get(builder.
getSIntNTy(8)));
1882 mlir::Value guardLoad =
1886 builder.
createCompare(loc, cir::CmpOpKind::eq, guardLoad, zero);
1887 return cir::IfOp::create(
1889 false, [&](mlir::OpBuilder &, mlir::Location loc) {
1893 loc, builder.
getConstantInt(loc, guard.getSymType(), 1), getGuard);
1897void LoweringPreparePass::buildCXXGlobalTlsFunc() {
1898 if (globalThreadLocalInitializers.empty())
1904 cir::FuncOp tlsInit = getTlsInitFn();
1905 mlir::Location loc = tlsInit.getLoc();
1906 CIRBaseBuilderTy builder(getContext());
1907 mlir::Block *entryBB = tlsInit.addEntryBlock();
1908 builder.setInsertionPointToStart(entryBB);
1910 cir::IfOp ifOperation = buildGlobalTlsGuardCheck(
1911 builder, loc, createGlobalThreadLocalGuard(builder, loc));
1914 builder.setInsertionPointToEnd(&ifOperation.getThenRegion().front());
1915 for (cir::FuncOp initFunc : globalThreadLocalInitializers)
1917 cir::YieldOp::create(builder, loc);
1919 builder.setInsertionPointAfter(ifOperation);
1920 cir::ReturnOp::create(builder, loc);
1927 assert(priority <= 65535 &&
"Priority should always be <= 65535.");
1928 std::string prioritySuffix = llvm::utostr(priority);
1929 assert(prioritySuffix.size() < 6);
1930 prioritySuffix = std::string(6 - prioritySuffix.size(),
'0') + prioritySuffix;
1931 return prioritySuffix;
1934cir::FuncOp LoweringPreparePass::buildGlobalInitCallerFunc(
1935 llvm::StringRef fnName, cir::GlobalLinkageKind linkage,
1936 llvm::ArrayRef<cir::FuncOp> initializers,
uint32_t priority) {
1937 CIRBaseBuilderTy builder(getContext());
1938 builder.setInsertionPointToEnd(&mlirModule.getBodyRegion().back());
1939 auto fnType = cir::FuncType::get({}, builder.
getVoidTy());
1940 cir::FuncOp fn = buildRuntimeFunction(builder, fnName, mlirModule.getLoc(),
1942 builder.setInsertionPointToStart(fn.addEntryBlock());
1943 for (cir::FuncOp init : initializers)
1945 cir::ReturnOp::create(builder, fn.getLoc());
1946 globalCtorList.emplace_back(fnName, priority);
1950void LoweringPreparePass::buildCXXGlobalPriorityInitFuncs() {
1954 for (
const auto &[priority, initializers] : prioritizedDynamicInitializers) {
1955 SmallString<256> fnName;
1956 fnName +=
"_GLOBAL__I_";
1959 buildGlobalInitCallerFunc(fnName, cir::GlobalLinkageKind::InternalLinkage,
1960 initializers, priority);
1964void LoweringPreparePass::buildCXXGlobalInitFunc() {
1965 buildCXXGlobalPriorityInitFuncs();
1967 if (dynamicInitializers.empty())
1970 SmallString<256> fnName;
1971 cir::GlobalLinkageKind linkage;
1980 if (
auto fnNameAttr = mlirModule->getAttrOfType<mlir::StringAttr>(
1981 cir::CIRDialect::getCXXModuleInitFnNameAttrName())) {
1982 fnName += fnNameAttr.getValue();
1983 linkage = cir::GlobalLinkageKind::ExternalLinkage;
1986 llvm::raw_svector_ostream
out(fnName);
1987 std::unique_ptr<clang::MangleContext> mangleCtx(
1989 cast<clang::ItaniumMangleContext>(*mangleCtx)
1991 linkage = cir::GlobalLinkageKind::ExternalLinkage;
1993 fnName +=
"_GLOBAL__sub_I_";
1995 linkage = cir::GlobalLinkageKind::InternalLinkage;
1998 buildGlobalInitCallerFunc(fnName, linkage, dynamicInitializers,
1999 cir::GlobalCtorAttr::getDefaultPriority());
2008 mlir::Operation *op, mlir::Type eltTy,
2010 mlir::Value numElements,
2011 uint64_t arrayLen,
bool isCtor) {
2012 mlir::Location loc = op->getLoc();
2013 bool isDynamic = numElements !=
nullptr;
2017 const unsigned sizeTypeSize =
2023 mlir::Value begin, end;
2026 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, numElements);
2028 mlir::Value endOffsetVal =
2030 begin = cir::CastOp::create(builder, loc, eltTy,
2031 cir::CastKind::array_to_ptrdecay, addr);
2032 end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
2035 mlir::Value start = isCtor ? begin : end;
2036 mlir::Value stop = isCtor ? end : begin;
2042 mlir::Value guardCond;
2045 guardCond = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
2051 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, start, stop);
2053 ifOp = cir::IfOp::create(builder, loc, guardCond,
2055 [&](mlir::OpBuilder &, mlir::Location) {});
2056 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
2059 mlir::Value tmpAddr =
2064 mlir::Block *bodyBlock = &op->getRegion(0).front();
2069 auto cloneRegionBodyInto = [&](mlir::Block *srcBlock,
2070 mlir::Value replacement) {
2071 mlir::IRMapping map;
2072 map.map(srcBlock->getArgument(0), replacement);
2073 for (mlir::Operation ®ionOp : *srcBlock) {
2074 if (!mlir::isa<cir::YieldOp>(®ionOp))
2075 builder.clone(regionOp, map);
2079 mlir::Block *partialDtorBlock =
nullptr;
2080 if (
auto arrayCtor = mlir::dyn_cast<cir::ArrayCtor>(op)) {
2081 mlir::Region &partialDtor = arrayCtor.getPartialDtor();
2082 if (!partialDtor.empty())
2083 partialDtorBlock = &partialDtor.front();
2084 }
else if (
auto arrayDtor = mlir::dyn_cast<cir::ArrayDtor>(op)) {
2093 if (arrayDtor.getDtorMayThrow())
2094 partialDtorBlock = bodyBlock;
2097 auto emitCtorDtorLoop = [&]() {
2101 [&](mlir::OpBuilder &b, mlir::Location loc) {
2102 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2103 auto cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
2104 currentElement, stop);
2108 [&](mlir::OpBuilder &b, mlir::Location loc) {
2109 auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2111 cloneRegionBodyInto(bodyBlock, currentElement);
2112 mlir::Value stride = builder.
getUnsignedInt(loc, 1, sizeTypeSize);
2113 auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2114 currentElement, stride);
2117 mlir::Value stride = builder.
getSignedInt(loc, -1, sizeTypeSize);
2118 auto prevElement = cir::PtrStrideOp::create(builder, loc, eltTy,
2119 currentElement, stride);
2121 cloneRegionBodyInto(bodyBlock, prevElement);
2124 cir::YieldOp::create(b, loc);
2128 if (partialDtorBlock) {
2129 cir::CleanupScopeOp::create(
2130 builder, loc, cir::CleanupKind::EH,
2132 [&](mlir::OpBuilder &b, mlir::Location loc) {
2134 cir::YieldOp::create(b, loc);
2137 [&](mlir::OpBuilder &b, mlir::Location loc) {
2138 auto cur = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2140 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, cur, begin);
2142 builder, loc, cmp,
false,
2143 [&](mlir::OpBuilder &b, mlir::Location loc) {
2147 [&](mlir::OpBuilder &b, mlir::Location loc) {
2148 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2149 auto neq = cir::CmpOp::create(
2150 builder, loc, cir::CmpOpKind::ne, el, begin);
2154 [&](mlir::OpBuilder &b, mlir::Location loc) {
2155 auto el = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
2156 mlir::Value negOne =
2158 auto prev = cir::PtrStrideOp::create(builder, loc, eltTy,
2161 cloneRegionBodyInto(partialDtorBlock, prev);
2164 cir::YieldOp::create(builder, loc);
2166 cir::YieldOp::create(b, loc);
2173 cir::YieldOp::create(builder, loc);
2178void LoweringPreparePass::lowerArrayDtor(cir::ArrayDtor op) {
2179 CIRBaseBuilderTy builder(getContext());
2180 builder.setInsertionPointAfter(op.getOperation());
2182 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2184 if (op.getNumElements()) {
2186 op.getNumElements(), 0,
2192 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2198void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
2199 cir::CIRBaseBuilderTy builder(getContext());
2200 builder.setInsertionPointAfter(op.getOperation());
2202 mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
2204 if (op.getNumElements()) {
2206 op.getNumElements(), 0,
2212 mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
2218cir::FuncOp LoweringPreparePass::getCalledFunction(cir::CallOp callOp) {
2219 mlir::SymbolRefAttr sym = llvm::dyn_cast_if_present<mlir::SymbolRefAttr>(
2220 callOp.getCallableForCallee());
2223 return symbolTables.lookupNearestSymbolFrom<cir::FuncOp>(callOp, sym);
2226void LoweringPreparePass::lowerTrivialCopyCall(cir::CallOp op) {
2227 cir::FuncOp funcOp = getCalledFunction(op);
2231 std::optional<cir::CtorKind> ctorKind = funcOp.getCxxConstructorKind();
2232 if (ctorKind && *ctorKind == cir::CtorKind::Copy &&
2233 funcOp.isCxxTrivialMemberFunction()) {
2235 CIRBaseBuilderTy builder(getContext());
2236 mlir::ValueRange operands = op.getOperands();
2237 mlir::Value dest = operands[0];
2238 mlir::Value src = operands[1];
2239 builder.setInsertionPoint(op);
2245cir::GlobalOp LoweringPreparePass::getOrCreateConstAggregateGlobal(
2246 CIRBaseBuilderTy &builder, mlir::Location loc, llvm::StringRef baseName,
2247 mlir::Type ty, mlir::TypedAttr constant, uint64_t alignment) {
2249 llvm::SmallVector<cir::GlobalOp, 1> &versions =
2250 constAggregateGlobals[baseName];
2253 for (cir::GlobalOp gv : versions) {
2254 if (gv.getSymType() == ty && gv.getInitialValue() == constant)
2262 llvm::SmallString<128>
name(baseName);
2263 size_t baseLen =
name.size();
2264 unsigned version = versions.size();
2266 name.resize(baseLen);
2268 name.push_back(
'.');
2269 llvm::Twine(version).toVector(name);
2271 auto existingGv = symbolTables.lookupSymbolIn<cir::GlobalOp>(
2272 mlirModule, mlir::StringAttr::get(&getContext(), name));
2275 versions.push_back(existingGv);
2276 if (existingGv.getSymType() == ty &&
2277 existingGv.getInitialValue() == constant)
2283 mlir::OpBuilder::InsertionGuard guard(builder);
2284 builder.setInsertionPointToStart(mlirModule.getBody());
2286 cir::GlobalOp::create(builder, loc, name, ty,
2288 cir::LangAddressSpaceAttr::get(
2289 &getContext(), cir::LangAddressSpace::Default),
2290 cir::GlobalLinkageKind::PrivateLinkage);
2291 mlir::SymbolTable::setSymbolVisibility(
2292 gv, mlir::SymbolTable::Visibility::Private);
2293 gv.setInitialValueAttr(constant);
2294 gv.setAlignment(alignment);
2298 symbolTables.getSymbolTable(mlirModule).insert(gv);
2300 versions.push_back(gv);
2304void LoweringPreparePass::lowerStoreOfConstAggregate(cir::StoreOp op) {
2306 auto constOp = op.getValue().getDefiningOp<cir::ConstantOp>();
2310 mlir::Type ty = constOp.getType();
2311 if (!mlir::isa<cir::ArrayType, cir::RecordType>(ty))
2317 auto alloca = op.getAddr().getDefiningOp<cir::AllocaOp>();
2321 mlir::TypedAttr constant = constOp.getValue();
2332 auto func = op->getParentOfType<cir::FuncOp>();
2335 llvm::StringRef funcName = func.getSymName();
2338 llvm::StringRef varName = alloca.getName();
2341 std::string baseName = (
"__const." + funcName +
"." + varName).str();
2342 CIRBaseBuilderTy builder(getContext());
2346 cir::GlobalOp gv = getOrCreateConstAggregateGlobal(
2347 builder, op.getLoc(), baseName, ty, constant, alloca.getAlignment());
2350 builder.setInsertionPoint(op);
2352 auto ptrTy = cir::PointerType::get(ty);
2353 mlir::Value globalPtr =
2354 cir::GetGlobalOp::create(builder, op.getLoc(), ptrTy, gv.getSymName());
2363 if (constOp.use_empty())
2370void LoweringPreparePass::lowerStdOp(cir::StdOpInterface typedOp) {
2371 mlir::Operation *op = typedOp.getOperation();
2372 cir::CIRBaseBuilderTy builder(getContext());
2373 builder.setInsertionPointAfter(op);
2374 mlir::Type resultType;
2375 if (op->getNumResults())
2376 resultType = op->getResult(0).getType();
2378 op->getLoc(), typedOp.getOriginalFnAttr(), resultType, op->getOperands());
2379 for (mlir::NamedAttribute attr : op->getAttrs())
2380 if (
attr.getName() != typedOp.getOriginalFnAttrName())
2381 call->setAttr(
attr.getName(),
attr.getValue());
2383 op->replaceAllUsesWith(call);
2387void LoweringPreparePass::runOnOp(mlir::Operation *op) {
2388 if (
auto arrayCtor = dyn_cast<cir::ArrayCtor>(op)) {
2389 lowerArrayCtor(arrayCtor);
2390 }
else if (
auto arrayDtor = dyn_cast<cir::ArrayDtor>(op)) {
2391 lowerArrayDtor(arrayDtor);
2392 }
else if (
auto stdOp = mlir::dyn_cast<cir::StdOpInterface>(op)) {
2394 }
else if (
auto cast = mlir::dyn_cast<cir::CastOp>(op)) {
2396 }
else if (
auto complexConj = mlir::dyn_cast<cir::ComplexConjOp>(op)) {
2397 lowerComplexConjOp(complexConj);
2398 }
else if (
auto complexDiv = mlir::dyn_cast<cir::ComplexDivOp>(op)) {
2399 lowerComplexDivOp(complexDiv);
2400 }
else if (
auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) {
2401 lowerComplexMulOp(complexMul);
2402 }
else if (
auto glob = mlir::dyn_cast<cir::GlobalOp>(op)) {
2403 lowerGlobalOp(glob);
2404 if (
auto regAttr = glob->getAttrOfType<CUDAVarRegistrationInfoAttr>(
2405 CUDAVarRegistrationInfoAttr::getMnemonic()))
2406 cudaDeviceVars.emplace_back(glob, regAttr);
2407 }
else if (
auto getGlob = mlir::dyn_cast<cir::GetGlobalOp>(op)) {
2408 lowerGetGlobalOp(getGlob);
2409 }
else if (
auto callOp = dyn_cast<cir::CallOp>(op)) {
2410 lowerTrivialCopyCall(callOp);
2411 }
else if (
auto storeOp = dyn_cast<cir::StoreOp>(op)) {
2412 lowerStoreOfConstAggregate(storeOp);
2413 }
else if (
auto fnOp = dyn_cast<cir::FuncOp>(op)) {
2414 if (
auto globalCtor = fnOp.getGlobalCtorPriority())
2415 globalCtorList.emplace_back(fnOp.getName(), globalCtor.value());
2416 else if (
auto globalDtor = fnOp.getGlobalDtorPriority())
2417 globalDtorList.emplace_back(fnOp.getName(), globalDtor.value());
2419 if (mlir::Attribute attr =
2420 fnOp->getAttr(cir::CUDAKernelNameAttr::getMnemonic())) {
2421 auto kernelNameAttr = dyn_cast<CUDAKernelNameAttr>(attr);
2422 llvm::StringRef kernelName = kernelNameAttr.getKernelName();
2423 cudaKernelMap[kernelName] = fnOp;
2425 }
else if (
auto threeWayCmp = dyn_cast<cir::CmpThreeWayOp>(op)) {
2426 lowerThreeWayCmpOp(threeWayCmp);
2427 }
else if (
auto initOp = dyn_cast<cir::LocalInitOp>(op)) {
2428 lowerLocalInitOp(initOp);
2439 llvm::StringRef name) {
2440 return (
"__" + prefix + name).str();
2462void LoweringPreparePass::buildCUDAModuleCtor() {
2465 if (astCtx->
getLangOpts().GPURelocatableDeviceCode)
2466 llvm_unreachable(
"GPU RDC NYI");
2470 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2475 mlir::Attribute cudaBinaryHandleAttr =
2476 mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName());
2477 if (!cudaBinaryHandleAttr) {
2483 llvm::StringRef cudaGPUBinaryName =
2484 mlir::cast<CUDABinaryHandleAttr>(cudaBinaryHandleAttr)
2488 llvm::vfs::FileSystem &vfs =
2490 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> gpuBinaryOrErr =
2491 vfs.getBufferForFile(cudaGPUBinaryName);
2492 if (std::error_code ec = gpuBinaryOrErr.getError()) {
2493 mlirModule->emitError(
"cannot open GPU binary file: " + cudaGPUBinaryName +
2494 ": " + ec.message());
2497 std::unique_ptr<llvm::MemoryBuffer> gpuBinary =
2498 std::move(gpuBinaryOrErr.get());
2502 mlir::Location loc = mlirModule->getLoc();
2503 CIRBaseBuilderTy builder(getContext());
2504 builder.setInsertionPointToStart(mlirModule.getBody());
2508 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2510 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2516 llvm::StringRef fatbinConstName =
2517 astCtx->
getLangOpts().HIP ?
".hip_fatbin" :
".nv_fatbin";
2519 llvm::StringRef fatbinSectionName =
2520 astCtx->
getLangOpts().HIP ?
".hipFatBinSegment" :
".nvFatBinSegment";
2524 ArrayType::get(&getContext(), charTy, gpuBinary->getBuffer().size());
2526 GlobalOp fatbinStr = GlobalOp::create(builder, loc, fatbinStrName, fatbinType,
2528 GlobalLinkageKind::PrivateLinkage);
2530 const unsigned HIPCodeObjectAlign = 4096;
2531 fatbinStr.setAlignment(HIPCodeObjectAlign);
2533 fatbinStr.setAlignment(8);
2536 fatbinStr.setInitialValueAttr(cir::ConstArrayAttr::get(
2537 fatbinType, StringAttr::get(gpuBinary->getBuffer(), fatbinType)));
2538 fatbinStr.setSection(fatbinConstName);
2539 fatbinStr.setPrivate();
2543 mlir::Type fatbinWrapperMembers[] = {intTy, intTy, voidPtrTy, voidPtrTy};
2544 auto fatbinWrapperType = cir::StructType::get(
2545 &getContext(), fatbinWrapperMembers,
false,
false,
2547 std::string fatbinWrapperName =
2549 GlobalOp fatbinWrapper = GlobalOp::create(
2550 builder, loc, fatbinWrapperName, fatbinWrapperType,
2551 true, {}, GlobalLinkageKind::PrivateLinkage);
2552 fatbinWrapper.setSection(fatbinSectionName);
2554 constexpr unsigned cudaFatMagic = 0x466243b1;
2555 constexpr unsigned hipFatMagic = 0x48495046;
2556 unsigned fatMagic =
isHIP ? hipFatMagic : cudaFatMagic;
2558 auto magicInit = IntAttr::get(intTy, fatMagic);
2559 auto versionInit = IntAttr::get(intTy, 1);
2560 auto fatbinStrSymbol =
2561 mlir::FlatSymbolRefAttr::get(fatbinStr.getSymNameAttr());
2562 auto fatbinInit = GlobalViewAttr::get(voidPtrTy, fatbinStrSymbol);
2564 fatbinWrapper.setInitialValueAttr(cir::ConstRecordAttr::get(
2566 mlir::ArrayAttr::get(&getContext(),
2567 {magicInit, versionInit, fatbinInit, unusedInit})));
2570 std::string gpubinHandleName =
2573 GlobalOp gpuBinHandle = GlobalOp::create(
2574 builder, loc, gpubinHandleName, voidPtrPtrTy,
2575 false, {}, cir::GlobalLinkageKind::InternalLinkage);
2577 gpuBinHandle.setPrivate();
2582 std::string regFuncName =
2584 FuncType regFuncType = FuncType::get({voidPtrTy}, voidPtrPtrTy);
2585 cir::FuncOp regFunc =
2586 buildRuntimeFunction(builder, regFuncName, loc, regFuncType);
2589 cir::FuncOp moduleCtor = buildRuntimeFunction(
2590 builder, moduleCtorName, loc, FuncType::get({}, voidTy),
2591 GlobalLinkageKind::InternalLinkage);
2593 globalCtorList.emplace_back(moduleCtorName,
2594 cir::GlobalCtorAttr::getDefaultPriority());
2595 builder.setInsertionPointToStart(moduleCtor.addEntryBlock());
2603 mlir::Block *entryBlock = builder.getInsertionBlock();
2604 mlir::Region *parent = entryBlock->getParent();
2605 mlir::Block *ifBlock = builder.createBlock(parent);
2606 mlir::Block *exitBlock = builder.createBlock(parent);
2608 mlir::OpBuilder::InsertionGuard guard(builder);
2609 builder.setInsertionPointToEnd(entryBlock);
2610 mlir::Value handle =
2612 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2613 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2614 mlir::Value isNull =
2615 builder.
createCompare(loc, cir::CmpOpKind::eq, handle, nullPtr);
2616 cir::BrCondOp::create(builder, loc, isNull, ifBlock, exitBlock);
2620 mlir::OpBuilder::InsertionGuard guard(builder);
2621 builder.setInsertionPointToStart(ifBlock);
2623 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2624 cir::CallOp gpuBinaryHandleCall =
2626 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2628 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2629 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2630 cir::BrOp::create(builder, loc, exitBlock);
2635 mlir::OpBuilder::InsertionGuard guard(builder);
2636 builder.setInsertionPointToStart(exitBlock);
2637 mlir::Value gHandle =
2640 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals())
2643 if (std::optional<FuncOp> dtor = buildHIPModuleDtor()) {
2644 cir::CIRBaseBuilderTy globalBuilder(getContext());
2645 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2646 FuncOp atexit = buildRuntimeFunction(
2647 globalBuilder,
"atexit", loc,
2648 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2649 mlir::Value dtorFunc = GetGlobalOp::create(
2650 builder, loc, PointerType::get(dtor->getFunctionType()),
2651 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2654 cir::ReturnOp::create(builder, loc);
2658 if (!astCtx->
getLangOpts().GPURelocatableDeviceCode) {
2666 mlir::Value fatbinVoidPtr = builder.
createBitcast(wrapper, voidPtrTy);
2667 cir::CallOp gpuBinaryHandleCall =
2669 mlir::Value gpuBinaryHandle = gpuBinaryHandleCall.getResult();
2671 mlir::Value gpuBinaryHandleGlobal = builder.
createGetGlobal(gpuBinHandle);
2672 builder.
createStore(loc, gpuBinaryHandle, gpuBinaryHandleGlobal);
2675 if (std::optional<FuncOp> regGlobal = buildCUDARegisterGlobals()) {
2676 builder.
createCallOp(loc, *regGlobal, gpuBinaryHandle);
2685 cir::CIRBaseBuilderTy globalBuilder(getContext());
2686 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2688 buildRuntimeFunction(globalBuilder,
"__cudaRegisterFatBinaryEnd", loc,
2689 FuncType::get({voidPtrPtrTy}, voidTy));
2693 llvm_unreachable(
"GPU RDC NYI");
2698 if (std::optional<FuncOp> dtor = buildCUDAModuleDtor()) {
2701 cir::CIRBaseBuilderTy globalBuilder(getContext());
2702 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2703 FuncOp atexit = buildRuntimeFunction(
2704 globalBuilder,
"atexit", loc,
2705 FuncType::get(PointerType::get(dtor->getFunctionType()), intTy));
2706 mlir::Value dtorFunc = GetGlobalOp::create(
2707 builder, loc, PointerType::get(dtor->getFunctionType()),
2708 mlir::FlatSymbolRefAttr::get(dtor->getSymNameAttr()));
2711 cir::ReturnOp::create(builder, loc);
2714std::optional<FuncOp> LoweringPreparePass::buildCUDAModuleDtor() {
2715 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2720 VoidType voidTy = VoidType::get(&getContext());
2721 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2723 mlir::Location loc = mlirModule.getLoc();
2725 cir::CIRBaseBuilderTy builder(getContext());
2726 builder.setInsertionPointToStart(mlirModule.getBody());
2729 std::string unregisterFuncName =
2731 FuncOp unregisterFunc = buildRuntimeFunction(
2732 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2741 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2742 GlobalLinkageKind::InternalLinkage);
2744 builder.setInsertionPointToStart(dtor.addEntryBlock());
2750 GlobalOp gpubinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2752 mlir::Value gpubin = builder.
createLoad(loc, gpubinAddress);
2754 ReturnOp::create(builder, loc);
2771std::optional<FuncOp> LoweringPreparePass::buildHIPModuleDtor() {
2772 if (!mlirModule->getAttr(CIRDialect::getCUDABinaryHandleAttrName()))
2777 VoidType voidTy = VoidType::get(&getContext());
2778 PointerType voidPtrPtrTy = PointerType::get(PointerType::get(voidTy));
2780 mlir::Location loc = mlirModule.getLoc();
2782 cir::CIRBaseBuilderTy builder(getContext());
2783 builder.setInsertionPointToStart(mlirModule.getBody());
2786 std::string unregisterFuncName =
2788 FuncOp unregisterFunc = buildRuntimeFunction(
2789 builder, unregisterFuncName, loc, FuncType::get({voidPtrPtrTy}, voidTy));
2793 buildRuntimeFunction(builder, dtorName, loc, FuncType::get({}, voidTy),
2794 GlobalLinkageKind::InternalLinkage);
2797 GlobalOp gpuBinGlobal = cast<GlobalOp>(mlirModule.lookupSymbol(gpubinName));
2799 mlir::Block *entryBlock = dtor.addEntryBlock();
2800 mlir::Block *ifBlock = builder.createBlock(&dtor.getBody());
2801 mlir::Block *exitBlock = builder.createBlock(&dtor.getBody());
2803 mlir::OpBuilder::InsertionGuard guard(builder);
2804 builder.setInsertionPointToEnd(entryBlock);
2805 mlir::Value handle =
2807 auto handlePtrTy = mlir::cast<cir::PointerType>(handle.getType());
2808 mlir::Value nullPtr = builder.
getNullPtr(handlePtrTy, loc);
2809 mlir::Value isNotNull =
2810 builder.
createCompare(loc, cir::CmpOpKind::ne, handle, nullPtr);
2811 cir::BrCondOp::create(builder, loc, isNotNull, ifBlock, exitBlock);
2815 mlir::OpBuilder::InsertionGuard ifGuard(builder);
2816 builder.setInsertionPointToStart(ifBlock);
2819 cir::BrOp::create(builder, loc, exitBlock);
2822 mlir::OpBuilder::InsertionGuard exitGuard(builder);
2823 builder.setInsertionPointToStart(exitBlock);
2824 cir::ReturnOp::create(builder, loc);
2830std::optional<FuncOp> LoweringPreparePass::buildCUDARegisterGlobals() {
2831 if (cudaKernelMap.empty() && cudaDeviceVars.empty())
2834 cir::CIRBaseBuilderTy builder(getContext());
2835 builder.setInsertionPointToStart(mlirModule.getBody());
2837 mlir::Location loc = mlirModule.getLoc();
2840 auto voidTy = VoidType::get(&getContext());
2841 auto voidPtrTy = PointerType::get(voidTy);
2842 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2846 std::string regGlobalFuncName =
2848 auto regGlobalFuncTy = FuncType::get({voidPtrPtrTy}, voidTy);
2849 FuncOp regGlobalFunc =
2850 buildRuntimeFunction(builder, regGlobalFuncName, loc, regGlobalFuncTy,
2851 GlobalLinkageKind::InternalLinkage);
2852 builder.setInsertionPointToStart(regGlobalFunc.addEntryBlock());
2854 buildCUDARegisterGlobalFunctions(builder, regGlobalFunc);
2855 buildCUDARegisterVars(builder, regGlobalFunc);
2857 ReturnOp::create(builder, loc);
2858 return regGlobalFunc;
2861void LoweringPreparePass::buildCUDARegisterGlobalFunctions(
2862 cir::CIRBaseBuilderTy &builder, FuncOp regGlobalFunc) {
2863 mlir::Location loc = mlirModule.getLoc();
2865 cir::CIRDataLayout dataLayout(mlirModule);
2867 auto voidTy = VoidType::get(&getContext());
2868 auto voidPtrTy = PointerType::get(voidTy);
2869 auto voidPtrPtrTy = PointerType::get(voidPtrTy);
2871 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2875 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2877 cir::CIRBaseBuilderTy globalBuilder(getContext());
2878 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2892 FuncOp cudaRegisterFunction = buildRuntimeFunction(
2894 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2895 voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy},
2898 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2899 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2900 auto tmpString = cir::GlobalOp::create(
2901 globalBuilder, loc, (
".str" + str).str(), strType,
2903 cir::GlobalLinkageKind::PrivateLinkage);
2906 tmpString.setInitialValueAttr(
2907 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2908 tmpString.setPrivate();
2912 cir::ConstantOp cirNullPtr = builder.
getNullPtr(voidPtrTy, loc);
2914 for (
auto kernelName : cudaKernelMap.keys()) {
2915 FuncOp deviceStub = cudaKernelMap[kernelName];
2916 GlobalOp deviceFuncStr = makeConstantString(kernelName);
2920 mlir::Value hostFunc;
2927 auto funcHandle = cast<GlobalOp>(mlirModule.lookupSymbol(kernelName));
2932 GetGlobalOp::create(
2933 builder, loc, PointerType::get(deviceStub.getFunctionType()),
2934 mlir::FlatSymbolRefAttr::get(deviceStub.getSymNameAttr())),
2938 loc, cudaRegisterFunction,
2939 {fatbinHandle, hostFunc, deviceFunc, deviceFunc,
2940 ConstantOp::create(builder, loc, IntAttr::get(intTy, -1)), cirNullPtr,
2941 cirNullPtr, cirNullPtr, cirNullPtr, cirNullPtr});
2948void LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
2949 FuncOp regGlobalFunc) {
2950 mlir::Location loc = mlirModule.getLoc();
2952 cir::CIRDataLayout dataLayout(mlirModule);
2955 PointerType voidPtrPtrTy = builder.
getPointerTo(voidPtrTy);
2959 IntType charTy = cir::IntType::get(&getContext(), astCtx->
getCharWidth(),
2962 if (cudaDeviceVars.empty())
2965 cir::CIRBaseBuilderTy globalBuilder(getContext());
2966 globalBuilder.setInsertionPointToStart(mlirModule.getBody());
2973 cir::VoidType voidTy = builder.
getVoidTy();
2974 FuncOp cudaRegisterVar = buildRuntimeFunction(
2976 FuncType::get({voidPtrPtrTy, voidPtrTy, voidPtrTy, voidPtrTy, intTy,
2977 sizeTy, intTy, intTy},
2980 auto makeConstantString = [&](llvm::StringRef str) -> GlobalOp {
2981 auto strType = ArrayType::get(&getContext(), charTy, 1 + str.size());
2982 auto tmpString = cir::GlobalOp::create(
2983 globalBuilder, loc, (
".str" + str).str(), strType,
2985 cir::GlobalLinkageKind::PrivateLinkage);
2986 tmpString.setInitialValueAttr(
2987 ConstArrayAttr::get(strType, StringAttr::get(str +
"\0", strType)));
2988 tmpString.setPrivate();
2992 mlir::Value fatbinHandle = *regGlobalFunc.args_begin();
2994 for (
auto &[global, regAttr] : cudaDeviceVars) {
2995 switch (regAttr.getKind()) {
2996 case cir::CUDADeviceVarKind::Variable:
2998 case cir::CUDADeviceVarKind::Surface:
2999 llvm_unreachable(
"Surface registration NYI");
3000 case cir::CUDADeviceVarKind::Texture:
3001 llvm_unreachable(
"Texture registration NYI");
3004 if (regAttr.getIsManaged())
3005 llvm_unreachable(
"Managed variable registration NYI");
3007 GlobalOp deviceNameStr = makeConstantString(regAttr.getDeviceSideName());
3010 mlir::Value hostVar =
3013 auto isExtern = ConstantOp::create(
3014 builder, loc, IntAttr::get(intTy, regAttr.getIsExtern() ? 1 : 0));
3015 llvm::TypeSize size = dataLayout.getTypeAllocSize(global.getSymType());
3016 auto varSize = ConstantOp::create(
3017 builder, loc, IntAttr::get(sizeTy, size.getFixedValue()));
3018 auto isConstant = ConstantOp::create(
3019 builder, loc, IntAttr::get(intTy, regAttr.getIsConstant() ? 1 : 0));
3020 auto normalized = ConstantOp::create(builder, loc, IntAttr::get(intTy, 0));
3022 {fatbinHandle, hostVar, deviceName, deviceName,
3023 isExtern, varSize, isConstant, normalized});
3027void LoweringPreparePass::runOnOperation() {
3028 mlir::Operation *op = getOperation();
3029 if (isa<::mlir::ModuleOp>(op))
3030 mlirModule = cast<::mlir::ModuleOp>(op);
3032 llvm::SmallVector<mlir::Operation *> opsToTransform;
3034 op->walk([&](mlir::Operation *op) {
3035 if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
3036 cir::ComplexConjOp, cir::ComplexMulOp, cir::ComplexDivOp,
3037 cir::DynamicCastOp, cir::FuncOp, cir::CallOp,
3038 cir::GetGlobalOp, cir::GlobalOp, cir::StoreOp,
3039 cir::CmpThreeWayOp, cir::LocalInitOp, cir::StdOpInterface>(
3041 opsToTransform.push_back(op);
3044 for (mlir::Operation *o : opsToTransform)
3047 buildCXXGlobalInitFunc();
3048 buildCXXGlobalTlsFunc();
3050 buildCUDAModuleCtor();
3052 buildGlobalCtorDtorList();
3056 return std::make_unique<LoweringPreparePass>();
3059std::unique_ptr<Pass>
3061 auto pass = std::make_unique<LoweringPreparePass>();
3062 pass->setASTContext(astCtx);
3063 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 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 std::string getPrioritySuffix(unsigned priority)
Compute the zero-padded priority suffix used to name priority-specific global init functions,...
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::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()
__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()