65#include "llvm/IR/IntrinsicsAMDGPU.h"
95#define DEBUG_TYPE "irtranslator"
101 cl::desc(
"Should enable CSE in irtranslator"),
119 MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
123 if (!R.getLocation().isValid() || TPC.isGlobalISelAbortEnabled())
124 R << (
" (in function: " + MF.getName() +
")").str();
126 if (TPC.isGlobalISelAbortEnabled())
143 DILocationVerifier() =
default;
144 ~DILocationVerifier() =
default;
146 const Instruction *getCurrentInst()
const {
return CurrInst; }
147 void setCurrentInst(
const Instruction *Inst) { CurrInst = Inst; }
154 assert(getCurrentInst() &&
"Inserted instruction without a current MI");
159 <<
" was copied to " <<
MI);
165 (
MI.getParent()->isEntryBlock() && !
MI.getDebugLoc()) ||
166 (
MI.isDebugInstr())) &&
167 "Line info was not transferred to all instructions");
190IRTranslator::allocateVRegs(
const Value &Val) {
191 auto VRegsIt = VMap.findVRegs(Val);
192 if (VRegsIt != VMap.vregs_end())
193 return *VRegsIt->second;
194 auto *Regs = VMap.getVRegs(Val);
195 auto *Offsets = VMap.getOffsets(Val);
198 Offsets->empty() ? Offsets :
nullptr);
199 for (
unsigned i = 0; i < SplitTys.
size(); ++i)
205 auto VRegsIt = VMap.findVRegs(Val);
206 if (VRegsIt != VMap.vregs_end())
207 return *VRegsIt->second;
210 return *VMap.getVRegs(Val);
213 auto *VRegs = VMap.getVRegs(Val);
214 auto *Offsets = VMap.getOffsets(Val);
218 "Don't know how to create an empty vreg");
222 Offsets->empty() ? Offsets :
nullptr);
224 if (!isa<Constant>(Val)) {
225 for (
auto Ty : SplitTys)
232 auto &
C = cast<Constant>(Val);
234 while (
auto Elt =
C.getAggregateElement(
Idx++)) {
235 auto EltRegs = getOrCreateVRegs(*Elt);
236 llvm::copy(EltRegs, std::back_inserter(*VRegs));
239 assert(SplitTys.size() == 1 &&
"unexpectedly split LLT");
241 bool Success = translate(cast<Constant>(Val), VRegs->front());
246 R <<
"unable to translate constant: " <<
ore::NV(
"Type", Val.
getType());
255int IRTranslator::getOrCreateFrameIndex(
const AllocaInst &AI) {
256 auto MapEntry = FrameIndices.find(&AI);
257 if (MapEntry != FrameIndices.end())
258 return MapEntry->second;
262 ElementSize * cast<ConstantInt>(AI.
getArraySize())->getZExtValue();
265 Size = std::max<uint64_t>(
Size, 1u);
267 int &FI = FrameIndices[&AI];
273 if (
const StoreInst *SI = dyn_cast<StoreInst>(&
I))
274 return SI->getAlign();
275 if (
const LoadInst *LI = dyn_cast<LoadInst>(&
I))
276 return LI->getAlign();
283 R <<
"unable to translate memop: " <<
ore::NV(
"Opcode", &
I);
290 assert(
MBB &&
"BasicBlock was not encountered before");
295 assert(NewPred &&
"new predecessor must be a real MachineBasicBlock");
296 MachinePreds[Edge].push_back(NewPred);
299bool IRTranslator::translateBinaryOp(
unsigned Opcode,
const User &U,
305 Register Op0 = getOrCreateVReg(*
U.getOperand(0));
306 Register Op1 = getOrCreateVReg(*
U.getOperand(1));
309 if (isa<Instruction>(U)) {
318bool IRTranslator::translateUnaryOp(
unsigned Opcode,
const User &U,
320 Register Op0 = getOrCreateVReg(*
U.getOperand(0));
323 if (isa<Instruction>(U)) {
332 return translateUnaryOp(TargetOpcode::G_FNEG, U, MIRBuilder);
335bool IRTranslator::translateCompare(
const User &U,
337 auto *CI = cast<CmpInst>(&U);
338 Register Op0 = getOrCreateVReg(*
U.getOperand(0));
339 Register Op1 = getOrCreateVReg(*
U.getOperand(1));
344 MIRBuilder.
buildICmp(Pred, Res, Op0, Op1, Flags);
352 MIRBuilder.
buildFCmp(Pred, Res, Op0, Op1, Flags);
365 VRegs = getOrCreateVRegs(*Ret);
376 return CLI->
lowerReturn(MIRBuilder, Ret, VRegs, FuncInfo, SwiftErrorVReg);
379void IRTranslator::emitBranchForMergedCondition(
385 if (
const CmpInst *BOp = dyn_cast<CmpInst>(
Cond)) {
388 Condition = InvertCond ? IC->getInversePredicate() : IC->getPredicate();
391 Condition = InvertCond ?
FC->getInversePredicate() :
FC->getPredicate();
395 BOp->getOperand(1),
nullptr,
TBB, FBB, CurBB,
396 CurBuilder->getDebugLoc(), TProb, FProb);
397 SL->SwitchCases.push_back(CB);
405 nullptr,
TBB, FBB, CurBB, CurBuilder->getDebugLoc(), TProb, FProb);
406 SL->SwitchCases.push_back(CB);
411 return I->getParent() == BB;
415void IRTranslator::findMergedConditions(
420 using namespace PatternMatch;
421 assert((Opc == Instruction::And || Opc == Instruction::Or) &&
422 "Expected Opc to be AND/OR");
428 findMergedConditions(NotCond,
TBB, FBB, CurBB, SwitchBB, Opc, TProb, FProb,
434 const Value *BOpOp0, *BOpOp1;
448 if (BOpc == Instruction::And)
449 BOpc = Instruction::Or;
450 else if (BOpc == Instruction::Or)
451 BOpc = Instruction::And;
457 bool BOpIsInOrAndTree = BOpc && BOpc == Opc && BOp->
hasOneUse();
461 emitBranchForMergedCondition(
Cond,
TBB, FBB, CurBB, SwitchBB, TProb, FProb,
472 if (Opc == Instruction::Or) {
493 auto NewTrueProb = TProb / 2;
494 auto NewFalseProb = TProb / 2 + FProb;
496 findMergedConditions(BOpOp0,
TBB, TmpBB, CurBB, SwitchBB, Opc, NewTrueProb,
497 NewFalseProb, InvertCond);
503 findMergedConditions(BOpOp1,
TBB, FBB, TmpBB, SwitchBB, Opc, Probs[0],
504 Probs[1], InvertCond);
506 assert(Opc == Instruction::And &&
"Unknown merge op!");
526 auto NewTrueProb = TProb + FProb / 2;
527 auto NewFalseProb = FProb / 2;
529 findMergedConditions(BOpOp0, TmpBB, FBB, CurBB, SwitchBB, Opc, NewTrueProb,
530 NewFalseProb, InvertCond);
536 findMergedConditions(BOpOp1,
TBB, FBB, TmpBB, SwitchBB, Opc, Probs[0],
537 Probs[1], InvertCond);
541bool IRTranslator::shouldEmitAsBranches(
542 const std::vector<SwitchCG::CaseBlock> &Cases) {
544 if (Cases.size() != 2)
549 if ((Cases[0].CmpLHS == Cases[1].CmpLHS &&
550 Cases[0].CmpRHS == Cases[1].CmpRHS) ||
551 (Cases[0].CmpRHS == Cases[1].CmpLHS &&
552 Cases[0].CmpLHS == Cases[1].CmpRHS)) {
558 if (Cases[0].CmpRHS == Cases[1].CmpRHS &&
559 Cases[0].PredInfo.Pred == Cases[1].PredInfo.Pred &&
560 isa<Constant>(Cases[0].CmpRHS) &&
561 cast<Constant>(Cases[0].CmpRHS)->isNullValue()) {
563 Cases[0].TrueBB == Cases[1].ThisBB)
566 Cases[0].FalseBB == Cases[1].ThisBB)
574 const BranchInst &BrInst = cast<BranchInst>(U);
575 auto &CurMBB = MIRBuilder.
getMBB();
581 !CurMBB.isLayoutSuccessor(Succ0MBB))
586 CurMBB.addSuccessor(&getMBB(*Succ));
612 using namespace PatternMatch;
613 const Instruction *CondI = dyn_cast<Instruction>(CondVal);
615 !BrInst.
hasMetadata(LLVMContext::MD_unpredictable)) {
618 const Value *BOp0, *BOp1;
620 Opcode = Instruction::And;
622 Opcode = Instruction::Or;
626 findMergedConditions(CondI, Succ0MBB, Succ1MBB, &CurMBB, &CurMBB, Opcode,
627 getEdgeProbability(&CurMBB, Succ0MBB),
628 getEdgeProbability(&CurMBB, Succ1MBB),
630 assert(SL->SwitchCases[0].ThisBB == &CurMBB &&
"Unexpected lowering!");
633 if (shouldEmitAsBranches(SL->SwitchCases)) {
635 emitSwitchCase(SL->SwitchCases[0], &CurMBB, *CurBuilder);
636 SL->SwitchCases.erase(SL->SwitchCases.begin());
642 for (
unsigned I = 1, E = SL->SwitchCases.size();
I != E; ++
I)
643 MF->
erase(SL->SwitchCases[
I].ThisBB);
645 SL->SwitchCases.clear();
652 nullptr, Succ0MBB, Succ1MBB, &CurMBB,
653 CurBuilder->getDebugLoc());
657 emitSwitchCase(CB, &CurMBB, *CurBuilder);
665 Src->addSuccessorWithoutProb(Dst);
669 Prob = getEdgeProbability(Src, Dst);
670 Src->addSuccessor(Dst, Prob);
676 const BasicBlock *SrcBB = Src->getBasicBlock();
677 const BasicBlock *DstBB = Dst->getBasicBlock();
681 auto SuccSize = std::max<uint32_t>(
succ_size(SrcBB), 1);
688 using namespace SwitchCG;
693 Clusters.reserve(
SI.getNumCases());
694 for (
const auto &
I :
SI.cases()) {
696 assert(Succ &&
"Could not find successor mbb in mapping");
701 Clusters.push_back(CaseCluster::range(CaseVal, CaseVal, Succ, Prob));
714 if (Clusters.empty()) {
721 SL->findJumpTables(Clusters, &SI, std::nullopt, DefaultMBB,
nullptr,
nullptr);
722 SL->findBitTestClusters(Clusters, &SI);
725 dbgs() <<
"Case clusters: ";
726 for (
const CaseCluster &
C : Clusters) {
727 if (
C.Kind == CC_JumpTable)
729 if (
C.Kind == CC_BitTests)
732 C.Low->getValue().print(
dbgs(),
true);
733 if (
C.Low !=
C.High) {
735 C.High->getValue().print(
dbgs(),
true);
742 assert(!Clusters.empty());
746 auto DefaultProb = getEdgeProbability(SwitchMBB, DefaultMBB);
747 WorkList.push_back({SwitchMBB,
First,
Last,
nullptr,
nullptr, DefaultProb});
749 while (!WorkList.empty()) {
750 SwitchWorkListItem
W = WorkList.pop_back_val();
752 unsigned NumClusters =
W.LastCluster -
W.FirstCluster + 1;
754 if (NumClusters > 3 &&
757 splitWorkItem(WorkList, W,
SI.getCondition(), SwitchMBB, MIB);
761 if (!lowerSwitchWorkItem(W,
SI.getCondition(), SwitchMBB, DefaultMBB, MIB))
771 using namespace SwitchCG;
772 assert(
W.FirstCluster->Low->getValue().slt(
W.LastCluster->Low->getValue()) &&
773 "Clusters not sorted?");
774 assert(
W.LastCluster -
W.FirstCluster + 1 >= 2 &&
"Too small to split!");
776 auto [LastLeft, FirstRight, LeftProb, RightProb] =
777 SL->computeSplitWorkItemInfo(W);
782 assert(PivotCluster >
W.FirstCluster);
783 assert(PivotCluster <=
W.LastCluster);
798 if (FirstLeft == LastLeft && FirstLeft->Kind == CC_Range &&
799 FirstLeft->Low ==
W.GE &&
800 (FirstLeft->High->getValue() + 1LL) == Pivot->
getValue()) {
801 LeftMBB = FirstLeft->MBB;
806 {LeftMBB, FirstLeft, LastLeft,
W.GE, Pivot,
W.DefaultProb / 2});
813 if (FirstRight == LastRight && FirstRight->Kind == CC_Range &&
W.LT &&
814 (FirstRight->High->getValue() + 1ULL) ==
W.LT->getValue()) {
815 RightMBB = FirstRight->MBB;
820 {RightMBB, FirstRight, LastRight, Pivot,
W.LT,
W.DefaultProb / 2});
828 if (
W.MBB == SwitchMBB)
829 emitSwitchCase(CB, SwitchMBB, MIB);
831 SL->SwitchCases.push_back(CB);
837 assert(
JT.Reg &&
"Should lower JT Header first!");
859 Register SwitchOpReg = getOrCreateVReg(SValue);
861 auto Sub = MIB.
buildSub({SwitchTy}, SwitchOpReg, FirstCst);
869 JT.Reg = Sub.getReg(0);
880 auto Cst = getOrCreateVReg(
917 const auto *CI = dyn_cast<ConstantInt>(CB.
CmpRHS);
935 "Can only handle SLE ranges");
941 if (cast<ConstantInt>(CB.
CmpLHS)->isMinValue(
true)) {
947 auto Sub = MIB.
buildSub({CmpTy}, CmpOpReg, CondLHS);
982 bool FallthroughUnreachable) {
983 using namespace SwitchCG;
986 JumpTableHeader *JTH = &SL->JTCases[
I->JTCasesIndex].first;
992 CurMF->
insert(BBI, JumpMBB);
1002 auto JumpProb =
I->Prob;
1003 auto FallthroughProb = UnhandledProbs;
1011 if (*SI == DefaultMBB) {
1012 JumpProb += DefaultProb / 2;
1013 FallthroughProb -= DefaultProb / 2;
1018 addMachineCFGPred({SwitchMBB->
getBasicBlock(), (*SI)->getBasicBlock()},
1023 if (FallthroughUnreachable)
1024 JTH->FallthroughUnreachable =
true;
1026 if (!JTH->FallthroughUnreachable)
1027 addSuccessorWithProb(CurMBB, Fallthrough, FallthroughProb);
1028 addSuccessorWithProb(CurMBB, JumpMBB, JumpProb);
1033 JTH->HeaderBB = CurMBB;
1034 JT->Default = Fallthrough;
1037 if (CurMBB == SwitchMBB) {
1038 if (!emitJumpTableHeader(*JT, *JTH, CurMBB))
1040 JTH->Emitted =
true;
1047 bool FallthroughUnreachable,
1052 using namespace SwitchCG;
1055 if (
I->Low ==
I->High) {
1071 CaseBlock CB(Pred, FallthroughUnreachable, LHS, RHS, MHS,
I->MBB, Fallthrough,
1074 emitSwitchCase(CB, SwitchMBB, MIB);
1084 Register SwitchOpReg = getOrCreateVReg(*
B.SValue);
1088 auto RangeSub = MIB.
buildSub(SwitchOpTy, SwitchOpReg, MinValReg);
1093 LLT MaskTy = SwitchOpTy;
1099 for (
unsigned I = 0, E =
B.Cases.size();
I != E; ++
I) {
1109 if (SwitchOpTy != MaskTy)
1117 if (!
B.FallthroughUnreachable)
1118 addSuccessorWithProb(SwitchBB,
B.Default,
B.DefaultProb);
1119 addSuccessorWithProb(SwitchBB,
MBB,
B.Prob);
1123 if (!
B.FallthroughUnreachable) {
1127 RangeSub, RangeCst);
1147 if (PopCount == 1) {
1150 auto MaskTrailingZeros =
1155 }
else if (PopCount == BB.
Range) {
1157 auto MaskTrailingOnes =
1164 auto SwitchVal = MIB.
buildShl(SwitchTy, CstOne, Reg);
1168 auto AndOp = MIB.
buildAnd(SwitchTy, SwitchVal, CstMask);
1175 addSuccessorWithProb(SwitchBB,
B.TargetBB,
B.ExtraProb);
1177 addSuccessorWithProb(SwitchBB, NextMBB, BranchProbToNext);
1195bool IRTranslator::lowerBitTestWorkItem(
1201 bool FallthroughUnreachable) {
1202 using namespace SwitchCG;
1205 BitTestBlock *BTB = &SL->BitTestCases[
I->BTCasesIndex];
1207 for (BitTestCase &BTC : BTB->Cases)
1208 CurMF->
insert(BBI, BTC.ThisBB);
1211 BTB->Parent = CurMBB;
1212 BTB->Default = Fallthrough;
1214 BTB->DefaultProb = UnhandledProbs;
1218 if (!BTB->ContiguousRange) {
1219 BTB->Prob += DefaultProb / 2;
1220 BTB->DefaultProb -= DefaultProb / 2;
1223 if (FallthroughUnreachable)
1224 BTB->FallthroughUnreachable =
true;
1227 if (CurMBB == SwitchMBB) {
1228 emitBitTestHeader(*BTB, SwitchMBB);
1229 BTB->Emitted =
true;
1239 using namespace SwitchCG;
1243 if (++BBI != FuncInfo.
MF->
end())
1252 [](
const CaseCluster &a,
const CaseCluster &b) {
1253 return a.Prob != b.Prob
1255 : a.Low->getValue().slt(b.Low->getValue());
1260 for (CaseClusterIt
I =
W.LastCluster;
I >
W.FirstCluster;) {
1262 if (
I->Prob >
W.LastCluster->Prob)
1264 if (
I->Kind == CC_Range &&
I->MBB == NextMBB) {
1274 for (CaseClusterIt
I =
W.FirstCluster;
I <=
W.LastCluster; ++
I)
1275 UnhandledProbs +=
I->Prob;
1278 for (CaseClusterIt
I =
W.FirstCluster, E =
W.LastCluster;
I <= E; ++
I) {
1279 bool FallthroughUnreachable =
false;
1281 if (
I ==
W.LastCluster) {
1283 Fallthrough = DefaultMBB;
1284 FallthroughUnreachable = isa<UnreachableInst>(
1288 CurMF->
insert(BBI, Fallthrough);
1290 UnhandledProbs -=
I->Prob;
1294 if (!lowerBitTestWorkItem(W, SwitchMBB, CurMBB, DefaultMBB, MIB, BBI,
1295 DefaultProb, UnhandledProbs,
I, Fallthrough,
1296 FallthroughUnreachable)) {
1304 if (!lowerJumpTableWorkItem(W, SwitchMBB, CurMBB, DefaultMBB, MIB, BBI,
1305 UnhandledProbs,
I, Fallthrough,
1306 FallthroughUnreachable)) {
1313 if (!lowerSwitchRangeWorkItem(
I,
Cond, Fallthrough,
1314 FallthroughUnreachable, UnhandledProbs,
1315 CurMBB, MIB, SwitchMBB)) {
1322 CurMBB = Fallthrough;
1328bool IRTranslator::translateIndirectBr(
const User &U,
1342 if (!AddedSuccessors.
insert(Succ).second)
1351 if (
auto Arg = dyn_cast<Argument>(V))
1352 return Arg->hasSwiftErrorAttr();
1353 if (
auto AI = dyn_cast<AllocaInst>(V))
1359 const LoadInst &LI = cast<LoadInst>(U);
1374 assert(Regs.
size() == 1 &&
"swifterror should be single pointer");
1392 for (
unsigned i = 0; i < Regs.
size(); ++i) {
1397 Align BaseAlign = getMemOpAlign(LI);
1421 assert(Vals.
size() == 1 &&
"swifterror should be single pointer");
1424 SI.getPointerOperand());
1431 for (
unsigned i = 0; i < Vals.
size(); ++i) {
1436 Align BaseAlign = getMemOpAlign(SI);
1440 SI.getSyncScopeID(),
SI.getOrdering());
1447 const Value *Src = U.getOperand(0);
1453 Indices.
push_back(ConstantInt::get(Int32Ty, 0));
1456 for (
auto Idx : EVI->indices())
1458 }
else if (
const InsertValueInst *IVI = dyn_cast<InsertValueInst>(&U)) {
1459 for (
auto Idx : IVI->indices())
1467 DL.getIndexedOffsetInType(Src->getType(), Indices));
1470bool IRTranslator::translateExtractValue(
const User &U,
1472 const Value *Src =
U.getOperand(0);
1477 auto &DstRegs = allocateVRegs(U);
1479 for (
unsigned i = 0; i < DstRegs.size(); ++i)
1480 DstRegs[i] = SrcRegs[
Idx++];
1485bool IRTranslator::translateInsertValue(
const User &U,
1487 const Value *Src =
U.getOperand(0);
1489 auto &DstRegs = allocateVRegs(U);
1493 auto *InsertedIt = InsertedRegs.
begin();
1495 for (
unsigned i = 0; i < DstRegs.size(); ++i) {
1496 if (DstOffsets[i] >=
Offset && InsertedIt != InsertedRegs.
end())
1497 DstRegs[i] = *InsertedIt++;
1499 DstRegs[i] = SrcRegs[i];
1505bool IRTranslator::translateSelect(
const User &U,
1507 Register Tst = getOrCreateVReg(*
U.getOperand(0));
1513 if (
const SelectInst *SI = dyn_cast<SelectInst>(&U))
1516 for (
unsigned i = 0; i < ResRegs.
size(); ++i) {
1517 MIRBuilder.
buildSelect(ResRegs[i], Tst, Op0Regs[i], Op1Regs[i], Flags);
1523bool IRTranslator::translateCopy(
const User &U,
const Value &V,
1526 auto &Regs = *VMap.getVRegs(U);
1528 Regs.push_back(Src);
1529 VMap.getOffsets(U)->push_back(0);
1538bool IRTranslator::translateBitCast(
const User &U,
1545 if (isa<ConstantInt>(
U.getOperand(0)))
1546 return translateCast(TargetOpcode::G_CONSTANT_FOLD_BARRIER, U,
1548 return translateCopy(U, *
U.getOperand(0), MIRBuilder);
1551 return translateCast(TargetOpcode::G_BITCAST, U, MIRBuilder);
1554bool IRTranslator::translateCast(
unsigned Opcode,
const User &U,
1556 if (
U.getType()->getScalarType()->isBFloatTy() ||
1557 U.getOperand(0)->getType()->getScalarType()->isBFloatTy())
1570bool IRTranslator::translateGetElementPtr(
const User &U,
1572 Value &Op0 = *
U.getOperand(0);
1573 Register BaseReg = getOrCreateVReg(Op0);
1585 unsigned VectorWidth = 0;
1589 bool WantSplatVector =
false;
1590 if (
auto *VT = dyn_cast<VectorType>(
U.getType())) {
1591 VectorWidth = cast<FixedVectorType>(VT)->getNumElements();
1593 WantSplatVector = VectorWidth > 1;
1598 if (WantSplatVector && !PtrTy.
isVector()) {
1599 BaseReg = MIRBuilder
1612 const Value *
Idx = GTI.getOperand();
1613 if (
StructType *StTy = GTI.getStructTypeOrNull()) {
1614 unsigned Field = cast<Constant>(
Idx)->getUniqueInteger().getZExtValue();
1618 uint64_t ElementSize = GTI.getSequentialElementStride(*DL);
1622 if (
const auto *CI = dyn_cast<ConstantInt>(
Idx)) {
1623 if (std::optional<int64_t> Val = CI->getValue().trySExtValue()) {
1624 Offset += ElementSize * *Val;
1631 BaseReg = MIRBuilder.
buildPtrAdd(PtrTy, BaseReg, OffsetMIB.getReg(0))
1638 if (IdxTy != OffsetTy) {
1639 if (!IdxTy.
isVector() && WantSplatVector) {
1652 if (ElementSize != 1) {
1658 GepOffsetReg = IdxReg;
1668 if (int64_t(
Offset) >= 0 && cast<GEPOperator>(U).isInBounds())
1671 MIRBuilder.
buildPtrAdd(getOrCreateVReg(U), BaseReg, OffsetMIB.getReg(0),
1676 MIRBuilder.
buildCopy(getOrCreateVReg(U), BaseReg);
1680bool IRTranslator::translateMemFunc(
const CallInst &CI,
1685 if (isa<UndefValue>(SrcPtr))
1690 unsigned MinPtrSize = UINT_MAX;
1691 for (
auto AI = CI.
arg_begin(), AE = CI.
arg_end(); std::next(AI) != AE; ++AI) {
1692 Register SrcReg = getOrCreateVReg(**AI);
1695 MinPtrSize = std::min<unsigned>(SrcTy.
getSizeInBits(), MinPtrSize);
1703 if (MRI->
getType(SizeOpReg) != SizeTy)
1717 if (
auto *MCI = dyn_cast<MemCpyInst>(&CI)) {
1718 DstAlign = MCI->getDestAlign().valueOrOne();
1719 SrcAlign = MCI->getSourceAlign().valueOrOne();
1720 CopySize = dyn_cast<ConstantInt>(MCI->getArgOperand(2));
1721 }
else if (
auto *MCI = dyn_cast<MemCpyInlineInst>(&CI)) {
1722 DstAlign = MCI->getDestAlign().valueOrOne();
1723 SrcAlign = MCI->getSourceAlign().valueOrOne();
1724 CopySize = dyn_cast<ConstantInt>(MCI->getArgOperand(2));
1725 }
else if (
auto *MMI = dyn_cast<MemMoveInst>(&CI)) {
1726 DstAlign = MMI->getDestAlign().valueOrOne();
1727 SrcAlign = MMI->getSourceAlign().valueOrOne();
1728 CopySize = dyn_cast<ConstantInt>(MMI->getArgOperand(2));
1730 auto *MSI = cast<MemSetInst>(&CI);
1731 DstAlign = MSI->getDestAlign().valueOrOne();
1734 if (Opcode != TargetOpcode::G_MEMCPY_INLINE) {
1750 if (AA && CopySize &&
1761 ICall.addMemOperand(
1763 StoreFlags, 1, DstAlign, AAInfo));
1764 if (Opcode != TargetOpcode::G_MEMSET)
1771bool IRTranslator::translateTrap(
const CallInst &CI,
1776 if (TrapFuncName.
empty()) {
1777 if (Opcode == TargetOpcode::G_UBSANTRAP) {
1787 if (Opcode == TargetOpcode::G_UBSANTRAP)
1794 return CLI->
lowerCall(MIRBuilder, Info);
1797bool IRTranslator::translateVectorInterleave2Intrinsic(
1800 "This function can only be called on the interleave2 intrinsic!");
1804 Register Res = getOrCreateVReg(CI);
1813bool IRTranslator::translateVectorDeinterleave2Intrinsic(
1816 "This function can only be called on the deinterleave2 intrinsic!");
1832void IRTranslator::getStackGuard(
Register DstReg,
1837 MIRBuilder.
buildInstr(TargetOpcode::LOAD_STACK_GUARD, {DstReg}, {});
1843 unsigned AddrSpace =
Global->getType()->getPointerAddressSpace();
1851 MIB.setMemRefs({
MemRef});
1854bool IRTranslator::translateOverflowIntrinsic(
const CallInst &CI,
unsigned Op,
1858 Op, {ResRegs[0], ResRegs[1]},
1864bool IRTranslator::translateFixedPointIntrinsic(
unsigned Op,
const CallInst &CI,
1866 Register Dst = getOrCreateVReg(CI);
1870 MIRBuilder.
buildInstr(
Op, {Dst}, { Src0, Src1, Scale });
1878 case Intrinsic::acos:
1879 return TargetOpcode::G_FACOS;
1880 case Intrinsic::asin:
1881 return TargetOpcode::G_FASIN;
1882 case Intrinsic::atan:
1883 return TargetOpcode::G_FATAN;
1884 case Intrinsic::atan2:
1885 return TargetOpcode::G_FATAN2;
1886 case Intrinsic::bswap:
1887 return TargetOpcode::G_BSWAP;
1888 case Intrinsic::bitreverse:
1889 return TargetOpcode::G_BITREVERSE;
1890 case Intrinsic::fshl:
1891 return TargetOpcode::G_FSHL;
1892 case Intrinsic::fshr:
1893 return TargetOpcode::G_FSHR;
1894 case Intrinsic::ceil:
1895 return TargetOpcode::G_FCEIL;
1896 case Intrinsic::cos:
1897 return TargetOpcode::G_FCOS;
1898 case Intrinsic::cosh:
1899 return TargetOpcode::G_FCOSH;
1900 case Intrinsic::ctpop:
1901 return TargetOpcode::G_CTPOP;
1902 case Intrinsic::exp:
1903 return TargetOpcode::G_FEXP;
1904 case Intrinsic::exp2:
1905 return TargetOpcode::G_FEXP2;
1906 case Intrinsic::exp10:
1907 return TargetOpcode::G_FEXP10;
1908 case Intrinsic::fabs:
1909 return TargetOpcode::G_FABS;
1910 case Intrinsic::copysign:
1911 return TargetOpcode::G_FCOPYSIGN;
1912 case Intrinsic::minnum:
1913 return TargetOpcode::G_FMINNUM;
1914 case Intrinsic::maxnum:
1915 return TargetOpcode::G_FMAXNUM;
1916 case Intrinsic::minimum:
1917 return TargetOpcode::G_FMINIMUM;
1918 case Intrinsic::maximum:
1919 return TargetOpcode::G_FMAXIMUM;
1920 case Intrinsic::canonicalize:
1921 return TargetOpcode::G_FCANONICALIZE;
1922 case Intrinsic::floor:
1923 return TargetOpcode::G_FFLOOR;
1924 case Intrinsic::fma:
1925 return TargetOpcode::G_FMA;
1926 case Intrinsic::log:
1927 return TargetOpcode::G_FLOG;
1928 case Intrinsic::log2:
1929 return TargetOpcode::G_FLOG2;
1930 case Intrinsic::log10:
1931 return TargetOpcode::G_FLOG10;
1932 case Intrinsic::ldexp:
1933 return TargetOpcode::G_FLDEXP;
1934 case Intrinsic::nearbyint:
1935 return TargetOpcode::G_FNEARBYINT;
1936 case Intrinsic::pow:
1937 return TargetOpcode::G_FPOW;
1938 case Intrinsic::powi:
1939 return TargetOpcode::G_FPOWI;
1940 case Intrinsic::rint:
1941 return TargetOpcode::G_FRINT;
1942 case Intrinsic::round:
1943 return TargetOpcode::G_INTRINSIC_ROUND;
1944 case Intrinsic::roundeven:
1945 return TargetOpcode::G_INTRINSIC_ROUNDEVEN;
1946 case Intrinsic::sin:
1947 return TargetOpcode::G_FSIN;
1948 case Intrinsic::sinh:
1949 return TargetOpcode::G_FSINH;
1950 case Intrinsic::sqrt:
1951 return TargetOpcode::G_FSQRT;
1952 case Intrinsic::tan:
1953 return TargetOpcode::G_FTAN;
1954 case Intrinsic::tanh:
1955 return TargetOpcode::G_FTANH;
1956 case Intrinsic::trunc:
1957 return TargetOpcode::G_INTRINSIC_TRUNC;
1958 case Intrinsic::readcyclecounter:
1959 return TargetOpcode::G_READCYCLECOUNTER;
1960 case Intrinsic::readsteadycounter:
1961 return TargetOpcode::G_READSTEADYCOUNTER;
1962 case Intrinsic::ptrmask:
1963 return TargetOpcode::G_PTRMASK;
1964 case Intrinsic::lrint:
1965 return TargetOpcode::G_INTRINSIC_LRINT;
1966 case Intrinsic::llrint:
1967 return TargetOpcode::G_INTRINSIC_LLRINT;
1969 case Intrinsic::vector_reduce_fmin:
1970 return TargetOpcode::G_VECREDUCE_FMIN;
1971 case Intrinsic::vector_reduce_fmax:
1972 return TargetOpcode::G_VECREDUCE_FMAX;
1973 case Intrinsic::vector_reduce_fminimum:
1974 return TargetOpcode::G_VECREDUCE_FMINIMUM;
1975 case Intrinsic::vector_reduce_fmaximum:
1976 return TargetOpcode::G_VECREDUCE_FMAXIMUM;
1977 case Intrinsic::vector_reduce_add:
1978 return TargetOpcode::G_VECREDUCE_ADD;
1979 case Intrinsic::vector_reduce_mul:
1980 return TargetOpcode::G_VECREDUCE_MUL;
1981 case Intrinsic::vector_reduce_and:
1982 return TargetOpcode::G_VECREDUCE_AND;
1983 case Intrinsic::vector_reduce_or:
1984 return TargetOpcode::G_VECREDUCE_OR;
1985 case Intrinsic::vector_reduce_xor:
1986 return TargetOpcode::G_VECREDUCE_XOR;
1987 case Intrinsic::vector_reduce_smax:
1988 return TargetOpcode::G_VECREDUCE_SMAX;
1989 case Intrinsic::vector_reduce_smin:
1990 return TargetOpcode::G_VECREDUCE_SMIN;
1991 case Intrinsic::vector_reduce_umax:
1992 return TargetOpcode::G_VECREDUCE_UMAX;
1993 case Intrinsic::vector_reduce_umin:
1994 return TargetOpcode::G_VECREDUCE_UMIN;
1995 case Intrinsic::experimental_vector_compress:
1996 return TargetOpcode::G_VECTOR_COMPRESS;
1997 case Intrinsic::lround:
1998 return TargetOpcode::G_LROUND;
1999 case Intrinsic::llround:
2000 return TargetOpcode::G_LLROUND;
2001 case Intrinsic::get_fpenv:
2002 return TargetOpcode::G_GET_FPENV;
2003 case Intrinsic::get_fpmode:
2004 return TargetOpcode::G_GET_FPMODE;
2009bool IRTranslator::translateSimpleIntrinsic(
const CallInst &CI,
2013 unsigned Op = getSimpleIntrinsicOpcode(
ID);
2021 for (
const auto &Arg : CI.
args())
2024 MIRBuilder.
buildInstr(
Op, {getOrCreateVReg(CI)}, VRegs,
2032 case Intrinsic::experimental_constrained_fadd:
2033 return TargetOpcode::G_STRICT_FADD;
2034 case Intrinsic::experimental_constrained_fsub:
2035 return TargetOpcode::G_STRICT_FSUB;
2036 case Intrinsic::experimental_constrained_fmul:
2037 return TargetOpcode::G_STRICT_FMUL;
2038 case Intrinsic::experimental_constrained_fdiv:
2039 return TargetOpcode::G_STRICT_FDIV;
2040 case Intrinsic::experimental_constrained_frem:
2041 return TargetOpcode::G_STRICT_FREM;
2042 case Intrinsic::experimental_constrained_fma:
2043 return TargetOpcode::G_STRICT_FMA;
2044 case Intrinsic::experimental_constrained_sqrt:
2045 return TargetOpcode::G_STRICT_FSQRT;
2046 case Intrinsic::experimental_constrained_ldexp:
2047 return TargetOpcode::G_STRICT_FLDEXP;
2053bool IRTranslator::translateConstrainedFPIntrinsic(
2073std::optional<MCRegister> IRTranslator::getArgPhysReg(
Argument &Arg) {
2074 auto VRegs = getOrCreateVRegs(Arg);
2075 if (VRegs.
size() != 1)
2076 return std::nullopt;
2080 if (!VRegDef || !VRegDef->isCopy())
2081 return std::nullopt;
2085bool IRTranslator::translateIfEntryValueArgument(
bool isDeclare,
Value *Val,
2090 auto *Arg = dyn_cast<Argument>(Val);
2097 std::optional<MCRegister> PhysReg = getArgPhysReg(*Arg);
2099 LLVM_DEBUG(
dbgs() <<
"Dropping dbg." << (isDeclare ?
"declare" :
"value")
2100 <<
": expression is entry_value but "
2101 <<
"couldn't find a physical register\n");
2121 case Intrinsic::experimental_convergence_anchor:
2122 return TargetOpcode::CONVERGENCECTRL_ANCHOR;
2123 case Intrinsic::experimental_convergence_entry:
2124 return TargetOpcode::CONVERGENCECTRL_ENTRY;
2125 case Intrinsic::experimental_convergence_loop:
2126 return TargetOpcode::CONVERGENCECTRL_LOOP;
2130bool IRTranslator::translateConvergenceControlIntrinsic(
2133 Register OutputReg = getOrCreateConvergenceTokenVReg(CI);
2136 if (
ID == Intrinsic::experimental_convergence_loop) {
2138 assert(Bundle &&
"Expected a convergence control token.");
2140 getOrCreateConvergenceTokenVReg(*Bundle->Inputs[0].get());
2149 if (
auto *
MI = dyn_cast<AnyMemIntrinsic>(&CI)) {
2150 if (ORE->enabled()) {
2160 if (translateSimpleIntrinsic(CI,
ID, MIRBuilder))
2166 case Intrinsic::lifetime_start:
2167 case Intrinsic::lifetime_end: {
2173 unsigned Op =
ID == Intrinsic::lifetime_start ? TargetOpcode::LIFETIME_START
2174 : TargetOpcode::LIFETIME_END;
2183 for (
const Value *V : Allocas) {
2184 const AllocaInst *AI = dyn_cast<AllocaInst>(V);
2195 case Intrinsic::fake_use: {
2197 for (
const auto &Arg : CI.
args())
2198 for (
auto VReg : getOrCreateVRegs(*Arg))
2200 MIRBuilder.
buildInstr(TargetOpcode::FAKE_USE, {}, VRegs);
2204 case Intrinsic::dbg_declare: {
2211 case Intrinsic::dbg_label: {
2217 "Expected inlined-at fields to agree");
2222 case Intrinsic::vaend:
2226 case Intrinsic::vastart: {
2231 MIRBuilder.
buildInstr(TargetOpcode::G_VASTART, {}, {getOrCreateVReg(*
Ptr)})
2234 ListSize, Alignment));
2237 case Intrinsic::dbg_assign:
2244 case Intrinsic::dbg_value: {
2251 case Intrinsic::uadd_with_overflow:
2252 return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDO, MIRBuilder);
2253 case Intrinsic::sadd_with_overflow:
2254 return translateOverflowIntrinsic(CI, TargetOpcode::G_SADDO, MIRBuilder);
2255 case Intrinsic::usub_with_overflow:
2256 return translateOverflowIntrinsic(CI, TargetOpcode::G_USUBO, MIRBuilder);
2257 case Intrinsic::ssub_with_overflow:
2258 return translateOverflowIntrinsic(CI, TargetOpcode::G_SSUBO, MIRBuilder);
2259 case Intrinsic::umul_with_overflow:
2260 return translateOverflowIntrinsic(CI, TargetOpcode::G_UMULO, MIRBuilder);
2261 case Intrinsic::smul_with_overflow:
2262 return translateOverflowIntrinsic(CI, TargetOpcode::G_SMULO, MIRBuilder);
2263 case Intrinsic::uadd_sat:
2264 return translateBinaryOp(TargetOpcode::G_UADDSAT, CI, MIRBuilder);
2265 case Intrinsic::sadd_sat:
2266 return translateBinaryOp(TargetOpcode::G_SADDSAT, CI, MIRBuilder);
2267 case Intrinsic::usub_sat:
2268 return translateBinaryOp(TargetOpcode::G_USUBSAT, CI, MIRBuilder);
2269 case Intrinsic::ssub_sat:
2270 return translateBinaryOp(TargetOpcode::G_SSUBSAT, CI, MIRBuilder);
2271 case Intrinsic::ushl_sat:
2272 return translateBinaryOp(TargetOpcode::G_USHLSAT, CI, MIRBuilder);
2273 case Intrinsic::sshl_sat:
2274 return translateBinaryOp(TargetOpcode::G_SSHLSAT, CI, MIRBuilder);
2275 case Intrinsic::umin:
2276 return translateBinaryOp(TargetOpcode::G_UMIN, CI, MIRBuilder);
2277 case Intrinsic::umax:
2278 return translateBinaryOp(TargetOpcode::G_UMAX, CI, MIRBuilder);
2279 case Intrinsic::smin:
2280 return translateBinaryOp(TargetOpcode::G_SMIN, CI, MIRBuilder);
2281 case Intrinsic::smax:
2282 return translateBinaryOp(TargetOpcode::G_SMAX, CI, MIRBuilder);
2283 case Intrinsic::abs:
2285 return translateUnaryOp(TargetOpcode::G_ABS, CI, MIRBuilder);
2286 case Intrinsic::smul_fix:
2287 return translateFixedPointIntrinsic(TargetOpcode::G_SMULFIX, CI, MIRBuilder);
2288 case Intrinsic::umul_fix:
2289 return translateFixedPointIntrinsic(TargetOpcode::G_UMULFIX, CI, MIRBuilder);
2290 case Intrinsic::smul_fix_sat:
2291 return translateFixedPointIntrinsic(TargetOpcode::G_SMULFIXSAT, CI, MIRBuilder);
2292 case Intrinsic::umul_fix_sat:
2293 return translateFixedPointIntrinsic(TargetOpcode::G_UMULFIXSAT, CI, MIRBuilder);
2294 case Intrinsic::sdiv_fix:
2295 return translateFixedPointIntrinsic(TargetOpcode::G_SDIVFIX, CI, MIRBuilder);
2296 case Intrinsic::udiv_fix:
2297 return translateFixedPointIntrinsic(TargetOpcode::G_UDIVFIX, CI, MIRBuilder);
2298 case Intrinsic::sdiv_fix_sat:
2299 return translateFixedPointIntrinsic(TargetOpcode::G_SDIVFIXSAT, CI, MIRBuilder);
2300 case Intrinsic::udiv_fix_sat:
2301 return translateFixedPointIntrinsic(TargetOpcode::G_UDIVFIXSAT, CI, MIRBuilder);
2302 case Intrinsic::fmuladd: {
2304 Register Dst = getOrCreateVReg(CI);
2313 MIRBuilder.
buildFMA(Dst, Op0, Op1, Op2,
2324 case Intrinsic::convert_from_fp16:
2330 case Intrinsic::convert_to_fp16:
2336 case Intrinsic::frexp: {
2343 case Intrinsic::sincos: {
2350 case Intrinsic::fptosi_sat:
2354 case Intrinsic::fptoui_sat:
2358 case Intrinsic::memcpy_inline:
2359 return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMCPY_INLINE);
2360 case Intrinsic::memcpy:
2361 return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMCPY);
2362 case Intrinsic::memmove:
2363 return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMMOVE);
2364 case Intrinsic::memset:
2365 return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMSET);
2366 case Intrinsic::eh_typeid_for: {
2373 case Intrinsic::objectsize:
2376 case Intrinsic::is_constant:
2379 case Intrinsic::stackguard:
2380 getStackGuard(getOrCreateVReg(CI), MIRBuilder);
2382 case Intrinsic::stackprotector: {
2387 getStackGuard(GuardVal, MIRBuilder);
2392 int FI = getOrCreateFrameIndex(*Slot);
2396 GuardVal, getOrCreateVReg(*Slot),
2403 case Intrinsic::stacksave: {
2404 MIRBuilder.
buildInstr(TargetOpcode::G_STACKSAVE, {getOrCreateVReg(CI)}, {});
2407 case Intrinsic::stackrestore: {
2408 MIRBuilder.
buildInstr(TargetOpcode::G_STACKRESTORE, {},
2412 case Intrinsic::cttz:
2413 case Intrinsic::ctlz: {
2415 bool isTrailing =
ID == Intrinsic::cttz;
2416 unsigned Opcode = isTrailing
2417 ? Cst->
isZero() ? TargetOpcode::G_CTTZ
2418 : TargetOpcode::G_CTTZ_ZERO_UNDEF
2419 : Cst->
isZero() ? TargetOpcode::G_CTLZ
2420 : TargetOpcode::G_CTLZ_ZERO_UNDEF;
2421 MIRBuilder.
buildInstr(Opcode, {getOrCreateVReg(CI)},
2425 case Intrinsic::invariant_start: {
2431 case Intrinsic::invariant_end:
2433 case Intrinsic::expect:
2434 case Intrinsic::expect_with_probability:
2435 case Intrinsic::annotation:
2436 case Intrinsic::ptr_annotation:
2437 case Intrinsic::launder_invariant_group:
2438 case Intrinsic::strip_invariant_group: {
2440 MIRBuilder.
buildCopy(getOrCreateVReg(CI),
2444 case Intrinsic::assume:
2445 case Intrinsic::experimental_noalias_scope_decl:
2446 case Intrinsic::var_annotation:
2447 case Intrinsic::sideeffect:
2450 case Intrinsic::read_volatile_register:
2451 case Intrinsic::read_register: {
2454 .
buildInstr(TargetOpcode::G_READ_REGISTER, {getOrCreateVReg(CI)}, {})
2455 .addMetadata(cast<MDNode>(cast<MetadataAsValue>(Arg)->getMetadata()));
2458 case Intrinsic::write_register: {
2460 MIRBuilder.
buildInstr(TargetOpcode::G_WRITE_REGISTER)
2461 .
addMetadata(cast<MDNode>(cast<MetadataAsValue>(Arg)->getMetadata()))
2465 case Intrinsic::localescape: {
2473 if (isa<ConstantPointerNull>(Arg))
2476 int FI = getOrCreateFrameIndex(*cast<AllocaInst>(Arg));
2491 case Intrinsic::vector_reduce_fadd:
2492 case Intrinsic::vector_reduce_fmul: {
2495 Register Dst = getOrCreateVReg(CI);
2501 Opc =
ID == Intrinsic::vector_reduce_fadd
2502 ? TargetOpcode::G_VECREDUCE_SEQ_FADD
2503 : TargetOpcode::G_VECREDUCE_SEQ_FMUL;
2504 MIRBuilder.
buildInstr(Opc, {Dst}, {ScalarSrc, VecSrc},
2511 if (
ID == Intrinsic::vector_reduce_fadd) {
2512 Opc = TargetOpcode::G_VECREDUCE_FADD;
2513 ScalarOpc = TargetOpcode::G_FADD;
2515 Opc = TargetOpcode::G_VECREDUCE_FMUL;
2516 ScalarOpc = TargetOpcode::G_FMUL;
2521 MIRBuilder.
buildInstr(ScalarOpc, {Dst}, {ScalarSrc, Rdx},
2526 case Intrinsic::trap:
2527 return translateTrap(CI, MIRBuilder, TargetOpcode::G_TRAP);
2528 case Intrinsic::debugtrap:
2529 return translateTrap(CI, MIRBuilder, TargetOpcode::G_DEBUGTRAP);
2530 case Intrinsic::ubsantrap:
2531 return translateTrap(CI, MIRBuilder, TargetOpcode::G_UBSANTRAP);
2532 case Intrinsic::allow_runtime_check:
2533 case Intrinsic::allow_ubsan_check:
2534 MIRBuilder.
buildCopy(getOrCreateVReg(CI),
2537 case Intrinsic::amdgcn_cs_chain:
2538 return translateCallBase(CI, MIRBuilder);
2539 case Intrinsic::fptrunc_round: {
2544 std::optional<RoundingMode> RoundMode =
2549 .
buildInstr(TargetOpcode::G_INTRINSIC_FPTRUNC_ROUND,
2550 {getOrCreateVReg(CI)},
2552 .addImm((
int)*RoundMode);
2556 case Intrinsic::is_fpclass: {
2561 .
buildInstr(TargetOpcode::G_IS_FPCLASS, {getOrCreateVReg(CI)},
2562 {getOrCreateVReg(*FpValue)})
2567 case Intrinsic::set_fpenv: {
2572 case Intrinsic::reset_fpenv:
2575 case Intrinsic::set_fpmode: {
2580 case Intrinsic::reset_fpmode:
2583 case Intrinsic::vscale: {
2587 case Intrinsic::scmp:
2588 MIRBuilder.
buildSCmp(getOrCreateVReg(CI),
2592 case Intrinsic::ucmp:
2593 MIRBuilder.
buildUCmp(getOrCreateVReg(CI),
2597 case Intrinsic::vector_extract:
2598 return translateExtractVector(CI, MIRBuilder);
2599 case Intrinsic::vector_insert:
2600 return translateInsertVector(CI, MIRBuilder);
2601 case Intrinsic::stepvector: {
2605 case Intrinsic::prefetch: {
2607 unsigned RW = cast<ConstantInt>(CI.
getOperand(1))->getZExtValue();
2608 unsigned Locality = cast<ConstantInt>(CI.
getOperand(2))->getZExtValue();
2609 unsigned CacheType = cast<ConstantInt>(CI.
getOperand(3))->getZExtValue();
2621 case Intrinsic::vector_interleave2:
2622 case Intrinsic::vector_deinterleave2: {
2630 return translateVectorInterleave2Intrinsic(CI, MIRBuilder);
2632 return translateVectorDeinterleave2Intrinsic(CI, MIRBuilder);
2635#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
2636 case Intrinsic::INTRINSIC:
2637#include "llvm/IR/ConstrainedOps.def"
2638 return translateConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(CI),
2640 case Intrinsic::experimental_convergence_anchor:
2641 case Intrinsic::experimental_convergence_entry:
2642 case Intrinsic::experimental_convergence_loop:
2643 return translateConvergenceControlIntrinsic(CI,
ID, MIRBuilder);
2648bool IRTranslator::translateInlineAsm(
const CallBase &CB,
2655 dbgs() <<
"Inline asm lowering is not supported for this target yet\n");
2660 MIRBuilder, CB, [&](
const Value &Val) {
return getOrCreateVRegs(Val); });
2663bool IRTranslator::translateCallBase(
const CallBase &CB,
2670 for (
const auto &Arg : CB.
args()) {
2672 assert(SwiftInVReg == 0 &&
"Expected only one swift error argument");
2676 &CB, &MIRBuilder.
getMBB(), Arg));
2682 Args.push_back(getOrCreateVRegs(*Arg));
2685 if (
auto *CI = dyn_cast<CallInst>(&CB)) {
2686 if (ORE->enabled()) {
2694 std::optional<CallLowering::PtrAuthInfo> PAI;
2699 const Value *
Key = Bundle->Inputs[0];
2706 if (!CalleeCPA || !isa<Function>(CalleeCPA->getPointer()) ||
2707 !CalleeCPA->isKnownCompatibleWith(Key, Discriminator, *DL)) {
2709 Register DiscReg = getOrCreateVReg(*Discriminator);
2717 const auto &Token = *Bundle->Inputs[0].get();
2718 ConvergenceCtrlToken = getOrCreateConvergenceTokenVReg(Token);
2725 MIRBuilder, CB, Res, Args, SwiftErrorVReg, PAI, ConvergenceCtrlToken,
2730 assert(!HasTailCall &&
"Can't tail call return twice from block?");
2739 const CallInst &CI = cast<CallInst>(U);
2745 if (
F && (
F->hasDLLImportStorageClass() ||
2747 F->hasExternalWeakLinkage())))
2755 if (isa<GCStatepointInst, GCRelocateInst, GCResultInst>(U))
2759 return translateInlineAsm(CI, MIRBuilder);
2764 if (
F &&
F->isIntrinsic()) {
2765 ID =
F->getIntrinsicID();
2771 return translateCallBase(CI, MIRBuilder);
2775 if (translateKnownIntrinsic(CI,
ID, MIRBuilder))
2780 ResultRegs = getOrCreateVRegs(CI);
2785 if (isa<FPMathOperator>(CI))
2792 if (
ConstantInt *CI = dyn_cast<ConstantInt>(Arg.value())) {
2795 assert(CI->getBitWidth() <= 64 &&
2796 "large intrinsic immediates not handled");
2797 MIB.
addImm(CI->getSExtValue());
2799 MIB.
addFPImm(cast<ConstantFP>(Arg.value()));
2801 }
else if (
auto *MDVal = dyn_cast<MetadataAsValue>(Arg.value())) {
2802 auto *MD = MDVal->getMetadata();
2803 auto *MDN = dyn_cast<MDNode>(MD);
2805 if (
auto *ConstMD = dyn_cast<ConstantAsMetadata>(MD))
2813 if (VRegs.
size() > 1)
2824 DL->getABITypeAlign(
Info.memVT.getTypeForEVT(
F->getContext())));
2825 LLT MemTy =
Info.memVT.isSimple()
2827 :
LLT::scalar(
Info.memVT.getStoreSizeInBits());
2834 else if (
Info.fallbackAddressSpace)
2842 auto *Token = Bundle->Inputs[0].get();
2843 Register TokenReg = getOrCreateVReg(*Token);
2851bool IRTranslator::findUnwindDestinations(
2871 if (isa<LandingPadInst>(Pad)) {
2873 UnwindDests.emplace_back(&getMBB(*EHPadBB), Prob);
2876 if (isa<CleanupPadInst>(Pad)) {
2879 UnwindDests.emplace_back(&getMBB(*EHPadBB), Prob);
2880 UnwindDests.
back().first->setIsEHScopeEntry();
2881 UnwindDests.back().first->setIsEHFuncletEntry();
2884 if (
auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Pad)) {
2886 for (
const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
2887 UnwindDests.emplace_back(&getMBB(*CatchPadBB), Prob);
2889 if (IsMSVCCXX || IsCoreCLR)
2890 UnwindDests.back().first->setIsEHFuncletEntry();
2892 UnwindDests.back().first->setIsEHScopeEntry();
2894 NewEHPadBB = CatchSwitch->getUnwindDest();
2900 if (BPI && NewEHPadBB)
2902 EHPadBB = NewEHPadBB;
2907bool IRTranslator::translateInvoke(
const User &U,
2915 const Function *Fn =
I.getCalledFunction();
2922 if (
I.hasDeoptState())
2940 bool LowerInlineAsm =
I.isInlineAsm();
2941 bool NeedEHLabel =
true;
2947 MIRBuilder.
buildInstr(TargetOpcode::G_INVOKE_REGION_START);
2952 if (LowerInlineAsm) {
2953 if (!translateInlineAsm(
I, MIRBuilder))
2955 }
else if (!translateCallBase(
I, MIRBuilder))
2971 if (!findUnwindDestinations(EHPadBB, EHPadBBProb, UnwindDests))
2975 &ReturnMBB = getMBB(*ReturnBB);
2977 addSuccessorWithProb(InvokeMBB, &ReturnMBB);
2978 for (
auto &UnwindDest : UnwindDests) {
2979 UnwindDest.first->setIsEHPad();
2980 addSuccessorWithProb(InvokeMBB, UnwindDest.first, UnwindDest.second);
2985 assert(BeginSymbol &&
"Expected a begin symbol!");
2986 assert(EndSymbol &&
"Expected an end symbol!");
2987 MF->
addInvoke(&EHPadMBB, BeginSymbol, EndSymbol);
2990 MIRBuilder.
buildBr(ReturnMBB);
2994bool IRTranslator::translateCallBr(
const User &U,
3000bool IRTranslator::translateLandingPad(
const User &U,
3024 MIRBuilder.
buildInstr(TargetOpcode::EH_LABEL)
3030 if (
auto *RegMask =
TRI.getCustomEHPadPreservedMask(*MF))
3038 for (
Type *Ty : cast<StructType>(LP.
getType())->elements())
3040 assert(
Tys.size() == 2 &&
"Only two-valued landingpads are supported");
3049 MIRBuilder.
buildCopy(ResRegs[0], ExceptionReg);
3057 MIRBuilder.
buildCopy(PtrVReg, SelectorReg);
3058 MIRBuilder.
buildCast(ResRegs[1], PtrVReg);
3063bool IRTranslator::translateAlloca(
const User &U,
3065 auto &AI = cast<AllocaInst>(U);
3071 Register Res = getOrCreateVReg(AI);
3072 int FI = getOrCreateFrameIndex(AI);
3085 if (MRI->
getType(NumElts) != IntPtrTy) {
3095 getOrCreateVReg(*ConstantInt::get(IntPtrIRTy,
DL->getTypeAllocSize(Ty)));
3096 MIRBuilder.
buildMul(AllocSize, NumElts, TySize);
3103 auto AllocAdd = MIRBuilder.
buildAdd(IntPtrTy, AllocSize, SAMinusOne,
3107 auto AlignedAlloc = MIRBuilder.
buildAnd(IntPtrTy, AllocAdd, AlignCst);
3110 if (Alignment <= StackAlign)
3111 Alignment =
Align(1);
3124 MIRBuilder.
buildInstr(TargetOpcode::G_VAARG, {getOrCreateVReg(U)},
3125 {getOrCreateVReg(*
U.getOperand(0)),
3126 DL->getABITypeAlign(
U.getType()).value()});
3134 auto &UI = cast<UnreachableInst>(U);
3137 if (
const CallInst *Call = dyn_cast_or_null<CallInst>(UI.getPrevNode());
3138 Call &&
Call->doesNotReturn()) {
3142 if (
Call->isNonContinuableTrap())
3150bool IRTranslator::translateInsertElement(
const User &U,
3154 if (
auto *FVT = dyn_cast<FixedVectorType>(
U.getType());
3155 FVT && FVT->getNumElements() == 1)
3156 return translateCopy(U, *
U.getOperand(1), MIRBuilder);
3159 Register Val = getOrCreateVReg(*
U.getOperand(0));
3160 Register Elt = getOrCreateVReg(*
U.getOperand(1));
3163 if (
auto *CI = dyn_cast<ConstantInt>(
U.getOperand(2))) {
3164 if (CI->getBitWidth() != PreferredVecIdxWidth) {
3165 APInt NewIdx = CI->getValue().zextOrTrunc(PreferredVecIdxWidth);
3166 auto *NewIdxCI = ConstantInt::get(CI->
getContext(), NewIdx);
3167 Idx = getOrCreateVReg(*NewIdxCI);
3171 Idx = getOrCreateVReg(*
U.getOperand(2));
3180bool IRTranslator::translateInsertVector(
const User &U,
3183 Register Vec = getOrCreateVReg(*
U.getOperand(0));
3184 Register Elt = getOrCreateVReg(*
U.getOperand(1));
3192 CI = ConstantInt::get(CI->
getContext(), NewIdx);
3196 if (
auto *ResultType = dyn_cast<FixedVectorType>(
U.getOperand(1)->getType());
3197 ResultType && ResultType->getNumElements() == 1) {
3198 if (
auto *InputType = dyn_cast<FixedVectorType>(
U.getOperand(0)->getType());
3199 InputType && InputType->getNumElements() == 1) {
3203 return translateCopy(U, *
U.getOperand(0), MIRBuilder);
3205 if (isa<FixedVectorType>(
U.getOperand(0)->getType())) {
3213 if (isa<ScalableVectorType>(
U.getOperand(0)->getType())) {
3218 auto ScaledIndex = MIRBuilder.
buildMul(
3226 getOrCreateVReg(U), getOrCreateVReg(*
U.getOperand(0)),
3231bool IRTranslator::translateExtractElement(
const User &U,
3236 dyn_cast<FixedVectorType>(
U.getOperand(0)->getType()))
3237 if (FVT->getNumElements() == 1)
3238 return translateCopy(U, *
U.getOperand(0), MIRBuilder);
3241 Register Val = getOrCreateVReg(*
U.getOperand(0));
3244 if (
auto *CI = dyn_cast<ConstantInt>(
U.getOperand(1))) {
3247 auto *NewIdxCI = ConstantInt::get(CI->
getContext(), NewIdx);
3248 Idx = getOrCreateVReg(*NewIdxCI);
3252 Idx = getOrCreateVReg(*
U.getOperand(1));
3261bool IRTranslator::translateExtractVector(
const User &U,
3264 Register Vec = getOrCreateVReg(*
U.getOperand(0));
3271 CI = ConstantInt::get(CI->
getContext(), NewIdx);
3275 if (
auto *ResultType = dyn_cast<FixedVectorType>(
U.getType());
3276 ResultType && ResultType->getNumElements() == 1) {
3277 if (
auto *InputType = dyn_cast<FixedVectorType>(
U.getOperand(0)->getType());
3278 InputType && InputType->getNumElements() == 1) {
3281 return translateCopy(U, *
U.getOperand(0), MIRBuilder);
3283 if (isa<FixedVectorType>(
U.getOperand(0)->getType())) {
3291 if (isa<ScalableVectorType>(
U.getOperand(0)->getType())) {
3296 auto ScaledIndex = MIRBuilder.
buildMul(
3304 getOrCreateVReg(*
U.getOperand(0)),
3309bool IRTranslator::translateShuffleVector(
const User &U,
3315 if (
U.getOperand(0)->getType()->isScalableTy()) {
3316 Register Val = getOrCreateVReg(*
U.getOperand(0));
3324 if (
auto *SVI = dyn_cast<ShuffleVectorInst>(&U))
3325 Mask = SVI->getShuffleMask();
3327 Mask = cast<ConstantExpr>(U).getShuffleMask();
3330 .
buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {getOrCreateVReg(U)},
3331 {getOrCreateVReg(*
U.getOperand(0)),
3332 getOrCreateVReg(*
U.getOperand(1))})
3333 .addShuffleMask(MaskAlloc);
3338 const PHINode &PI = cast<PHINode>(U);
3341 for (
auto Reg : getOrCreateVRegs(PI)) {
3342 auto MIB = MIRBuilder.
buildInstr(TargetOpcode::G_PHI, {
Reg}, {});
3346 PendingPHIs.emplace_back(&PI, std::move(Insts));
3350bool IRTranslator::translateAtomicCmpXchg(
const User &U,
3356 auto Res = getOrCreateVRegs(
I);
3360 Register Cmp = getOrCreateVReg(*
I.getCompareOperand());
3361 Register NewVal = getOrCreateVReg(*
I.getNewValOperand());
3364 OldValRes, SuccessRes,
Addr, Cmp, NewVal,
3367 getMemOpAlign(
I),
I.getAAMetadata(),
nullptr,
I.getSyncScopeID(),
3368 I.getSuccessOrdering(),
I.getFailureOrdering()));
3372bool IRTranslator::translateAtomicRMW(
const User &U,
3379 Register Val = getOrCreateVReg(*
I.getValOperand());
3381 unsigned Opcode = 0;
3382 switch (
I.getOperation()) {
3386 Opcode = TargetOpcode::G_ATOMICRMW_XCHG;
3389 Opcode = TargetOpcode::G_ATOMICRMW_ADD;
3392 Opcode = TargetOpcode::G_ATOMICRMW_SUB;
3395 Opcode = TargetOpcode::G_ATOMICRMW_AND;
3398 Opcode = TargetOpcode::G_ATOMICRMW_NAND;
3401 Opcode = TargetOpcode::G_ATOMICRMW_OR;
3404 Opcode = TargetOpcode::G_ATOMICRMW_XOR;
3407 Opcode = TargetOpcode::G_ATOMICRMW_MAX;
3410 Opcode = TargetOpcode::G_ATOMICRMW_MIN;
3413 Opcode = TargetOpcode::G_ATOMICRMW_UMAX;
3416 Opcode = TargetOpcode::G_ATOMICRMW_UMIN;
3419 Opcode = TargetOpcode::G_ATOMICRMW_FADD;
3422 Opcode = TargetOpcode::G_ATOMICRMW_FSUB;
3425 Opcode = TargetOpcode::G_ATOMICRMW_FMAX;
3428 Opcode = TargetOpcode::G_ATOMICRMW_FMIN;
3431 Opcode = TargetOpcode::G_ATOMICRMW_UINC_WRAP;
3434 Opcode = TargetOpcode::G_ATOMICRMW_UDEC_WRAP;
3437 Opcode = TargetOpcode::G_ATOMICRMW_USUB_COND;
3440 Opcode = TargetOpcode::G_ATOMICRMW_USUB_SAT;
3445 Opcode, Res,
Addr, Val,
3447 Flags, MRI->
getType(Val), getMemOpAlign(
I),
3448 I.getAAMetadata(),
nullptr,
I.getSyncScopeID(),
3453bool IRTranslator::translateFence(
const User &U,
3455 const FenceInst &Fence = cast<FenceInst>(U);
3461bool IRTranslator::translateFreeze(
const User &U,
3467 "Freeze with different source and destination type?");
3469 for (
unsigned I = 0;
I < DstRegs.
size(); ++
I) {
3476void IRTranslator::finishPendingPhis() {
3482 for (
auto &Phi : PendingPHIs) {
3497 for (
auto *Pred : getMachinePredBBs({IRPred, PI->
getParent()})) {
3501 for (
unsigned j = 0;
j < ValRegs.
size(); ++
j) {
3511void IRTranslator::translateDbgValueRecord(
Value *V,
bool HasArgList,
3517 "Expected inlined-at fields to agree");
3521 if (!V || HasArgList) {
3528 if (
const auto *CI = dyn_cast<Constant>(V)) {
3533 if (
auto *AI = dyn_cast<AllocaInst>(V);
3538 auto ExprOperands =
Expression->getElements();
3539 auto *ExprDerefRemoved =
3545 if (translateIfEntryValueArgument(
false, V, Variable,
Expression, DL,
3548 for (
Register Reg : getOrCreateVRegs(*V)) {
3557void IRTranslator::translateDbgDeclareRecord(
Value *
Address,
bool HasArgList,
3563 LLVM_DEBUG(
dbgs() <<
"Dropping debug info for " << *Variable <<
"\n");
3568 "Expected inlined-at fields to agree");
3569 auto AI = dyn_cast<AllocaInst>(
Address);
3574 getOrCreateFrameIndex(*AI), DL);
3578 if (translateIfEntryValueArgument(
true,
Address, Variable,
3591void IRTranslator::translateDbgInfo(
const Instruction &Inst,
3596 assert(DLR->getLabel() &&
"Missing label");
3597 assert(DLR->getLabel()->isValidLocationForIntrinsic(
3599 "Expected inlined-at fields to agree");
3616bool IRTranslator::translate(
const Instruction &Inst) {
3618 CurBuilder->setPCSections(Inst.
getMetadata(LLVMContext::MD_pcsections));
3619 CurBuilder->setMMRAMetadata(Inst.
getMetadata(LLVMContext::MD_mmra));
3625#define HANDLE_INST(NUM, OPCODE, CLASS) \
3626 case Instruction::OPCODE: \
3627 return translate##OPCODE(Inst, *CurBuilder.get());
3628#include "llvm/IR/Instruction.def"
3637 if (
auto CurrInstDL = CurBuilder->getDL())
3638 EntryBuilder->setDebugLoc(
DebugLoc());
3640 if (
auto CI = dyn_cast<ConstantInt>(&
C))
3641 EntryBuilder->buildConstant(Reg, *CI);
3642 else if (
auto CF = dyn_cast<ConstantFP>(&
C))
3643 EntryBuilder->buildFConstant(Reg, *CF);
3644 else if (isa<UndefValue>(
C))
3645 EntryBuilder->buildUndef(Reg);
3646 else if (isa<ConstantPointerNull>(
C))
3647 EntryBuilder->buildConstant(Reg, 0);
3648 else if (
auto GV = dyn_cast<GlobalValue>(&
C))
3649 EntryBuilder->buildGlobalValue(Reg, GV);
3650 else if (
auto CPA = dyn_cast<ConstantPtrAuth>(&
C)) {
3652 Register AddrDisc = getOrCreateVReg(*CPA->getAddrDiscriminator());
3653 EntryBuilder->buildConstantPtrAuth(Reg, CPA,
Addr, AddrDisc);
3654 }
else if (
auto CAZ = dyn_cast<ConstantAggregateZero>(&
C)) {
3655 Constant &Elt = *CAZ->getElementValue(0u);
3656 if (isa<ScalableVectorType>(CAZ->getType())) {
3657 EntryBuilder->buildSplatVector(Reg, getOrCreateVReg(Elt));
3661 unsigned NumElts = CAZ->getElementCount().getFixedValue();
3663 return translateCopy(
C, Elt, *EntryBuilder);
3665 EntryBuilder->buildSplatBuildVector(Reg, getOrCreateVReg(Elt));
3666 }
else if (
auto CV = dyn_cast<ConstantDataVector>(&
C)) {
3668 if (CV->getNumElements() == 1)
3669 return translateCopy(
C, *CV->getElementAsConstant(0), *EntryBuilder);
3671 for (
unsigned i = 0; i < CV->getNumElements(); ++i) {
3672 Constant &Elt = *CV->getElementAsConstant(i);
3675 EntryBuilder->buildBuildVector(Reg, Ops);
3676 }
else if (
auto CE = dyn_cast<ConstantExpr>(&
C)) {
3677 switch(
CE->getOpcode()) {
3678#define HANDLE_INST(NUM, OPCODE, CLASS) \
3679 case Instruction::OPCODE: \
3680 return translate##OPCODE(*CE, *EntryBuilder.get());
3681#include "llvm/IR/Instruction.def"
3685 }
else if (
auto CV = dyn_cast<ConstantVector>(&
C)) {
3686 if (CV->getNumOperands() == 1)
3687 return translateCopy(
C, *CV->getOperand(0), *EntryBuilder);
3689 for (
unsigned i = 0; i < CV->getNumOperands(); ++i) {
3690 Ops.
push_back(getOrCreateVReg(*CV->getOperand(i)));
3692 EntryBuilder->buildBuildVector(Reg, Ops);
3693 }
else if (
auto *BA = dyn_cast<BlockAddress>(&
C)) {
3694 EntryBuilder->buildBlockAddress(Reg, BA);
3701bool IRTranslator::finalizeBasicBlock(
const BasicBlock &BB,
3703 for (
auto &BTB : SL->BitTestCases) {
3706 emitBitTestHeader(BTB, BTB.Parent);
3709 for (
unsigned j = 0, ej = BTB.Cases.size(); j != ej; ++j) {
3710 UnhandledProb -= BTB.Cases[
j].ExtraProb;
3722 if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
3725 NextMBB = BTB.Cases[
j + 1].TargetBB;
3726 }
else if (j + 1 == ej) {
3728 NextMBB = BTB.Default;
3731 NextMBB = BTB.Cases[
j + 1].ThisBB;
3734 emitBitTestCase(BTB, NextMBB, UnhandledProb, BTB.Reg, BTB.Cases[j],
MBB);
3736 if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
3740 addMachineCFGPred({BTB.Parent->getBasicBlock(),
3741 BTB.Cases[ej - 1].TargetBB->getBasicBlock()},
3744 BTB.Cases.pop_back();
3750 CFGEdge HeaderToDefaultEdge = {BTB.Parent->getBasicBlock(),
3751 BTB.Default->getBasicBlock()};
3752 addMachineCFGPred(HeaderToDefaultEdge, BTB.Parent);
3753 if (!BTB.ContiguousRange) {
3754 addMachineCFGPred(HeaderToDefaultEdge, BTB.Cases.back().ThisBB);
3757 SL->BitTestCases.clear();
3759 for (
auto &JTCase : SL->JTCases) {
3761 if (!JTCase.first.Emitted)
3762 emitJumpTableHeader(JTCase.second, JTCase.first, JTCase.first.HeaderBB);
3764 emitJumpTable(JTCase.second, JTCase.second.MBB);
3766 SL->JTCases.clear();
3768 for (
auto &SwCase : SL->SwitchCases)
3769 emitSwitchCase(SwCase, &CurBuilder->getMBB(), *CurBuilder);
3770 SL->SwitchCases.clear();
3775 bool FunctionBasedInstrumentation =
3777 SPDescriptor.
initialize(&BB, &
MBB, FunctionBasedInstrumentation);
3797 SuccessMBB->
splice(SuccessMBB->
end(), ParentMBB, SplitPoint,
3801 if (!emitSPDescriptorParent(SPDescriptor, ParentMBB))
3806 if (FailureMBB->
empty()) {
3807 if (!emitSPDescriptorFailure(SPDescriptor, FailureMBB))
3819 CurBuilder->setInsertPt(*ParentBB, ParentBB->
end());
3829 Register StackSlotPtr = CurBuilder->buildFrameIndex(PtrTy, FI).getReg(0);
3836 ->buildLoad(PtrMemTy, StackSlotPtr,
3842 LLVM_DEBUG(
dbgs() <<
"Stack protector xor'ing with FP not yet implemented");
3860 assert(FnTy->getNumParams() == 1 &&
"Invalid function signature");
3862 if (GuardCheckFn->hasAttribute(1, Attribute::AttrKind::InReg))
3865 {GuardVal, FnTy->getParamType(0), {
Flags}});
3868 Info.OrigArgs.push_back(GuardArgInfo);
3869 Info.CallConv = GuardCheckFn->getCallingConv();
3872 if (!CLI->
lowerCall(MIRBuilder, Info)) {
3873 LLVM_DEBUG(
dbgs() <<
"Failed to lower call to stack protector check\n");
3885 getStackGuard(Guard, *CurBuilder);
3889 Register GuardPtr = getOrCreateVReg(*IRGuard);
3892 ->buildLoad(PtrMemTy, GuardPtr,
3911 CurBuilder->setInsertPt(*FailureBB, FailureBB->
end());
3921 if (!CLI->
lowerCall(*CurBuilder, Info)) {
3922 LLVM_DEBUG(
dbgs() <<
"Failed to lower call to stack protector fail\n");
3929 CurBuilder->buildInstr(TargetOpcode::G_TRAP);
3934void IRTranslator::finalizeFunction() {
3937 PendingPHIs.clear();
3939 FrameIndices.clear();
3940 MachinePreds.clear();
3944 EntryBuilder.reset();
3959 const auto *CI = dyn_cast<CallInst>(&
I);
3960 return CI && CI->isMustTailCall();
3968 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
3971 TPC = &getAnalysis<TargetPassConfig>();
3978 EntryBuilder = std::make_unique<CSEMIRBuilder>(CurMF);
3980 EntryBuilder->setCSEInfo(CSEInfo);
3981 CurBuilder = std::make_unique<CSEMIRBuilder>(CurMF);
3982 CurBuilder->setCSEInfo(CSEInfo);
3984 EntryBuilder = std::make_unique<MachineIRBuilder>();
3985 CurBuilder = std::make_unique<MachineIRBuilder>();
3988 CurBuilder->setMF(*MF);
3989 EntryBuilder->setMF(*MF);
3991 DL = &
F.getDataLayout();
3992 ORE = std::make_unique<OptimizationRemarkEmitter>(&
F);
3994 TM.resetTargetOptions(
F);
3998 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
3999 FuncInfo.
BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
4002 FuncInfo.
BPI =
nullptr;
4005 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
4007 LibInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
4010 SL = std::make_unique<GISelSwitchLowering>(
this, FuncInfo);
4011 SL->init(*TLI, TM, *
DL);
4013 assert(PendingPHIs.empty() &&
"stale PHIs");
4020 F.getSubprogram(), &
F.getEntryBlock());
4021 R <<
"unable to translate in big endian mode";
4027 auto FinalizeOnReturn =
make_scope_exit([
this]() { finalizeFunction(); });
4032 EntryBuilder->setMBB(*EntryBB);
4034 DebugLoc DbgLoc =
F.getEntryBlock().getFirstNonPHI()->getDebugLoc();
4038 bool IsVarArg =
F.isVarArg();
4039 bool HasMustTailInVarArgFn =
false;
4042 FuncInfo.
MBBMap.resize(
F.getMaxBlockNumber());
4052 if (!HasMustTailInVarArgFn)
4059 EntryBB->addSuccessor(&getMBB(
F.front()));
4063 F.getSubprogram(), &
F.getEntryBlock());
4064 R <<
"unable to lower function: "
4065 <<
ore::NV(
"Prototype",
F.getFunctionType());
4073 if (
DL->getTypeStoreSize(Arg.
getType()).isZero())
4078 if (Arg.hasSwiftErrorAttr()) {
4079 assert(VRegs.
size() == 1 &&
"Too many vregs for Swift error");
4086 F.getSubprogram(), &
F.getEntryBlock());
4087 R <<
"unable to lower arguments: "
4088 <<
ore::NV(
"Prototype",
F.getFunctionType());
4095 if (EnableCSE && CSEInfo)
4108 CurBuilder->setMBB(
MBB);
4109 HasTailCall =
false;
4123 translateDbgInfo(Inst, *CurBuilder);
4125 if (translate(Inst))
4130 R <<
"unable to translate instruction: " <<
ore::NV(
"Opcode", &Inst);
4132 if (ORE->allowExtraAnalysis(
"gisel-irtranslator")) {
4133 std::string InstStrStorage;
4137 R <<
": '" << InstStrStorage <<
"'";
4144 if (!finalizeBasicBlock(*BB,
MBB)) {
4146 BB->getTerminator()->getDebugLoc(), BB);
4147 R <<
"unable to translate basic block";
4157 finishPendingPhis();
4164 assert(EntryBB->succ_size() == 1 &&
4165 "Custom BB used for lowering should have only one successor");
4169 "LLVM-IR entry block has a predecessor!?");
4172 NewEntryBB.
splice(NewEntryBB.
begin(), EntryBB, EntryBB->begin(),
4181 EntryBB->removeSuccessor(&NewEntryBB);
4186 "New entry wasn't next in the list of basic block!");
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Provides analysis for continuously CSEing during GISel passes.
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
This file describes how to lower LLVM calls to machine code calls.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This contains common code to allow clients to notify changes to machine instr.
const HexagonInstrInfo * TII
IRTranslator LLVM IR static false void reportTranslationError(MachineFunction &MF, const TargetPassConfig &TPC, OptimizationRemarkEmitter &ORE, OptimizationRemarkMissed &R)
static bool checkForMustTailInVarArgFn(bool IsVarArg, const BasicBlock &BB)
Returns true if a BasicBlock BB within a variadic function contains a variadic musttail call.
static unsigned getConvOpcode(Intrinsic::ID ID)
static uint64_t getOffsetFromIndices(const User &U, const DataLayout &DL)
static unsigned getConstrainedOpcode(Intrinsic::ID ID)
static cl::opt< bool > EnableCSEInIRTranslator("enable-cse-in-irtranslator", cl::desc("Should enable CSE in irtranslator"), cl::Optional, cl::init(false))
static bool isValInBlock(const Value *V, const BasicBlock *BB)
static bool isSwiftError(const Value *V)
This file declares the IRTranslator pass.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This file describes how to lower LLVM inline asm to machine code INLINEASM.
Legalize the Machine IR a function s Machine IR
Implement a low-level type suitable for MachineInstr level instruction selection.
Implement a low-level type suitable for MachineInstr level instruction selection.
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
verify safepoint Safepoint IR Verifier
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallSet class.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal=false)
Checks whether the given location points to constant memory, or if OrLocal is true whether it points ...
Class for arbitrary precision integers.
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
an instruction to allocate memory on the stack
bool isSwiftError() const
Return true if this alloca is used as a swifterror argument to a call.
bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
const Value * getArraySize() const
Get the number of elements allocated.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
An immutable pass that tracks lazily created AssumptionCache objects.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
Attribute getFnAttr(Attribute::AttrKind Kind) const
Return the attribute object that exists for the function.
StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
unsigned getNumber() const
bool hasAddressTaken() const
Returns true if there are any uses of this basic block other than direct branches,...
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction * getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
const Instruction & back() const
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
Legacy analysis pass which computes BlockFrequencyInfo.
Conditional or Unconditional Branch instruction.
BasicBlock * getSuccessor(unsigned i) const
bool isUnconditional() const
Value * getCondition() const
Legacy analysis pass which computes BranchProbabilityInfo.
Analysis providing branch probability information.
BranchProbability getEdgeProbability(const BasicBlock *Src, unsigned IndexInSuccessors) const
Get an edge's probability, relative to other out-edges of the Src.
static BranchProbability getZero()
static void normalizeProbabilities(ProbabilityIter Begin, ProbabilityIter End)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
unsigned countOperandBundlesOfType(StringRef Name) const
Return the number of operand bundles with the tag Name attached to this instruction.
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
bool isConvergent() const
Determine if the invoke is convergent.
Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
bool checkReturnTypeForCallConv(MachineFunction &MF) const
Toplevel function to check the return type based on the target calling convention.
virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef< ArrayRef< Register > > VRegs, FunctionLoweringInfo &FLI) const
This hook must be implemented to lower the incoming (formal) arguments, described by VRegs,...
virtual bool enableBigEndian() const
For targets which want to use big-endian can enable it with enableBigEndian() hook.
virtual bool supportSwiftError() const
virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI, Register SwiftErrorVReg) const
This hook must be implemented to lower outgoing return values, described by Val, into the specified v...
virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const
This hook must be implemented to lower the given call instruction, including argument and return valu...
virtual bool fallBackToDAGISel(const MachineFunction &MF) const
This class is the base class for the comparison instructions.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_ULE
unsigned less or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
bool isFPPredicate() const
bool isIntPredicate() const
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This is the common base class for constrained floating point intrinsics.
std::optional< fp::ExceptionBehavior > getExceptionBehavior() const
unsigned getNonMetadataArgCount() const
bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
static DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Append the opcodes Ops to DIExpr.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this label.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const
Returns the type of a GEP index in AddressSpace.
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Align getPointerABIAlignment(unsigned AS) const
Layout pointer alignment.
This represents the llvm.dbg.declare instruction.
Value * getAddress() const
This represents the llvm.dbg.label instruction.
DILabel * getLabel() const
Records a position in IR for a source label (DILabel).
Base class for non-instruction debug metadata records that have positions within IR.
DebugLoc getDebugLoc() const
This represents the llvm.dbg.value instruction.
Value * getValue(unsigned OpIdx=0) const
DILocalVariable * getVariable() const
DIExpression * getExpression() const
Record of a variable value-assignment, aka a non instruction representation of the dbg....
DIExpression * getExpression() const
Value * getVariableLocationOp(unsigned OpIdx) const
DILocalVariable * getVariable() const
bool isDbgDeclare() const
Class representing an expression and its matching format.
This instruction compares its operands according to the predicate given to the constructor.
An instruction for ordering other memory operations.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this fence instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this fence instruction.
Class to represent fixed width SIMD vectors.
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
BranchProbabilityInfo * BPI
void clear()
clear - Clear out all the function-specific state.
MachineBasicBlock * getMBB(const BasicBlock *BB) const
SmallVector< MachineBasicBlock * > MBBMap
A mapping from LLVM basic block number to their machine block.
bool CanLowerReturn
CanLowerReturn - true iff the function's return value can be lowered to registers.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
const BasicBlock & getEntryBlock() const
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Constant * getPersonalityFn() const
Get the personality function associated with this function.
const Function & getFunction() const
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
bool hasOptNone() const
Do not optimize this function (-O0).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
The actual analysis pass wrapper.
Simple wrapper that does the following.
Abstract class that contains various methods for clients to notify about changes.
Simple wrapper observer that takes several observers, and calls each one for each event.
void removeObserver(GISelChangeObserver *O)
void addObserver(GISelChangeObserver *O)
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isTailCall(const MachineInstr &MI) const override
This instruction compares its operands according to the predicate given to the constructor.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
IRTranslator(CodeGenOptLevel OptLevel=CodeGenOptLevel::None)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Indirect Branch Instruction.
bool lowerInlineAsm(MachineIRBuilder &MIRBuilder, const CallBase &CB, std::function< ArrayRef< Register >(const Value &Val)> GetOrCreateVRegs) const
Lower the given inline asm call instruction GetOrCreateVRegs is a callback to materialize a register ...
This instruction inserts a struct field of array element value into an aggregate value.
iterator_range< simple_ilist< DbgRecord >::iterator > getDbgRecordRange() const
Return a range over the DbgRecords attached to this instruction.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool hasAllowReassoc() const LLVM_READONLY
Determine whether the allow-reassociation flag is set.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
The landingpad instruction holds all of the information necessary to generate correct exception handl...
An instruction for reading from memory.
Value * getPointerOperand()
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
static LocationSize precise(uint64_t Value)
Context object for machine code objects.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSymbol * getOrCreateFrameAllocSymbol(const Twine &FuncName, unsigned Idx)
Gets a symbol that will be defined to the final stack offset of a local variable after codegen.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
unsigned pred_size() const
void normalizeSuccProbs()
Normalize probabilities of all successors so that the sum of them becomes one.
void setAddressTakenIRBlock(BasicBlock *BB)
Set this block to reflect that it corresponds to an IR-level basic block with a BlockAddress.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void setSuccProbability(succ_iterator I, BranchProbability Prob)
Set successor probability of a given iterator.
succ_iterator succ_begin()
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
SmallVectorImpl< MachineBasicBlock * >::iterator succ_iterator
void sortUniqueLiveIns()
Sorts and uniques the LiveIns vector.
bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
int getStackProtectorIndex() const
Return the index for the stack protector object.
void setStackProtectorIndex(int I)
int CreateVariableSizedObject(Align Alignment, const AllocaInst *Alloca)
Notify the MachineFrameInfo object that a variable sized object has been created.
void setHasMustTailInVarArgFunc(bool B)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
ArrayRef< int > allocateShuffleMask(ArrayRef< int > Mask)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const