xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //===- llvm/CodeGen/GlobalISel/IRTranslator.cpp - IRTranslator ---*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This file implements the IRTranslator class.
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
130b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
140b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
150b57cec5SDimitry Andric #include "llvm/ADT/ScopeExit.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
18fcaf7f86SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
19bdd1243dSDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
200b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
21bdd1243dSDimitry Andric #include "llvm/Analysis/Loads.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
240fca6ea1SDimitry Andric #include "llvm/Analysis/VectorUtils.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/Analysis.h"
2681ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
2781ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
305ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
31349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
3206c3fb27SDimitry Andric #include "llvm/CodeGen/LowLevelTypeUtils.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
370b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
38e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
390b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
400b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
410fca6ea1SDimitry Andric #include "llvm/CodeGen/RuntimeLibcallUtil.h"
420b57cec5SDimitry Andric #include "llvm/CodeGen/StackProtector.h"
43e8d8bef9SDimitry Andric #include "llvm/CodeGen/SwitchLoweringUtils.h"
440b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
458bcb0991SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
460b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
4706c3fb27SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
480b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
490b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
500b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
510fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h"
520b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
530b57cec5SDimitry Andric #include "llvm/IR/CFG.h"
540b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
550b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
560b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
570b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
58349cc55cSDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
590b57cec5SDimitry Andric #include "llvm/IR/Function.h"
600b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
610b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
62e8d8bef9SDimitry Andric #include "llvm/IR/InstrTypes.h"
630b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
640b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
650b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
665f757f3fSDimitry Andric #include "llvm/IR/IntrinsicsAMDGPU.h"
670b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
680b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
69e8d8bef9SDimitry Andric #include "llvm/IR/PatternMatch.h"
70bdd1243dSDimitry Andric #include "llvm/IR/Statepoint.h"
710b57cec5SDimitry Andric #include "llvm/IR/Type.h"
720b57cec5SDimitry Andric #include "llvm/IR/User.h"
730b57cec5SDimitry Andric #include "llvm/IR/Value.h"
74480093f4SDimitry Andric #include "llvm/InitializePasses.h"
750b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
760b57cec5SDimitry Andric #include "llvm/Pass.h"
770b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
780b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
790b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
800b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
810b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
820b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
830b57cec5SDimitry Andric #include "llvm/Target/TargetIntrinsicInfo.h"
840b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
855f757f3fSDimitry Andric #include "llvm/Transforms/Utils/Local.h"
86fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/MemoryOpRemark.h"
870b57cec5SDimitry Andric #include <algorithm>
880b57cec5SDimitry Andric #include <cassert>
890b57cec5SDimitry Andric #include <cstdint>
900b57cec5SDimitry Andric #include <iterator>
91bdd1243dSDimitry Andric #include <optional>
920b57cec5SDimitry Andric #include <string>
930b57cec5SDimitry Andric #include <utility>
940b57cec5SDimitry Andric #include <vector>
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric #define DEBUG_TYPE "irtranslator"
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric using namespace llvm;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric static cl::opt<bool>
1010b57cec5SDimitry Andric     EnableCSEInIRTranslator("enable-cse-in-irtranslator",
1020b57cec5SDimitry Andric                             cl::desc("Should enable CSE in irtranslator"),
1030b57cec5SDimitry Andric                             cl::Optional, cl::init(false));
1040b57cec5SDimitry Andric char IRTranslator::ID = 0;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(IRTranslator, DEBUG_TYPE, "IRTranslator LLVM IR -> MI",
1070b57cec5SDimitry Andric                 false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)1080b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
1090b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
110e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
111e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(StackProtector)
112fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
1130b57cec5SDimitry Andric INITIALIZE_PASS_END(IRTranslator, DEBUG_TYPE, "IRTranslator LLVM IR -> MI",
1140b57cec5SDimitry Andric                 false, false)
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric static void reportTranslationError(MachineFunction &MF,
1170b57cec5SDimitry Andric                                    const TargetPassConfig &TPC,
1180b57cec5SDimitry Andric                                    OptimizationRemarkEmitter &ORE,
1190b57cec5SDimitry Andric                                    OptimizationRemarkMissed &R) {
1200b57cec5SDimitry Andric   MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // Print the function name explicitly if we don't have a debug location (which
1230b57cec5SDimitry Andric   // makes the diagnostic less useful) or if we're going to emit a raw error.
1240b57cec5SDimitry Andric   if (!R.getLocation().isValid() || TPC.isGlobalISelAbortEnabled())
1250b57cec5SDimitry Andric     R << (" (in function: " + MF.getName() + ")").str();
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   if (TPC.isGlobalISelAbortEnabled())
128349cc55cSDimitry Andric     report_fatal_error(Twine(R.getMsg()));
1290b57cec5SDimitry Andric   else
1300b57cec5SDimitry Andric     ORE.emit(R);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
IRTranslator(CodeGenOptLevel optlevel)1335f757f3fSDimitry Andric IRTranslator::IRTranslator(CodeGenOptLevel optlevel)
134e8d8bef9SDimitry Andric     : MachineFunctionPass(ID), OptLevel(optlevel) {}
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric #ifndef NDEBUG
1370b57cec5SDimitry Andric namespace {
1380b57cec5SDimitry Andric /// Verify that every instruction created has the same DILocation as the
1390b57cec5SDimitry Andric /// instruction being translated.
1400b57cec5SDimitry Andric class DILocationVerifier : public GISelChangeObserver {
1410b57cec5SDimitry Andric   const Instruction *CurrInst = nullptr;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric public:
1440b57cec5SDimitry Andric   DILocationVerifier() = default;
1450b57cec5SDimitry Andric   ~DILocationVerifier() = default;
1460b57cec5SDimitry Andric 
getCurrentInst() const1470b57cec5SDimitry Andric   const Instruction *getCurrentInst() const { return CurrInst; }
setCurrentInst(const Instruction * Inst)1480b57cec5SDimitry Andric   void setCurrentInst(const Instruction *Inst) { CurrInst = Inst; }
1490b57cec5SDimitry Andric 
erasingInstr(MachineInstr & MI)1500b57cec5SDimitry Andric   void erasingInstr(MachineInstr &MI) override {}
changingInstr(MachineInstr & MI)1510b57cec5SDimitry Andric   void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)1520b57cec5SDimitry Andric   void changedInstr(MachineInstr &MI) override {}
1530b57cec5SDimitry Andric 
createdInstr(MachineInstr & MI)1540b57cec5SDimitry Andric   void createdInstr(MachineInstr &MI) override {
1550b57cec5SDimitry Andric     assert(getCurrentInst() && "Inserted instruction without a current MI");
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric     // Only print the check message if we're actually checking it.
1580b57cec5SDimitry Andric #ifndef NDEBUG
1590b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Checking DILocation from " << *CurrInst
1600b57cec5SDimitry Andric                       << " was copied to " << MI);
1610b57cec5SDimitry Andric #endif
162972a253aSDimitry Andric     // We allow insts in the entry block to have no debug loc because
1630b57cec5SDimitry Andric     // they could have originated from constants, and we don't want a jumpy
1640b57cec5SDimitry Andric     // debug experience.
1650b57cec5SDimitry Andric     assert((CurrInst->getDebugLoc() == MI.getDebugLoc() ||
1667a6dacacSDimitry Andric             (MI.getParent()->isEntryBlock() && !MI.getDebugLoc()) ||
1677a6dacacSDimitry Andric             (MI.isDebugInstr())) &&
1680b57cec5SDimitry Andric            "Line info was not transferred to all instructions");
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric };
1710b57cec5SDimitry Andric } // namespace
1720b57cec5SDimitry Andric #endif // ifndef NDEBUG
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const1750b57cec5SDimitry Andric void IRTranslator::getAnalysisUsage(AnalysisUsage &AU) const {
1760b57cec5SDimitry Andric   AU.addRequired<StackProtector>();
1770b57cec5SDimitry Andric   AU.addRequired<TargetPassConfig>();
1780b57cec5SDimitry Andric   AU.addRequired<GISelCSEAnalysisWrapperPass>();
179bdd1243dSDimitry Andric   AU.addRequired<AssumptionCacheTracker>();
1805f757f3fSDimitry Andric   if (OptLevel != CodeGenOptLevel::None) {
181e8d8bef9SDimitry Andric     AU.addRequired<BranchProbabilityInfoWrapperPass>();
182fcaf7f86SDimitry Andric     AU.addRequired<AAResultsWrapperPass>();
183fcaf7f86SDimitry Andric   }
184fe6060f1SDimitry Andric   AU.addRequired<TargetLibraryInfoWrapperPass>();
185fe6060f1SDimitry Andric   AU.addPreserved<TargetLibraryInfoWrapperPass>();
1860b57cec5SDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
1870b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric IRTranslator::ValueToVRegInfo::VRegListT &
allocateVRegs(const Value & Val)1910b57cec5SDimitry Andric IRTranslator::allocateVRegs(const Value &Val) {
192e8d8bef9SDimitry Andric   auto VRegsIt = VMap.findVRegs(Val);
193e8d8bef9SDimitry Andric   if (VRegsIt != VMap.vregs_end())
194e8d8bef9SDimitry Andric     return *VRegsIt->second;
1950b57cec5SDimitry Andric   auto *Regs = VMap.getVRegs(Val);
1960b57cec5SDimitry Andric   auto *Offsets = VMap.getOffsets(Val);
1970b57cec5SDimitry Andric   SmallVector<LLT, 4> SplitTys;
1980b57cec5SDimitry Andric   computeValueLLTs(*DL, *Val.getType(), SplitTys,
1990b57cec5SDimitry Andric                    Offsets->empty() ? Offsets : nullptr);
2000b57cec5SDimitry Andric   for (unsigned i = 0; i < SplitTys.size(); ++i)
2010b57cec5SDimitry Andric     Regs->push_back(0);
2020b57cec5SDimitry Andric   return *Regs;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
getOrCreateVRegs(const Value & Val)2050b57cec5SDimitry Andric ArrayRef<Register> IRTranslator::getOrCreateVRegs(const Value &Val) {
2060b57cec5SDimitry Andric   auto VRegsIt = VMap.findVRegs(Val);
2070b57cec5SDimitry Andric   if (VRegsIt != VMap.vregs_end())
2080b57cec5SDimitry Andric     return *VRegsIt->second;
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   if (Val.getType()->isVoidTy())
2110b57cec5SDimitry Andric     return *VMap.getVRegs(Val);
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   // Create entry for this type.
2140b57cec5SDimitry Andric   auto *VRegs = VMap.getVRegs(Val);
2150b57cec5SDimitry Andric   auto *Offsets = VMap.getOffsets(Val);
2160b57cec5SDimitry Andric 
2170fca6ea1SDimitry Andric   if (!Val.getType()->isTokenTy())
2180b57cec5SDimitry Andric     assert(Val.getType()->isSized() &&
2190b57cec5SDimitry Andric            "Don't know how to create an empty vreg");
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   SmallVector<LLT, 4> SplitTys;
2220b57cec5SDimitry Andric   computeValueLLTs(*DL, *Val.getType(), SplitTys,
2230b57cec5SDimitry Andric                    Offsets->empty() ? Offsets : nullptr);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   if (!isa<Constant>(Val)) {
2260b57cec5SDimitry Andric     for (auto Ty : SplitTys)
2270b57cec5SDimitry Andric       VRegs->push_back(MRI->createGenericVirtualRegister(Ty));
2280b57cec5SDimitry Andric     return *VRegs;
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   if (Val.getType()->isAggregateType()) {
2320b57cec5SDimitry Andric     // UndefValue, ConstantAggregateZero
2330b57cec5SDimitry Andric     auto &C = cast<Constant>(Val);
2340b57cec5SDimitry Andric     unsigned Idx = 0;
2350b57cec5SDimitry Andric     while (auto Elt = C.getAggregateElement(Idx++)) {
2360b57cec5SDimitry Andric       auto EltRegs = getOrCreateVRegs(*Elt);
2370b57cec5SDimitry Andric       llvm::copy(EltRegs, std::back_inserter(*VRegs));
2380b57cec5SDimitry Andric     }
2390b57cec5SDimitry Andric   } else {
2400b57cec5SDimitry Andric     assert(SplitTys.size() == 1 && "unexpectedly split LLT");
2410b57cec5SDimitry Andric     VRegs->push_back(MRI->createGenericVirtualRegister(SplitTys[0]));
2420b57cec5SDimitry Andric     bool Success = translate(cast<Constant>(Val), VRegs->front());
2430b57cec5SDimitry Andric     if (!Success) {
2440b57cec5SDimitry Andric       OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
2450b57cec5SDimitry Andric                                  MF->getFunction().getSubprogram(),
2460b57cec5SDimitry Andric                                  &MF->getFunction().getEntryBlock());
2470b57cec5SDimitry Andric       R << "unable to translate constant: " << ore::NV("Type", Val.getType());
2480b57cec5SDimitry Andric       reportTranslationError(*MF, *TPC, *ORE, R);
2490b57cec5SDimitry Andric       return *VRegs;
2500b57cec5SDimitry Andric     }
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   return *VRegs;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
getOrCreateFrameIndex(const AllocaInst & AI)2560b57cec5SDimitry Andric int IRTranslator::getOrCreateFrameIndex(const AllocaInst &AI) {
257e8d8bef9SDimitry Andric   auto MapEntry = FrameIndices.find(&AI);
258e8d8bef9SDimitry Andric   if (MapEntry != FrameIndices.end())
259e8d8bef9SDimitry Andric     return MapEntry->second;
2600b57cec5SDimitry Andric 
261480093f4SDimitry Andric   uint64_t ElementSize = DL->getTypeAllocSize(AI.getAllocatedType());
262480093f4SDimitry Andric   uint64_t Size =
2630b57cec5SDimitry Andric       ElementSize * cast<ConstantInt>(AI.getArraySize())->getZExtValue();
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   // Always allocate at least one byte.
266480093f4SDimitry Andric   Size = std::max<uint64_t>(Size, 1u);
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   int &FI = FrameIndices[&AI];
2695ffd83dbSDimitry Andric   FI = MF->getFrameInfo().CreateStackObject(Size, AI.getAlign(), false, &AI);
2700b57cec5SDimitry Andric   return FI;
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric 
getMemOpAlign(const Instruction & I)2735ffd83dbSDimitry Andric Align IRTranslator::getMemOpAlign(const Instruction &I) {
2745ffd83dbSDimitry Andric   if (const StoreInst *SI = dyn_cast<StoreInst>(&I))
2755ffd83dbSDimitry Andric     return SI->getAlign();
276fe6060f1SDimitry Andric   if (const LoadInst *LI = dyn_cast<LoadInst>(&I))
2775ffd83dbSDimitry Andric     return LI->getAlign();
278fe6060f1SDimitry Andric   if (const AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(&I))
279fe6060f1SDimitry Andric     return AI->getAlign();
280fe6060f1SDimitry Andric   if (const AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(&I))
281fe6060f1SDimitry Andric     return AI->getAlign();
282fe6060f1SDimitry Andric 
2830b57cec5SDimitry Andric   OptimizationRemarkMissed R("gisel-irtranslator", "", &I);
2840b57cec5SDimitry Andric   R << "unable to translate memop: " << ore::NV("Opcode", &I);
2850b57cec5SDimitry Andric   reportTranslationError(*MF, *TPC, *ORE, R);
2865ffd83dbSDimitry Andric   return Align(1);
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
getMBB(const BasicBlock & BB)2890b57cec5SDimitry Andric MachineBasicBlock &IRTranslator::getMBB(const BasicBlock &BB) {
2900b57cec5SDimitry Andric   MachineBasicBlock *&MBB = BBToMBB[&BB];
2910b57cec5SDimitry Andric   assert(MBB && "BasicBlock was not encountered before");
2920b57cec5SDimitry Andric   return *MBB;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric 
addMachineCFGPred(CFGEdge Edge,MachineBasicBlock * NewPred)2950b57cec5SDimitry Andric void IRTranslator::addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred) {
2960b57cec5SDimitry Andric   assert(NewPred && "new predecessor must be a real MachineBasicBlock");
2970b57cec5SDimitry Andric   MachinePreds[Edge].push_back(NewPred);
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric 
translateBinaryOp(unsigned Opcode,const User & U,MachineIRBuilder & MIRBuilder)3000b57cec5SDimitry Andric bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
3010b57cec5SDimitry Andric                                      MachineIRBuilder &MIRBuilder) {
3020b57cec5SDimitry Andric   // Get or create a virtual register for each value.
3030b57cec5SDimitry Andric   // Unless the value is a Constant => loadimm cst?
3040b57cec5SDimitry Andric   // or inline constant each time?
3050b57cec5SDimitry Andric   // Creation of a virtual register needs to have a size.
3060b57cec5SDimitry Andric   Register Op0 = getOrCreateVReg(*U.getOperand(0));
3070b57cec5SDimitry Andric   Register Op1 = getOrCreateVReg(*U.getOperand(1));
3080b57cec5SDimitry Andric   Register Res = getOrCreateVReg(U);
30906c3fb27SDimitry Andric   uint32_t Flags = 0;
3100b57cec5SDimitry Andric   if (isa<Instruction>(U)) {
3110b57cec5SDimitry Andric     const Instruction &I = cast<Instruction>(U);
3120b57cec5SDimitry Andric     Flags = MachineInstr::copyFlagsFromInstruction(I);
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   MIRBuilder.buildInstr(Opcode, {Res}, {Op0, Op1}, Flags);
3160b57cec5SDimitry Andric   return true;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric 
translateUnaryOp(unsigned Opcode,const User & U,MachineIRBuilder & MIRBuilder)319e8d8bef9SDimitry Andric bool IRTranslator::translateUnaryOp(unsigned Opcode, const User &U,
320e8d8bef9SDimitry Andric                                     MachineIRBuilder &MIRBuilder) {
3210b57cec5SDimitry Andric   Register Op0 = getOrCreateVReg(*U.getOperand(0));
3220b57cec5SDimitry Andric   Register Res = getOrCreateVReg(U);
32306c3fb27SDimitry Andric   uint32_t Flags = 0;
3240b57cec5SDimitry Andric   if (isa<Instruction>(U)) {
3250b57cec5SDimitry Andric     const Instruction &I = cast<Instruction>(U);
3260b57cec5SDimitry Andric     Flags = MachineInstr::copyFlagsFromInstruction(I);
3270b57cec5SDimitry Andric   }
328e8d8bef9SDimitry Andric   MIRBuilder.buildInstr(Opcode, {Res}, {Op0}, Flags);
3290b57cec5SDimitry Andric   return true;
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
translateFNeg(const User & U,MachineIRBuilder & MIRBuilder)332e8d8bef9SDimitry Andric bool IRTranslator::translateFNeg(const User &U, MachineIRBuilder &MIRBuilder) {
333e8d8bef9SDimitry Andric   return translateUnaryOp(TargetOpcode::G_FNEG, U, MIRBuilder);
334e8d8bef9SDimitry Andric }
335e8d8bef9SDimitry Andric 
translateCompare(const User & U,MachineIRBuilder & MIRBuilder)3360b57cec5SDimitry Andric bool IRTranslator::translateCompare(const User &U,
3370b57cec5SDimitry Andric                                     MachineIRBuilder &MIRBuilder) {
3380fca6ea1SDimitry Andric   auto *CI = cast<CmpInst>(&U);
3390b57cec5SDimitry Andric   Register Op0 = getOrCreateVReg(*U.getOperand(0));
3400b57cec5SDimitry Andric   Register Op1 = getOrCreateVReg(*U.getOperand(1));
3410b57cec5SDimitry Andric   Register Res = getOrCreateVReg(U);
3420fca6ea1SDimitry Andric   CmpInst::Predicate Pred = CI->getPredicate();
3430b57cec5SDimitry Andric   if (CmpInst::isIntPredicate(Pred))
3440b57cec5SDimitry Andric     MIRBuilder.buildICmp(Pred, Res, Op0, Op1);
3450b57cec5SDimitry Andric   else if (Pred == CmpInst::FCMP_FALSE)
3460b57cec5SDimitry Andric     MIRBuilder.buildCopy(
3478bcb0991SDimitry Andric         Res, getOrCreateVReg(*Constant::getNullValue(U.getType())));
3480b57cec5SDimitry Andric   else if (Pred == CmpInst::FCMP_TRUE)
3490b57cec5SDimitry Andric     MIRBuilder.buildCopy(
3508bcb0991SDimitry Andric         Res, getOrCreateVReg(*Constant::getAllOnesValue(U.getType())));
3510b57cec5SDimitry Andric   else {
35206c3fb27SDimitry Andric     uint32_t Flags = 0;
3530eae32dcSDimitry Andric     if (CI)
3540eae32dcSDimitry Andric       Flags = MachineInstr::copyFlagsFromInstruction(*CI);
3550eae32dcSDimitry Andric     MIRBuilder.buildFCmp(Pred, Res, Op0, Op1, Flags);
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   return true;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
translateRet(const User & U,MachineIRBuilder & MIRBuilder)3610b57cec5SDimitry Andric bool IRTranslator::translateRet(const User &U, MachineIRBuilder &MIRBuilder) {
3620b57cec5SDimitry Andric   const ReturnInst &RI = cast<ReturnInst>(U);
3630b57cec5SDimitry Andric   const Value *Ret = RI.getReturnValue();
3645f757f3fSDimitry Andric   if (Ret && DL->getTypeStoreSize(Ret->getType()).isZero())
3650b57cec5SDimitry Andric     Ret = nullptr;
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   ArrayRef<Register> VRegs;
3680b57cec5SDimitry Andric   if (Ret)
3690b57cec5SDimitry Andric     VRegs = getOrCreateVRegs(*Ret);
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   Register SwiftErrorVReg = 0;
3720b57cec5SDimitry Andric   if (CLI->supportSwiftError() && SwiftError.getFunctionArg()) {
3730b57cec5SDimitry Andric     SwiftErrorVReg = SwiftError.getOrCreateVRegUseAt(
3740b57cec5SDimitry Andric         &RI, &MIRBuilder.getMBB(), SwiftError.getFunctionArg());
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   // The target may mess up with the insertion point, but
3780b57cec5SDimitry Andric   // this is not important as a return is the last instruction
3790b57cec5SDimitry Andric   // of the block anyway.
380e8d8bef9SDimitry Andric   return CLI->lowerReturn(MIRBuilder, Ret, VRegs, FuncInfo, SwiftErrorVReg);
381e8d8bef9SDimitry Andric }
382e8d8bef9SDimitry Andric 
emitBranchForMergedCondition(const Value * Cond,MachineBasicBlock * TBB,MachineBasicBlock * FBB,MachineBasicBlock * CurBB,MachineBasicBlock * SwitchBB,BranchProbability TProb,BranchProbability FProb,bool InvertCond)383e8d8bef9SDimitry Andric void IRTranslator::emitBranchForMergedCondition(
384e8d8bef9SDimitry Andric     const Value *Cond, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
385e8d8bef9SDimitry Andric     MachineBasicBlock *CurBB, MachineBasicBlock *SwitchBB,
386e8d8bef9SDimitry Andric     BranchProbability TProb, BranchProbability FProb, bool InvertCond) {
387e8d8bef9SDimitry Andric   // If the leaf of the tree is a comparison, merge the condition into
388e8d8bef9SDimitry Andric   // the caseblock.
389e8d8bef9SDimitry Andric   if (const CmpInst *BOp = dyn_cast<CmpInst>(Cond)) {
390e8d8bef9SDimitry Andric     CmpInst::Predicate Condition;
391e8d8bef9SDimitry Andric     if (const ICmpInst *IC = dyn_cast<ICmpInst>(Cond)) {
392e8d8bef9SDimitry Andric       Condition = InvertCond ? IC->getInversePredicate() : IC->getPredicate();
393e8d8bef9SDimitry Andric     } else {
394e8d8bef9SDimitry Andric       const FCmpInst *FC = cast<FCmpInst>(Cond);
395e8d8bef9SDimitry Andric       Condition = InvertCond ? FC->getInversePredicate() : FC->getPredicate();
396e8d8bef9SDimitry Andric     }
397e8d8bef9SDimitry Andric 
398e8d8bef9SDimitry Andric     SwitchCG::CaseBlock CB(Condition, false, BOp->getOperand(0),
399e8d8bef9SDimitry Andric                            BOp->getOperand(1), nullptr, TBB, FBB, CurBB,
400e8d8bef9SDimitry Andric                            CurBuilder->getDebugLoc(), TProb, FProb);
401e8d8bef9SDimitry Andric     SL->SwitchCases.push_back(CB);
402e8d8bef9SDimitry Andric     return;
403e8d8bef9SDimitry Andric   }
404e8d8bef9SDimitry Andric 
405e8d8bef9SDimitry Andric   // Create a CaseBlock record representing this branch.
406e8d8bef9SDimitry Andric   CmpInst::Predicate Pred = InvertCond ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ;
407e8d8bef9SDimitry Andric   SwitchCG::CaseBlock CB(
408e8d8bef9SDimitry Andric       Pred, false, Cond, ConstantInt::getTrue(MF->getFunction().getContext()),
409e8d8bef9SDimitry Andric       nullptr, TBB, FBB, CurBB, CurBuilder->getDebugLoc(), TProb, FProb);
410e8d8bef9SDimitry Andric   SL->SwitchCases.push_back(CB);
411e8d8bef9SDimitry Andric }
412e8d8bef9SDimitry Andric 
isValInBlock(const Value * V,const BasicBlock * BB)413e8d8bef9SDimitry Andric static bool isValInBlock(const Value *V, const BasicBlock *BB) {
414e8d8bef9SDimitry Andric   if (const Instruction *I = dyn_cast<Instruction>(V))
415e8d8bef9SDimitry Andric     return I->getParent() == BB;
416e8d8bef9SDimitry Andric   return true;
417e8d8bef9SDimitry Andric }
418e8d8bef9SDimitry Andric 
findMergedConditions(const Value * Cond,MachineBasicBlock * TBB,MachineBasicBlock * FBB,MachineBasicBlock * CurBB,MachineBasicBlock * SwitchBB,Instruction::BinaryOps Opc,BranchProbability TProb,BranchProbability FProb,bool InvertCond)419e8d8bef9SDimitry Andric void IRTranslator::findMergedConditions(
420e8d8bef9SDimitry Andric     const Value *Cond, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
421e8d8bef9SDimitry Andric     MachineBasicBlock *CurBB, MachineBasicBlock *SwitchBB,
422e8d8bef9SDimitry Andric     Instruction::BinaryOps Opc, BranchProbability TProb,
423e8d8bef9SDimitry Andric     BranchProbability FProb, bool InvertCond) {
424e8d8bef9SDimitry Andric   using namespace PatternMatch;
425e8d8bef9SDimitry Andric   assert((Opc == Instruction::And || Opc == Instruction::Or) &&
426e8d8bef9SDimitry Andric          "Expected Opc to be AND/OR");
427e8d8bef9SDimitry Andric   // Skip over not part of the tree and remember to invert op and operands at
428e8d8bef9SDimitry Andric   // next level.
429e8d8bef9SDimitry Andric   Value *NotCond;
430e8d8bef9SDimitry Andric   if (match(Cond, m_OneUse(m_Not(m_Value(NotCond)))) &&
431e8d8bef9SDimitry Andric       isValInBlock(NotCond, CurBB->getBasicBlock())) {
432e8d8bef9SDimitry Andric     findMergedConditions(NotCond, TBB, FBB, CurBB, SwitchBB, Opc, TProb, FProb,
433e8d8bef9SDimitry Andric                          !InvertCond);
434e8d8bef9SDimitry Andric     return;
435e8d8bef9SDimitry Andric   }
436e8d8bef9SDimitry Andric 
437e8d8bef9SDimitry Andric   const Instruction *BOp = dyn_cast<Instruction>(Cond);
438e8d8bef9SDimitry Andric   const Value *BOpOp0, *BOpOp1;
439e8d8bef9SDimitry Andric   // Compute the effective opcode for Cond, taking into account whether it needs
440e8d8bef9SDimitry Andric   // to be inverted, e.g.
441e8d8bef9SDimitry Andric   //   and (not (or A, B)), C
442e8d8bef9SDimitry Andric   // gets lowered as
443e8d8bef9SDimitry Andric   //   and (and (not A, not B), C)
444e8d8bef9SDimitry Andric   Instruction::BinaryOps BOpc = (Instruction::BinaryOps)0;
445e8d8bef9SDimitry Andric   if (BOp) {
446e8d8bef9SDimitry Andric     BOpc = match(BOp, m_LogicalAnd(m_Value(BOpOp0), m_Value(BOpOp1)))
447e8d8bef9SDimitry Andric                ? Instruction::And
448e8d8bef9SDimitry Andric                : (match(BOp, m_LogicalOr(m_Value(BOpOp0), m_Value(BOpOp1)))
449e8d8bef9SDimitry Andric                       ? Instruction::Or
450e8d8bef9SDimitry Andric                       : (Instruction::BinaryOps)0);
451e8d8bef9SDimitry Andric     if (InvertCond) {
452e8d8bef9SDimitry Andric       if (BOpc == Instruction::And)
453e8d8bef9SDimitry Andric         BOpc = Instruction::Or;
454e8d8bef9SDimitry Andric       else if (BOpc == Instruction::Or)
455e8d8bef9SDimitry Andric         BOpc = Instruction::And;
456e8d8bef9SDimitry Andric     }
457e8d8bef9SDimitry Andric   }
458e8d8bef9SDimitry Andric 
459e8d8bef9SDimitry Andric   // If this node is not part of the or/and tree, emit it as a branch.
460e8d8bef9SDimitry Andric   // Note that all nodes in the tree should have same opcode.
461e8d8bef9SDimitry Andric   bool BOpIsInOrAndTree = BOpc && BOpc == Opc && BOp->hasOneUse();
462e8d8bef9SDimitry Andric   if (!BOpIsInOrAndTree || BOp->getParent() != CurBB->getBasicBlock() ||
463e8d8bef9SDimitry Andric       !isValInBlock(BOpOp0, CurBB->getBasicBlock()) ||
464e8d8bef9SDimitry Andric       !isValInBlock(BOpOp1, CurBB->getBasicBlock())) {
465e8d8bef9SDimitry Andric     emitBranchForMergedCondition(Cond, TBB, FBB, CurBB, SwitchBB, TProb, FProb,
466e8d8bef9SDimitry Andric                                  InvertCond);
467e8d8bef9SDimitry Andric     return;
468e8d8bef9SDimitry Andric   }
469e8d8bef9SDimitry Andric 
470e8d8bef9SDimitry Andric   //  Create TmpBB after CurBB.
471e8d8bef9SDimitry Andric   MachineFunction::iterator BBI(CurBB);
472e8d8bef9SDimitry Andric   MachineBasicBlock *TmpBB =
473e8d8bef9SDimitry Andric       MF->CreateMachineBasicBlock(CurBB->getBasicBlock());
474e8d8bef9SDimitry Andric   CurBB->getParent()->insert(++BBI, TmpBB);
475e8d8bef9SDimitry Andric 
476e8d8bef9SDimitry Andric   if (Opc == Instruction::Or) {
477e8d8bef9SDimitry Andric     // Codegen X | Y as:
478e8d8bef9SDimitry Andric     // BB1:
479e8d8bef9SDimitry Andric     //   jmp_if_X TBB
480e8d8bef9SDimitry Andric     //   jmp TmpBB
481e8d8bef9SDimitry Andric     // TmpBB:
482e8d8bef9SDimitry Andric     //   jmp_if_Y TBB
483e8d8bef9SDimitry Andric     //   jmp FBB
484e8d8bef9SDimitry Andric     //
485e8d8bef9SDimitry Andric 
486e8d8bef9SDimitry Andric     // We have flexibility in setting Prob for BB1 and Prob for TmpBB.
487e8d8bef9SDimitry Andric     // The requirement is that
488e8d8bef9SDimitry Andric     //   TrueProb for BB1 + (FalseProb for BB1 * TrueProb for TmpBB)
489e8d8bef9SDimitry Andric     //     = TrueProb for original BB.
490e8d8bef9SDimitry Andric     // Assuming the original probabilities are A and B, one choice is to set
491e8d8bef9SDimitry Andric     // BB1's probabilities to A/2 and A/2+B, and set TmpBB's probabilities to
492e8d8bef9SDimitry Andric     // A/(1+B) and 2B/(1+B). This choice assumes that
493e8d8bef9SDimitry Andric     //   TrueProb for BB1 == FalseProb for BB1 * TrueProb for TmpBB.
494e8d8bef9SDimitry Andric     // Another choice is to assume TrueProb for BB1 equals to TrueProb for
495e8d8bef9SDimitry Andric     // TmpBB, but the math is more complicated.
496e8d8bef9SDimitry Andric 
497e8d8bef9SDimitry Andric     auto NewTrueProb = TProb / 2;
498e8d8bef9SDimitry Andric     auto NewFalseProb = TProb / 2 + FProb;
499e8d8bef9SDimitry Andric     // Emit the LHS condition.
500e8d8bef9SDimitry Andric     findMergedConditions(BOpOp0, TBB, TmpBB, CurBB, SwitchBB, Opc, NewTrueProb,
501e8d8bef9SDimitry Andric                          NewFalseProb, InvertCond);
502e8d8bef9SDimitry Andric 
503e8d8bef9SDimitry Andric     // Normalize A/2 and B to get A/(1+B) and 2B/(1+B).
504e8d8bef9SDimitry Andric     SmallVector<BranchProbability, 2> Probs{TProb / 2, FProb};
505e8d8bef9SDimitry Andric     BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
506e8d8bef9SDimitry Andric     // Emit the RHS condition into TmpBB.
507e8d8bef9SDimitry Andric     findMergedConditions(BOpOp1, TBB, FBB, TmpBB, SwitchBB, Opc, Probs[0],
508e8d8bef9SDimitry Andric                          Probs[1], InvertCond);
509e8d8bef9SDimitry Andric   } else {
510e8d8bef9SDimitry Andric     assert(Opc == Instruction::And && "Unknown merge op!");
511e8d8bef9SDimitry Andric     // Codegen X & Y as:
512e8d8bef9SDimitry Andric     // BB1:
513e8d8bef9SDimitry Andric     //   jmp_if_X TmpBB
514e8d8bef9SDimitry Andric     //   jmp FBB
515e8d8bef9SDimitry Andric     // TmpBB:
516e8d8bef9SDimitry Andric     //   jmp_if_Y TBB
517e8d8bef9SDimitry Andric     //   jmp FBB
518e8d8bef9SDimitry Andric     //
519e8d8bef9SDimitry Andric     //  This requires creation of TmpBB after CurBB.
520e8d8bef9SDimitry Andric 
521e8d8bef9SDimitry Andric     // We have flexibility in setting Prob for BB1 and Prob for TmpBB.
522e8d8bef9SDimitry Andric     // The requirement is that
523e8d8bef9SDimitry Andric     //   FalseProb for BB1 + (TrueProb for BB1 * FalseProb for TmpBB)
524e8d8bef9SDimitry Andric     //     = FalseProb for original BB.
525e8d8bef9SDimitry Andric     // Assuming the original probabilities are A and B, one choice is to set
526e8d8bef9SDimitry Andric     // BB1's probabilities to A+B/2 and B/2, and set TmpBB's probabilities to
527e8d8bef9SDimitry Andric     // 2A/(1+A) and B/(1+A). This choice assumes that FalseProb for BB1 ==
528e8d8bef9SDimitry Andric     // TrueProb for BB1 * FalseProb for TmpBB.
529e8d8bef9SDimitry Andric 
530e8d8bef9SDimitry Andric     auto NewTrueProb = TProb + FProb / 2;
531e8d8bef9SDimitry Andric     auto NewFalseProb = FProb / 2;
532e8d8bef9SDimitry Andric     // Emit the LHS condition.
533e8d8bef9SDimitry Andric     findMergedConditions(BOpOp0, TmpBB, FBB, CurBB, SwitchBB, Opc, NewTrueProb,
534e8d8bef9SDimitry Andric                          NewFalseProb, InvertCond);
535e8d8bef9SDimitry Andric 
536e8d8bef9SDimitry Andric     // Normalize A and B/2 to get 2A/(1+A) and B/(1+A).
537e8d8bef9SDimitry Andric     SmallVector<BranchProbability, 2> Probs{TProb, FProb / 2};
538e8d8bef9SDimitry Andric     BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
539e8d8bef9SDimitry Andric     // Emit the RHS condition into TmpBB.
540e8d8bef9SDimitry Andric     findMergedConditions(BOpOp1, TBB, FBB, TmpBB, SwitchBB, Opc, Probs[0],
541e8d8bef9SDimitry Andric                          Probs[1], InvertCond);
542e8d8bef9SDimitry Andric   }
543e8d8bef9SDimitry Andric }
544e8d8bef9SDimitry Andric 
shouldEmitAsBranches(const std::vector<SwitchCG::CaseBlock> & Cases)545e8d8bef9SDimitry Andric bool IRTranslator::shouldEmitAsBranches(
546e8d8bef9SDimitry Andric     const std::vector<SwitchCG::CaseBlock> &Cases) {
547e8d8bef9SDimitry Andric   // For multiple cases, it's better to emit as branches.
548e8d8bef9SDimitry Andric   if (Cases.size() != 2)
549e8d8bef9SDimitry Andric     return true;
550e8d8bef9SDimitry Andric 
551e8d8bef9SDimitry Andric   // If this is two comparisons of the same values or'd or and'd together, they
552e8d8bef9SDimitry Andric   // will get folded into a single comparison, so don't emit two blocks.
553e8d8bef9SDimitry Andric   if ((Cases[0].CmpLHS == Cases[1].CmpLHS &&
554e8d8bef9SDimitry Andric        Cases[0].CmpRHS == Cases[1].CmpRHS) ||
555e8d8bef9SDimitry Andric       (Cases[0].CmpRHS == Cases[1].CmpLHS &&
556e8d8bef9SDimitry Andric        Cases[0].CmpLHS == Cases[1].CmpRHS)) {
557e8d8bef9SDimitry Andric     return false;
558e8d8bef9SDimitry Andric   }
559e8d8bef9SDimitry Andric 
560e8d8bef9SDimitry Andric   // Handle: (X != null) | (Y != null) --> (X|Y) != 0
561e8d8bef9SDimitry Andric   // Handle: (X == null) & (Y == null) --> (X|Y) == 0
562e8d8bef9SDimitry Andric   if (Cases[0].CmpRHS == Cases[1].CmpRHS &&
563e8d8bef9SDimitry Andric       Cases[0].PredInfo.Pred == Cases[1].PredInfo.Pred &&
564e8d8bef9SDimitry Andric       isa<Constant>(Cases[0].CmpRHS) &&
565e8d8bef9SDimitry Andric       cast<Constant>(Cases[0].CmpRHS)->isNullValue()) {
566e8d8bef9SDimitry Andric     if (Cases[0].PredInfo.Pred == CmpInst::ICMP_EQ &&
567e8d8bef9SDimitry Andric         Cases[0].TrueBB == Cases[1].ThisBB)
568e8d8bef9SDimitry Andric       return false;
569e8d8bef9SDimitry Andric     if (Cases[0].PredInfo.Pred == CmpInst::ICMP_NE &&
570e8d8bef9SDimitry Andric         Cases[0].FalseBB == Cases[1].ThisBB)
571e8d8bef9SDimitry Andric       return false;
572e8d8bef9SDimitry Andric   }
573e8d8bef9SDimitry Andric 
574e8d8bef9SDimitry Andric   return true;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
translateBr(const User & U,MachineIRBuilder & MIRBuilder)5770b57cec5SDimitry Andric bool IRTranslator::translateBr(const User &U, MachineIRBuilder &MIRBuilder) {
5780b57cec5SDimitry Andric   const BranchInst &BrInst = cast<BranchInst>(U);
579e8d8bef9SDimitry Andric   auto &CurMBB = MIRBuilder.getMBB();
580e8d8bef9SDimitry Andric   auto *Succ0MBB = &getMBB(*BrInst.getSuccessor(0));
5810b57cec5SDimitry Andric 
582e8d8bef9SDimitry Andric   if (BrInst.isUnconditional()) {
5830b57cec5SDimitry Andric     // If the unconditional target is the layout successor, fallthrough.
5845f757f3fSDimitry Andric     if (OptLevel == CodeGenOptLevel::None ||
5855f757f3fSDimitry Andric         !CurMBB.isLayoutSuccessor(Succ0MBB))
586e8d8bef9SDimitry Andric       MIRBuilder.buildBr(*Succ0MBB);
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric     // Link successors.
5890b57cec5SDimitry Andric     for (const BasicBlock *Succ : successors(&BrInst))
590e8d8bef9SDimitry Andric       CurMBB.addSuccessor(&getMBB(*Succ));
591e8d8bef9SDimitry Andric     return true;
592e8d8bef9SDimitry Andric   }
593e8d8bef9SDimitry Andric 
594e8d8bef9SDimitry Andric   // If this condition is one of the special cases we handle, do special stuff
595e8d8bef9SDimitry Andric   // now.
596e8d8bef9SDimitry Andric   const Value *CondVal = BrInst.getCondition();
597e8d8bef9SDimitry Andric   MachineBasicBlock *Succ1MBB = &getMBB(*BrInst.getSuccessor(1));
598e8d8bef9SDimitry Andric 
599e8d8bef9SDimitry Andric   // If this is a series of conditions that are or'd or and'd together, emit
600e8d8bef9SDimitry Andric   // this as a sequence of branches instead of setcc's with and/or operations.
601e8d8bef9SDimitry Andric   // As long as jumps are not expensive (exceptions for multi-use logic ops,
602e8d8bef9SDimitry Andric   // unpredictable branches, and vector extracts because those jumps are likely
603e8d8bef9SDimitry Andric   // expensive for any target), this should improve performance.
604e8d8bef9SDimitry Andric   // For example, instead of something like:
605e8d8bef9SDimitry Andric   //     cmp A, B
606e8d8bef9SDimitry Andric   //     C = seteq
607e8d8bef9SDimitry Andric   //     cmp D, E
608e8d8bef9SDimitry Andric   //     F = setle
609e8d8bef9SDimitry Andric   //     or C, F
610e8d8bef9SDimitry Andric   //     jnz foo
611e8d8bef9SDimitry Andric   // Emit:
612e8d8bef9SDimitry Andric   //     cmp A, B
613e8d8bef9SDimitry Andric   //     je foo
614e8d8bef9SDimitry Andric   //     cmp D, E
615e8d8bef9SDimitry Andric   //     jle foo
616e8d8bef9SDimitry Andric   using namespace PatternMatch;
617e8d8bef9SDimitry Andric   const Instruction *CondI = dyn_cast<Instruction>(CondVal);
6180fca6ea1SDimitry Andric   if (!TLI->isJumpExpensive() && CondI && CondI->hasOneUse() &&
619e8d8bef9SDimitry Andric       !BrInst.hasMetadata(LLVMContext::MD_unpredictable)) {
620e8d8bef9SDimitry Andric     Instruction::BinaryOps Opcode = (Instruction::BinaryOps)0;
621e8d8bef9SDimitry Andric     Value *Vec;
622e8d8bef9SDimitry Andric     const Value *BOp0, *BOp1;
623e8d8bef9SDimitry Andric     if (match(CondI, m_LogicalAnd(m_Value(BOp0), m_Value(BOp1))))
624e8d8bef9SDimitry Andric       Opcode = Instruction::And;
625e8d8bef9SDimitry Andric     else if (match(CondI, m_LogicalOr(m_Value(BOp0), m_Value(BOp1))))
626e8d8bef9SDimitry Andric       Opcode = Instruction::Or;
627e8d8bef9SDimitry Andric 
628e8d8bef9SDimitry Andric     if (Opcode && !(match(BOp0, m_ExtractElt(m_Value(Vec), m_Value())) &&
629e8d8bef9SDimitry Andric                     match(BOp1, m_ExtractElt(m_Specific(Vec), m_Value())))) {
630e8d8bef9SDimitry Andric       findMergedConditions(CondI, Succ0MBB, Succ1MBB, &CurMBB, &CurMBB, Opcode,
631e8d8bef9SDimitry Andric                            getEdgeProbability(&CurMBB, Succ0MBB),
632e8d8bef9SDimitry Andric                            getEdgeProbability(&CurMBB, Succ1MBB),
633e8d8bef9SDimitry Andric                            /*InvertCond=*/false);
634e8d8bef9SDimitry Andric       assert(SL->SwitchCases[0].ThisBB == &CurMBB && "Unexpected lowering!");
635e8d8bef9SDimitry Andric 
636e8d8bef9SDimitry Andric       // Allow some cases to be rejected.
637e8d8bef9SDimitry Andric       if (shouldEmitAsBranches(SL->SwitchCases)) {
638e8d8bef9SDimitry Andric         // Emit the branch for this block.
639e8d8bef9SDimitry Andric         emitSwitchCase(SL->SwitchCases[0], &CurMBB, *CurBuilder);
640e8d8bef9SDimitry Andric         SL->SwitchCases.erase(SL->SwitchCases.begin());
641e8d8bef9SDimitry Andric         return true;
642e8d8bef9SDimitry Andric       }
643e8d8bef9SDimitry Andric 
644e8d8bef9SDimitry Andric       // Okay, we decided not to do this, remove any inserted MBB's and clear
645e8d8bef9SDimitry Andric       // SwitchCases.
646e8d8bef9SDimitry Andric       for (unsigned I = 1, E = SL->SwitchCases.size(); I != E; ++I)
647e8d8bef9SDimitry Andric         MF->erase(SL->SwitchCases[I].ThisBB);
648e8d8bef9SDimitry Andric 
649e8d8bef9SDimitry Andric       SL->SwitchCases.clear();
650e8d8bef9SDimitry Andric     }
651e8d8bef9SDimitry Andric   }
652e8d8bef9SDimitry Andric 
653e8d8bef9SDimitry Andric   // Create a CaseBlock record representing this branch.
654e8d8bef9SDimitry Andric   SwitchCG::CaseBlock CB(CmpInst::ICMP_EQ, false, CondVal,
655e8d8bef9SDimitry Andric                          ConstantInt::getTrue(MF->getFunction().getContext()),
656e8d8bef9SDimitry Andric                          nullptr, Succ0MBB, Succ1MBB, &CurMBB,
657e8d8bef9SDimitry Andric                          CurBuilder->getDebugLoc());
658e8d8bef9SDimitry Andric 
659e8d8bef9SDimitry Andric   // Use emitSwitchCase to actually insert the fast branch sequence for this
660e8d8bef9SDimitry Andric   // cond branch.
661e8d8bef9SDimitry Andric   emitSwitchCase(CB, &CurMBB, *CurBuilder);
6620b57cec5SDimitry Andric   return true;
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric 
addSuccessorWithProb(MachineBasicBlock * Src,MachineBasicBlock * Dst,BranchProbability Prob)6650b57cec5SDimitry Andric void IRTranslator::addSuccessorWithProb(MachineBasicBlock *Src,
6660b57cec5SDimitry Andric                                         MachineBasicBlock *Dst,
6670b57cec5SDimitry Andric                                         BranchProbability Prob) {
6680b57cec5SDimitry Andric   if (!FuncInfo.BPI) {
6690b57cec5SDimitry Andric     Src->addSuccessorWithoutProb(Dst);
6700b57cec5SDimitry Andric     return;
6710b57cec5SDimitry Andric   }
6720b57cec5SDimitry Andric   if (Prob.isUnknown())
6730b57cec5SDimitry Andric     Prob = getEdgeProbability(Src, Dst);
6740b57cec5SDimitry Andric   Src->addSuccessor(Dst, Prob);
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric BranchProbability
getEdgeProbability(const MachineBasicBlock * Src,const MachineBasicBlock * Dst) const6780b57cec5SDimitry Andric IRTranslator::getEdgeProbability(const MachineBasicBlock *Src,
6790b57cec5SDimitry Andric                                  const MachineBasicBlock *Dst) const {
6800b57cec5SDimitry Andric   const BasicBlock *SrcBB = Src->getBasicBlock();
6810b57cec5SDimitry Andric   const BasicBlock *DstBB = Dst->getBasicBlock();
6820b57cec5SDimitry Andric   if (!FuncInfo.BPI) {
6830b57cec5SDimitry Andric     // If BPI is not available, set the default probability as 1 / N, where N is
6840b57cec5SDimitry Andric     // the number of successors.
6850b57cec5SDimitry Andric     auto SuccSize = std::max<uint32_t>(succ_size(SrcBB), 1);
6860b57cec5SDimitry Andric     return BranchProbability(1, SuccSize);
6870b57cec5SDimitry Andric   }
6880b57cec5SDimitry Andric   return FuncInfo.BPI->getEdgeProbability(SrcBB, DstBB);
6890b57cec5SDimitry Andric }
6900b57cec5SDimitry Andric 
translateSwitch(const User & U,MachineIRBuilder & MIB)6910b57cec5SDimitry Andric bool IRTranslator::translateSwitch(const User &U, MachineIRBuilder &MIB) {
6920b57cec5SDimitry Andric   using namespace SwitchCG;
6930b57cec5SDimitry Andric   // Extract cases from the switch.
6940b57cec5SDimitry Andric   const SwitchInst &SI = cast<SwitchInst>(U);
6950b57cec5SDimitry Andric   BranchProbabilityInfo *BPI = FuncInfo.BPI;
6960b57cec5SDimitry Andric   CaseClusterVector Clusters;
6970b57cec5SDimitry Andric   Clusters.reserve(SI.getNumCases());
698fcaf7f86SDimitry Andric   for (const auto &I : SI.cases()) {
6990b57cec5SDimitry Andric     MachineBasicBlock *Succ = &getMBB(*I.getCaseSuccessor());
7000b57cec5SDimitry Andric     assert(Succ && "Could not find successor mbb in mapping");
7010b57cec5SDimitry Andric     const ConstantInt *CaseVal = I.getCaseValue();
7020b57cec5SDimitry Andric     BranchProbability Prob =
7030b57cec5SDimitry Andric         BPI ? BPI->getEdgeProbability(SI.getParent(), I.getSuccessorIndex())
7040b57cec5SDimitry Andric             : BranchProbability(1, SI.getNumCases() + 1);
7050b57cec5SDimitry Andric     Clusters.push_back(CaseCluster::range(CaseVal, CaseVal, Succ, Prob));
7060b57cec5SDimitry Andric   }
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   MachineBasicBlock *DefaultMBB = &getMBB(*SI.getDefaultDest());
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   // Cluster adjacent cases with the same destination. We do this at all
7110b57cec5SDimitry Andric   // optimization levels because it's cheap to do and will make codegen faster
7120b57cec5SDimitry Andric   // if there are many clusters.
7130b57cec5SDimitry Andric   sortAndRangeify(Clusters);
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   MachineBasicBlock *SwitchMBB = &getMBB(*SI.getParent());
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   // If there is only the default destination, jump there directly.
7180b57cec5SDimitry Andric   if (Clusters.empty()) {
7190b57cec5SDimitry Andric     SwitchMBB->addSuccessor(DefaultMBB);
7200b57cec5SDimitry Andric     if (DefaultMBB != SwitchMBB->getNextNode())
7210b57cec5SDimitry Andric       MIB.buildBr(*DefaultMBB);
7220b57cec5SDimitry Andric     return true;
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric 
7255f757f3fSDimitry Andric   SL->findJumpTables(Clusters, &SI, std::nullopt, DefaultMBB, nullptr, nullptr);
726e8d8bef9SDimitry Andric   SL->findBitTestClusters(Clusters, &SI);
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   LLVM_DEBUG({
7290b57cec5SDimitry Andric     dbgs() << "Case clusters: ";
7300b57cec5SDimitry Andric     for (const CaseCluster &C : Clusters) {
7310b57cec5SDimitry Andric       if (C.Kind == CC_JumpTable)
7320b57cec5SDimitry Andric         dbgs() << "JT:";
7330b57cec5SDimitry Andric       if (C.Kind == CC_BitTests)
7340b57cec5SDimitry Andric         dbgs() << "BT:";
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric       C.Low->getValue().print(dbgs(), true);
7370b57cec5SDimitry Andric       if (C.Low != C.High) {
7380b57cec5SDimitry Andric         dbgs() << '-';
7390b57cec5SDimitry Andric         C.High->getValue().print(dbgs(), true);
7400b57cec5SDimitry Andric       }
7410b57cec5SDimitry Andric       dbgs() << ' ';
7420b57cec5SDimitry Andric     }
7430b57cec5SDimitry Andric     dbgs() << '\n';
7440b57cec5SDimitry Andric   });
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   assert(!Clusters.empty());
7470b57cec5SDimitry Andric   SwitchWorkList WorkList;
7480b57cec5SDimitry Andric   CaseClusterIt First = Clusters.begin();
7490b57cec5SDimitry Andric   CaseClusterIt Last = Clusters.end() - 1;
7500b57cec5SDimitry Andric   auto DefaultProb = getEdgeProbability(SwitchMBB, DefaultMBB);
7510b57cec5SDimitry Andric   WorkList.push_back({SwitchMBB, First, Last, nullptr, nullptr, DefaultProb});
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   while (!WorkList.empty()) {
754349cc55cSDimitry Andric     SwitchWorkListItem W = WorkList.pop_back_val();
7551db9f3b2SDimitry Andric 
7561db9f3b2SDimitry Andric     unsigned NumClusters = W.LastCluster - W.FirstCluster + 1;
7571db9f3b2SDimitry Andric     // For optimized builds, lower large range as a balanced binary tree.
7581db9f3b2SDimitry Andric     if (NumClusters > 3 &&
7591db9f3b2SDimitry Andric         MF->getTarget().getOptLevel() != CodeGenOptLevel::None &&
7601db9f3b2SDimitry Andric         !DefaultMBB->getParent()->getFunction().hasMinSize()) {
7611db9f3b2SDimitry Andric       splitWorkItem(WorkList, W, SI.getCondition(), SwitchMBB, MIB);
7621db9f3b2SDimitry Andric       continue;
7631db9f3b2SDimitry Andric     }
7641db9f3b2SDimitry Andric 
7650b57cec5SDimitry Andric     if (!lowerSwitchWorkItem(W, SI.getCondition(), SwitchMBB, DefaultMBB, MIB))
7660b57cec5SDimitry Andric       return false;
7670b57cec5SDimitry Andric   }
7680b57cec5SDimitry Andric   return true;
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric 
splitWorkItem(SwitchCG::SwitchWorkList & WorkList,const SwitchCG::SwitchWorkListItem & W,Value * Cond,MachineBasicBlock * SwitchMBB,MachineIRBuilder & MIB)7711db9f3b2SDimitry Andric void IRTranslator::splitWorkItem(SwitchCG::SwitchWorkList &WorkList,
7721db9f3b2SDimitry Andric                                  const SwitchCG::SwitchWorkListItem &W,
7731db9f3b2SDimitry Andric                                  Value *Cond, MachineBasicBlock *SwitchMBB,
7741db9f3b2SDimitry Andric                                  MachineIRBuilder &MIB) {
7751db9f3b2SDimitry Andric   using namespace SwitchCG;
7761db9f3b2SDimitry Andric   assert(W.FirstCluster->Low->getValue().slt(W.LastCluster->Low->getValue()) &&
7771db9f3b2SDimitry Andric          "Clusters not sorted?");
7781db9f3b2SDimitry Andric   assert(W.LastCluster - W.FirstCluster + 1 >= 2 && "Too small to split!");
7791db9f3b2SDimitry Andric 
7801db9f3b2SDimitry Andric   auto [LastLeft, FirstRight, LeftProb, RightProb] =
7811db9f3b2SDimitry Andric       SL->computeSplitWorkItemInfo(W);
7821db9f3b2SDimitry Andric 
7831db9f3b2SDimitry Andric   // Use the first element on the right as pivot since we will make less-than
7841db9f3b2SDimitry Andric   // comparisons against it.
7851db9f3b2SDimitry Andric   CaseClusterIt PivotCluster = FirstRight;
7861db9f3b2SDimitry Andric   assert(PivotCluster > W.FirstCluster);
7871db9f3b2SDimitry Andric   assert(PivotCluster <= W.LastCluster);
7881db9f3b2SDimitry Andric 
7891db9f3b2SDimitry Andric   CaseClusterIt FirstLeft = W.FirstCluster;
7901db9f3b2SDimitry Andric   CaseClusterIt LastRight = W.LastCluster;
7911db9f3b2SDimitry Andric 
7921db9f3b2SDimitry Andric   const ConstantInt *Pivot = PivotCluster->Low;
7931db9f3b2SDimitry Andric 
7941db9f3b2SDimitry Andric   // New blocks will be inserted immediately after the current one.
7951db9f3b2SDimitry Andric   MachineFunction::iterator BBI(W.MBB);
7961db9f3b2SDimitry Andric   ++BBI;
7971db9f3b2SDimitry Andric 
7981db9f3b2SDimitry Andric   // We will branch to the LHS if Value < Pivot. If LHS is a single cluster,
7991db9f3b2SDimitry Andric   // we can branch to its destination directly if it's squeezed exactly in
8001db9f3b2SDimitry Andric   // between the known lower bound and Pivot - 1.
8011db9f3b2SDimitry Andric   MachineBasicBlock *LeftMBB;
8021db9f3b2SDimitry Andric   if (FirstLeft == LastLeft && FirstLeft->Kind == CC_Range &&
8031db9f3b2SDimitry Andric       FirstLeft->Low == W.GE &&
8041db9f3b2SDimitry Andric       (FirstLeft->High->getValue() + 1LL) == Pivot->getValue()) {
8051db9f3b2SDimitry Andric     LeftMBB = FirstLeft->MBB;
8061db9f3b2SDimitry Andric   } else {
8071db9f3b2SDimitry Andric     LeftMBB = FuncInfo.MF->CreateMachineBasicBlock(W.MBB->getBasicBlock());
8081db9f3b2SDimitry Andric     FuncInfo.MF->insert(BBI, LeftMBB);
8091db9f3b2SDimitry Andric     WorkList.push_back(
8101db9f3b2SDimitry Andric         {LeftMBB, FirstLeft, LastLeft, W.GE, Pivot, W.DefaultProb / 2});
8111db9f3b2SDimitry Andric   }
8121db9f3b2SDimitry Andric 
8131db9f3b2SDimitry Andric   // Similarly, we will branch to the RHS if Value >= Pivot. If RHS is a
8141db9f3b2SDimitry Andric   // single cluster, RHS.Low == Pivot, and we can branch to its destination
8151db9f3b2SDimitry Andric   // directly if RHS.High equals the current upper bound.
8161db9f3b2SDimitry Andric   MachineBasicBlock *RightMBB;
8171db9f3b2SDimitry Andric   if (FirstRight == LastRight && FirstRight->Kind == CC_Range && W.LT &&
8181db9f3b2SDimitry Andric       (FirstRight->High->getValue() + 1ULL) == W.LT->getValue()) {
8191db9f3b2SDimitry Andric     RightMBB = FirstRight->MBB;
8201db9f3b2SDimitry Andric   } else {
8211db9f3b2SDimitry Andric     RightMBB = FuncInfo.MF->CreateMachineBasicBlock(W.MBB->getBasicBlock());
8221db9f3b2SDimitry Andric     FuncInfo.MF->insert(BBI, RightMBB);
8231db9f3b2SDimitry Andric     WorkList.push_back(
8241db9f3b2SDimitry Andric         {RightMBB, FirstRight, LastRight, Pivot, W.LT, W.DefaultProb / 2});
8251db9f3b2SDimitry Andric   }
8261db9f3b2SDimitry Andric 
8271db9f3b2SDimitry Andric   // Create the CaseBlock record that will be used to lower the branch.
8281db9f3b2SDimitry Andric   CaseBlock CB(ICmpInst::Predicate::ICMP_SLT, false, Cond, Pivot, nullptr,
8291db9f3b2SDimitry Andric                LeftMBB, RightMBB, W.MBB, MIB.getDebugLoc(), LeftProb,
8301db9f3b2SDimitry Andric                RightProb);
8311db9f3b2SDimitry Andric 
8321db9f3b2SDimitry Andric   if (W.MBB == SwitchMBB)
8331db9f3b2SDimitry Andric     emitSwitchCase(CB, SwitchMBB, MIB);
8341db9f3b2SDimitry Andric   else
8351db9f3b2SDimitry Andric     SL->SwitchCases.push_back(CB);
8361db9f3b2SDimitry Andric }
8371db9f3b2SDimitry Andric 
emitJumpTable(SwitchCG::JumpTable & JT,MachineBasicBlock * MBB)8380b57cec5SDimitry Andric void IRTranslator::emitJumpTable(SwitchCG::JumpTable &JT,
8390b57cec5SDimitry Andric                                  MachineBasicBlock *MBB) {
8400b57cec5SDimitry Andric   // Emit the code for the jump table
8410b57cec5SDimitry Andric   assert(JT.Reg != -1U && "Should lower JT Header first!");
8420b57cec5SDimitry Andric   MachineIRBuilder MIB(*MBB->getParent());
8430b57cec5SDimitry Andric   MIB.setMBB(*MBB);
8440b57cec5SDimitry Andric   MIB.setDebugLoc(CurBuilder->getDebugLoc());
8450b57cec5SDimitry Andric 
8465f757f3fSDimitry Andric   Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
8470b57cec5SDimitry Andric   const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   auto Table = MIB.buildJumpTable(PtrTy, JT.JTI);
8500b57cec5SDimitry Andric   MIB.buildBrJT(Table.getReg(0), JT.JTI, JT.Reg);
8510b57cec5SDimitry Andric }
8520b57cec5SDimitry Andric 
emitJumpTableHeader(SwitchCG::JumpTable & JT,SwitchCG::JumpTableHeader & JTH,MachineBasicBlock * HeaderBB)8530b57cec5SDimitry Andric bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
8540b57cec5SDimitry Andric                                        SwitchCG::JumpTableHeader &JTH,
8550b57cec5SDimitry Andric                                        MachineBasicBlock *HeaderBB) {
8560b57cec5SDimitry Andric   MachineIRBuilder MIB(*HeaderBB->getParent());
8570b57cec5SDimitry Andric   MIB.setMBB(*HeaderBB);
8580b57cec5SDimitry Andric   MIB.setDebugLoc(CurBuilder->getDebugLoc());
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   const Value &SValue = *JTH.SValue;
8610b57cec5SDimitry Andric   // Subtract the lowest switch case value from the value being switched on.
8620b57cec5SDimitry Andric   const LLT SwitchTy = getLLTForType(*SValue.getType(), *DL);
8630b57cec5SDimitry Andric   Register SwitchOpReg = getOrCreateVReg(SValue);
8640b57cec5SDimitry Andric   auto FirstCst = MIB.buildConstant(SwitchTy, JTH.First);
8650b57cec5SDimitry Andric   auto Sub = MIB.buildSub({SwitchTy}, SwitchOpReg, FirstCst);
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric   // This value may be smaller or larger than the target's pointer type, and
8680b57cec5SDimitry Andric   // therefore require extension or truncating.
8695f757f3fSDimitry Andric   auto *PtrIRTy = PointerType::getUnqual(SValue.getContext());
8700b57cec5SDimitry Andric   const LLT PtrScalarTy = LLT::scalar(DL->getTypeSizeInBits(PtrIRTy));
8710b57cec5SDimitry Andric   Sub = MIB.buildZExtOrTrunc(PtrScalarTy, Sub);
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   JT.Reg = Sub.getReg(0);
8740b57cec5SDimitry Andric 
875349cc55cSDimitry Andric   if (JTH.FallthroughUnreachable) {
8760b57cec5SDimitry Andric     if (JT.MBB != HeaderBB->getNextNode())
8770b57cec5SDimitry Andric       MIB.buildBr(*JT.MBB);
8780b57cec5SDimitry Andric     return true;
8790b57cec5SDimitry Andric   }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric   // Emit the range check for the jump table, and branch to the default block
8820b57cec5SDimitry Andric   // for the switch statement if the value being switched on exceeds the
8830b57cec5SDimitry Andric   // largest case in the switch.
8840b57cec5SDimitry Andric   auto Cst = getOrCreateVReg(
8850b57cec5SDimitry Andric       *ConstantInt::get(SValue.getType(), JTH.Last - JTH.First));
8860b57cec5SDimitry Andric   Cst = MIB.buildZExtOrTrunc(PtrScalarTy, Cst).getReg(0);
8870b57cec5SDimitry Andric   auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::scalar(1), Sub, Cst);
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   auto BrCond = MIB.buildBrCond(Cmp.getReg(0), *JT.Default);
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric   // Avoid emitting unnecessary branches to the next block.
8920b57cec5SDimitry Andric   if (JT.MBB != HeaderBB->getNextNode())
8930b57cec5SDimitry Andric     BrCond = MIB.buildBr(*JT.MBB);
8940b57cec5SDimitry Andric   return true;
8950b57cec5SDimitry Andric }
8960b57cec5SDimitry Andric 
emitSwitchCase(SwitchCG::CaseBlock & CB,MachineBasicBlock * SwitchBB,MachineIRBuilder & MIB)8970b57cec5SDimitry Andric void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
8980b57cec5SDimitry Andric                                   MachineBasicBlock *SwitchBB,
8990b57cec5SDimitry Andric                                   MachineIRBuilder &MIB) {
9000b57cec5SDimitry Andric   Register CondLHS = getOrCreateVReg(*CB.CmpLHS);
9010b57cec5SDimitry Andric   Register Cond;
9020b57cec5SDimitry Andric   DebugLoc OldDbgLoc = MIB.getDebugLoc();
9030b57cec5SDimitry Andric   MIB.setDebugLoc(CB.DbgLoc);
9040b57cec5SDimitry Andric   MIB.setMBB(*CB.ThisBB);
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   if (CB.PredInfo.NoCmp) {
9070b57cec5SDimitry Andric     // Branch or fall through to TrueBB.
9080b57cec5SDimitry Andric     addSuccessorWithProb(CB.ThisBB, CB.TrueBB, CB.TrueProb);
9090b57cec5SDimitry Andric     addMachineCFGPred({SwitchBB->getBasicBlock(), CB.TrueBB->getBasicBlock()},
9100b57cec5SDimitry Andric                       CB.ThisBB);
9110b57cec5SDimitry Andric     CB.ThisBB->normalizeSuccProbs();
9120b57cec5SDimitry Andric     if (CB.TrueBB != CB.ThisBB->getNextNode())
9130b57cec5SDimitry Andric       MIB.buildBr(*CB.TrueBB);
9140b57cec5SDimitry Andric     MIB.setDebugLoc(OldDbgLoc);
9150b57cec5SDimitry Andric     return;
9160b57cec5SDimitry Andric   }
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   const LLT i1Ty = LLT::scalar(1);
9190b57cec5SDimitry Andric   // Build the compare.
9200b57cec5SDimitry Andric   if (!CB.CmpMHS) {
921e8d8bef9SDimitry Andric     const auto *CI = dyn_cast<ConstantInt>(CB.CmpRHS);
922e8d8bef9SDimitry Andric     // For conditional branch lowering, we might try to do something silly like
923e8d8bef9SDimitry Andric     // emit an G_ICMP to compare an existing G_ICMP i1 result with true. If so,
924e8d8bef9SDimitry Andric     // just re-use the existing condition vreg.
92506c3fb27SDimitry Andric     if (MRI->getType(CondLHS).getSizeInBits() == 1 && CI && CI->isOne() &&
92606c3fb27SDimitry Andric         CB.PredInfo.Pred == CmpInst::ICMP_EQ) {
927e8d8bef9SDimitry Andric       Cond = CondLHS;
928e8d8bef9SDimitry Andric     } else {
9290b57cec5SDimitry Andric       Register CondRHS = getOrCreateVReg(*CB.CmpRHS);
930e8d8bef9SDimitry Andric       if (CmpInst::isFPPredicate(CB.PredInfo.Pred))
931e8d8bef9SDimitry Andric         Cond =
932e8d8bef9SDimitry Andric             MIB.buildFCmp(CB.PredInfo.Pred, i1Ty, CondLHS, CondRHS).getReg(0);
933e8d8bef9SDimitry Andric       else
934e8d8bef9SDimitry Andric         Cond =
935e8d8bef9SDimitry Andric             MIB.buildICmp(CB.PredInfo.Pred, i1Ty, CondLHS, CondRHS).getReg(0);
936e8d8bef9SDimitry Andric     }
9370b57cec5SDimitry Andric   } else {
938c14a5a88SDimitry Andric     assert(CB.PredInfo.Pred == CmpInst::ICMP_SLE &&
939c14a5a88SDimitry Andric            "Can only handle SLE ranges");
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric     const APInt& Low = cast<ConstantInt>(CB.CmpLHS)->getValue();
9420b57cec5SDimitry Andric     const APInt& High = cast<ConstantInt>(CB.CmpRHS)->getValue();
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric     Register CmpOpReg = getOrCreateVReg(*CB.CmpMHS);
9450b57cec5SDimitry Andric     if (cast<ConstantInt>(CB.CmpLHS)->isMinValue(true)) {
9460b57cec5SDimitry Andric       Register CondRHS = getOrCreateVReg(*CB.CmpRHS);
9470b57cec5SDimitry Andric       Cond =
948c14a5a88SDimitry Andric           MIB.buildICmp(CmpInst::ICMP_SLE, i1Ty, CmpOpReg, CondRHS).getReg(0);
9490b57cec5SDimitry Andric     } else {
9505ffd83dbSDimitry Andric       const LLT CmpTy = MRI->getType(CmpOpReg);
9510b57cec5SDimitry Andric       auto Sub = MIB.buildSub({CmpTy}, CmpOpReg, CondLHS);
9520b57cec5SDimitry Andric       auto Diff = MIB.buildConstant(CmpTy, High - Low);
9530b57cec5SDimitry Andric       Cond = MIB.buildICmp(CmpInst::ICMP_ULE, i1Ty, Sub, Diff).getReg(0);
9540b57cec5SDimitry Andric     }
9550b57cec5SDimitry Andric   }
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   // Update successor info
9580b57cec5SDimitry Andric   addSuccessorWithProb(CB.ThisBB, CB.TrueBB, CB.TrueProb);
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   addMachineCFGPred({SwitchBB->getBasicBlock(), CB.TrueBB->getBasicBlock()},
9610b57cec5SDimitry Andric                     CB.ThisBB);
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   // TrueBB and FalseBB are always different unless the incoming IR is
9640b57cec5SDimitry Andric   // degenerate. This only happens when running llc on weird IR.
9650b57cec5SDimitry Andric   if (CB.TrueBB != CB.FalseBB)
9660b57cec5SDimitry Andric     addSuccessorWithProb(CB.ThisBB, CB.FalseBB, CB.FalseProb);
9670b57cec5SDimitry Andric   CB.ThisBB->normalizeSuccProbs();
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   addMachineCFGPred({SwitchBB->getBasicBlock(), CB.FalseBB->getBasicBlock()},
9700b57cec5SDimitry Andric                     CB.ThisBB);
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   MIB.buildBrCond(Cond, *CB.TrueBB);
9730b57cec5SDimitry Andric   MIB.buildBr(*CB.FalseBB);
9740b57cec5SDimitry Andric   MIB.setDebugLoc(OldDbgLoc);
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric 
lowerJumpTableWorkItem(SwitchCG::SwitchWorkListItem W,MachineBasicBlock * SwitchMBB,MachineBasicBlock * CurMBB,MachineBasicBlock * DefaultMBB,MachineIRBuilder & MIB,MachineFunction::iterator BBI,BranchProbability UnhandledProbs,SwitchCG::CaseClusterIt I,MachineBasicBlock * Fallthrough,bool FallthroughUnreachable)9770b57cec5SDimitry Andric bool IRTranslator::lowerJumpTableWorkItem(SwitchCG::SwitchWorkListItem W,
9780b57cec5SDimitry Andric                                           MachineBasicBlock *SwitchMBB,
9790b57cec5SDimitry Andric                                           MachineBasicBlock *CurMBB,
9800b57cec5SDimitry Andric                                           MachineBasicBlock *DefaultMBB,
9810b57cec5SDimitry Andric                                           MachineIRBuilder &MIB,
9820b57cec5SDimitry Andric                                           MachineFunction::iterator BBI,
9830b57cec5SDimitry Andric                                           BranchProbability UnhandledProbs,
9840b57cec5SDimitry Andric                                           SwitchCG::CaseClusterIt I,
9850b57cec5SDimitry Andric                                           MachineBasicBlock *Fallthrough,
9860b57cec5SDimitry Andric                                           bool FallthroughUnreachable) {
9870b57cec5SDimitry Andric   using namespace SwitchCG;
9880b57cec5SDimitry Andric   MachineFunction *CurMF = SwitchMBB->getParent();
9890b57cec5SDimitry Andric   // FIXME: Optimize away range check based on pivot comparisons.
9900b57cec5SDimitry Andric   JumpTableHeader *JTH = &SL->JTCases[I->JTCasesIndex].first;
9910b57cec5SDimitry Andric   SwitchCG::JumpTable *JT = &SL->JTCases[I->JTCasesIndex].second;
9920b57cec5SDimitry Andric   BranchProbability DefaultProb = W.DefaultProb;
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric   // The jump block hasn't been inserted yet; insert it here.
9950b57cec5SDimitry Andric   MachineBasicBlock *JumpMBB = JT->MBB;
9960b57cec5SDimitry Andric   CurMF->insert(BBI, JumpMBB);
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric   // Since the jump table block is separate from the switch block, we need
9990b57cec5SDimitry Andric   // to keep track of it as a machine predecessor to the default block,
10000b57cec5SDimitry Andric   // otherwise we lose the phi edges.
10010b57cec5SDimitry Andric   addMachineCFGPred({SwitchMBB->getBasicBlock(), DefaultMBB->getBasicBlock()},
10020b57cec5SDimitry Andric                     CurMBB);
10030b57cec5SDimitry Andric   addMachineCFGPred({SwitchMBB->getBasicBlock(), DefaultMBB->getBasicBlock()},
10040b57cec5SDimitry Andric                     JumpMBB);
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   auto JumpProb = I->Prob;
10070b57cec5SDimitry Andric   auto FallthroughProb = UnhandledProbs;
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   // If the default statement is a target of the jump table, we evenly
10100b57cec5SDimitry Andric   // distribute the default probability to successors of CurMBB. Also
10110b57cec5SDimitry Andric   // update the probability on the edge from JumpMBB to Fallthrough.
10120b57cec5SDimitry Andric   for (MachineBasicBlock::succ_iterator SI = JumpMBB->succ_begin(),
10130b57cec5SDimitry Andric                                         SE = JumpMBB->succ_end();
10140b57cec5SDimitry Andric        SI != SE; ++SI) {
10150b57cec5SDimitry Andric     if (*SI == DefaultMBB) {
10160b57cec5SDimitry Andric       JumpProb += DefaultProb / 2;
10170b57cec5SDimitry Andric       FallthroughProb -= DefaultProb / 2;
10180b57cec5SDimitry Andric       JumpMBB->setSuccProbability(SI, DefaultProb / 2);
10190b57cec5SDimitry Andric       JumpMBB->normalizeSuccProbs();
10200b57cec5SDimitry Andric     } else {
10210b57cec5SDimitry Andric       // Also record edges from the jump table block to it's successors.
10220b57cec5SDimitry Andric       addMachineCFGPred({SwitchMBB->getBasicBlock(), (*SI)->getBasicBlock()},
10230b57cec5SDimitry Andric                         JumpMBB);
10240b57cec5SDimitry Andric     }
10250b57cec5SDimitry Andric   }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   if (FallthroughUnreachable)
1028349cc55cSDimitry Andric     JTH->FallthroughUnreachable = true;
10290b57cec5SDimitry Andric 
1030349cc55cSDimitry Andric   if (!JTH->FallthroughUnreachable)
10310b57cec5SDimitry Andric     addSuccessorWithProb(CurMBB, Fallthrough, FallthroughProb);
10320b57cec5SDimitry Andric   addSuccessorWithProb(CurMBB, JumpMBB, JumpProb);
10330b57cec5SDimitry Andric   CurMBB->normalizeSuccProbs();
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   // The jump table header will be inserted in our current block, do the
10360b57cec5SDimitry Andric   // range check, and fall through to our fallthrough block.
10370b57cec5SDimitry Andric   JTH->HeaderBB = CurMBB;
10380b57cec5SDimitry Andric   JT->Default = Fallthrough; // FIXME: Move Default to JumpTableHeader.
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   // If we're in the right place, emit the jump table header right now.
10410b57cec5SDimitry Andric   if (CurMBB == SwitchMBB) {
10420b57cec5SDimitry Andric     if (!emitJumpTableHeader(*JT, *JTH, CurMBB))
10430b57cec5SDimitry Andric       return false;
10440b57cec5SDimitry Andric     JTH->Emitted = true;
10450b57cec5SDimitry Andric   }
10460b57cec5SDimitry Andric   return true;
10470b57cec5SDimitry Andric }
lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I,Value * Cond,MachineBasicBlock * Fallthrough,bool FallthroughUnreachable,BranchProbability UnhandledProbs,MachineBasicBlock * CurMBB,MachineIRBuilder & MIB,MachineBasicBlock * SwitchMBB)10480b57cec5SDimitry Andric bool IRTranslator::lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I,
10490b57cec5SDimitry Andric                                             Value *Cond,
10500b57cec5SDimitry Andric                                             MachineBasicBlock *Fallthrough,
10510b57cec5SDimitry Andric                                             bool FallthroughUnreachable,
10520b57cec5SDimitry Andric                                             BranchProbability UnhandledProbs,
10530b57cec5SDimitry Andric                                             MachineBasicBlock *CurMBB,
10540b57cec5SDimitry Andric                                             MachineIRBuilder &MIB,
10550b57cec5SDimitry Andric                                             MachineBasicBlock *SwitchMBB) {
10560b57cec5SDimitry Andric   using namespace SwitchCG;
10570b57cec5SDimitry Andric   const Value *RHS, *LHS, *MHS;
10580b57cec5SDimitry Andric   CmpInst::Predicate Pred;
10590b57cec5SDimitry Andric   if (I->Low == I->High) {
10600b57cec5SDimitry Andric     // Check Cond == I->Low.
10610b57cec5SDimitry Andric     Pred = CmpInst::ICMP_EQ;
10620b57cec5SDimitry Andric     LHS = Cond;
10630b57cec5SDimitry Andric     RHS = I->Low;
10640b57cec5SDimitry Andric     MHS = nullptr;
10650b57cec5SDimitry Andric   } else {
10660b57cec5SDimitry Andric     // Check I->Low <= Cond <= I->High.
1067c14a5a88SDimitry Andric     Pred = CmpInst::ICMP_SLE;
10680b57cec5SDimitry Andric     LHS = I->Low;
10690b57cec5SDimitry Andric     MHS = Cond;
10700b57cec5SDimitry Andric     RHS = I->High;
10710b57cec5SDimitry Andric   }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   // If Fallthrough is unreachable, fold away the comparison.
10740b57cec5SDimitry Andric   // The false probability is the sum of all unhandled cases.
10750b57cec5SDimitry Andric   CaseBlock CB(Pred, FallthroughUnreachable, LHS, RHS, MHS, I->MBB, Fallthrough,
10760b57cec5SDimitry Andric                CurMBB, MIB.getDebugLoc(), I->Prob, UnhandledProbs);
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   emitSwitchCase(CB, SwitchMBB, MIB);
10790b57cec5SDimitry Andric   return true;
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric 
emitBitTestHeader(SwitchCG::BitTestBlock & B,MachineBasicBlock * SwitchBB)1082e8d8bef9SDimitry Andric void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
1083e8d8bef9SDimitry Andric                                      MachineBasicBlock *SwitchBB) {
1084e8d8bef9SDimitry Andric   MachineIRBuilder &MIB = *CurBuilder;
1085e8d8bef9SDimitry Andric   MIB.setMBB(*SwitchBB);
1086e8d8bef9SDimitry Andric 
1087e8d8bef9SDimitry Andric   // Subtract the minimum value.
1088e8d8bef9SDimitry Andric   Register SwitchOpReg = getOrCreateVReg(*B.SValue);
1089e8d8bef9SDimitry Andric 
1090e8d8bef9SDimitry Andric   LLT SwitchOpTy = MRI->getType(SwitchOpReg);
1091e8d8bef9SDimitry Andric   Register MinValReg = MIB.buildConstant(SwitchOpTy, B.First).getReg(0);
1092e8d8bef9SDimitry Andric   auto RangeSub = MIB.buildSub(SwitchOpTy, SwitchOpReg, MinValReg);
1093e8d8bef9SDimitry Andric 
10945f757f3fSDimitry Andric   Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
1095349cc55cSDimitry Andric   const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
1096349cc55cSDimitry Andric 
1097e8d8bef9SDimitry Andric   LLT MaskTy = SwitchOpTy;
1098349cc55cSDimitry Andric   if (MaskTy.getSizeInBits() > PtrTy.getSizeInBits() ||
109906c3fb27SDimitry Andric       !llvm::has_single_bit<uint32_t>(MaskTy.getSizeInBits()))
1100349cc55cSDimitry Andric     MaskTy = LLT::scalar(PtrTy.getSizeInBits());
1101349cc55cSDimitry Andric   else {
1102349cc55cSDimitry Andric     // Ensure that the type will fit the mask value.
1103e8d8bef9SDimitry Andric     for (unsigned I = 0, E = B.Cases.size(); I != E; ++I) {
1104e8d8bef9SDimitry Andric       if (!isUIntN(SwitchOpTy.getSizeInBits(), B.Cases[I].Mask)) {
1105e8d8bef9SDimitry Andric         // Switch table case range are encoded into series of masks.
1106e8d8bef9SDimitry Andric         // Just use pointer type, it's guaranteed to fit.
1107349cc55cSDimitry Andric         MaskTy = LLT::scalar(PtrTy.getSizeInBits());
1108e8d8bef9SDimitry Andric         break;
1109e8d8bef9SDimitry Andric       }
1110e8d8bef9SDimitry Andric     }
1111349cc55cSDimitry Andric   }
1112e8d8bef9SDimitry Andric   Register SubReg = RangeSub.getReg(0);
1113e8d8bef9SDimitry Andric   if (SwitchOpTy != MaskTy)
1114e8d8bef9SDimitry Andric     SubReg = MIB.buildZExtOrTrunc(MaskTy, SubReg).getReg(0);
1115e8d8bef9SDimitry Andric 
1116e8d8bef9SDimitry Andric   B.RegVT = getMVTForLLT(MaskTy);
1117e8d8bef9SDimitry Andric   B.Reg = SubReg;
1118e8d8bef9SDimitry Andric 
1119e8d8bef9SDimitry Andric   MachineBasicBlock *MBB = B.Cases[0].ThisBB;
1120e8d8bef9SDimitry Andric 
1121349cc55cSDimitry Andric   if (!B.FallthroughUnreachable)
1122e8d8bef9SDimitry Andric     addSuccessorWithProb(SwitchBB, B.Default, B.DefaultProb);
1123e8d8bef9SDimitry Andric   addSuccessorWithProb(SwitchBB, MBB, B.Prob);
1124e8d8bef9SDimitry Andric 
1125e8d8bef9SDimitry Andric   SwitchBB->normalizeSuccProbs();
1126e8d8bef9SDimitry Andric 
1127349cc55cSDimitry Andric   if (!B.FallthroughUnreachable) {
1128e8d8bef9SDimitry Andric     // Conditional branch to the default block.
1129e8d8bef9SDimitry Andric     auto RangeCst = MIB.buildConstant(SwitchOpTy, B.Range);
1130e8d8bef9SDimitry Andric     auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::scalar(1),
1131e8d8bef9SDimitry Andric                                   RangeSub, RangeCst);
1132e8d8bef9SDimitry Andric     MIB.buildBrCond(RangeCmp, *B.Default);
1133e8d8bef9SDimitry Andric   }
1134e8d8bef9SDimitry Andric 
1135e8d8bef9SDimitry Andric   // Avoid emitting unnecessary branches to the next block.
1136e8d8bef9SDimitry Andric   if (MBB != SwitchBB->getNextNode())
1137e8d8bef9SDimitry Andric     MIB.buildBr(*MBB);
1138e8d8bef9SDimitry Andric }
1139e8d8bef9SDimitry Andric 
emitBitTestCase(SwitchCG::BitTestBlock & BB,MachineBasicBlock * NextMBB,BranchProbability BranchProbToNext,Register Reg,SwitchCG::BitTestCase & B,MachineBasicBlock * SwitchBB)1140e8d8bef9SDimitry Andric void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
1141e8d8bef9SDimitry Andric                                    MachineBasicBlock *NextMBB,
1142e8d8bef9SDimitry Andric                                    BranchProbability BranchProbToNext,
1143e8d8bef9SDimitry Andric                                    Register Reg, SwitchCG::BitTestCase &B,
1144e8d8bef9SDimitry Andric                                    MachineBasicBlock *SwitchBB) {
1145e8d8bef9SDimitry Andric   MachineIRBuilder &MIB = *CurBuilder;
1146e8d8bef9SDimitry Andric   MIB.setMBB(*SwitchBB);
1147e8d8bef9SDimitry Andric 
1148e8d8bef9SDimitry Andric   LLT SwitchTy = getLLTForMVT(BB.RegVT);
1149e8d8bef9SDimitry Andric   Register Cmp;
1150bdd1243dSDimitry Andric   unsigned PopCount = llvm::popcount(B.Mask);
1151e8d8bef9SDimitry Andric   if (PopCount == 1) {
1152e8d8bef9SDimitry Andric     // Testing for a single bit; just compare the shift count with what it
1153e8d8bef9SDimitry Andric     // would need to be to shift a 1 bit in that position.
1154e8d8bef9SDimitry Andric     auto MaskTrailingZeros =
115506c3fb27SDimitry Andric         MIB.buildConstant(SwitchTy, llvm::countr_zero(B.Mask));
1156e8d8bef9SDimitry Andric     Cmp =
1157e8d8bef9SDimitry Andric         MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::scalar(1), Reg, MaskTrailingZeros)
1158e8d8bef9SDimitry Andric             .getReg(0);
1159e8d8bef9SDimitry Andric   } else if (PopCount == BB.Range) {
1160e8d8bef9SDimitry Andric     // There is only one zero bit in the range, test for it directly.
1161e8d8bef9SDimitry Andric     auto MaskTrailingOnes =
116206c3fb27SDimitry Andric         MIB.buildConstant(SwitchTy, llvm::countr_one(B.Mask));
1163e8d8bef9SDimitry Andric     Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Reg, MaskTrailingOnes)
1164e8d8bef9SDimitry Andric               .getReg(0);
1165e8d8bef9SDimitry Andric   } else {
1166e8d8bef9SDimitry Andric     // Make desired shift.
1167e8d8bef9SDimitry Andric     auto CstOne = MIB.buildConstant(SwitchTy, 1);
1168e8d8bef9SDimitry Andric     auto SwitchVal = MIB.buildShl(SwitchTy, CstOne, Reg);
1169e8d8bef9SDimitry Andric 
1170e8d8bef9SDimitry Andric     // Emit bit tests and jumps.
1171e8d8bef9SDimitry Andric     auto CstMask = MIB.buildConstant(SwitchTy, B.Mask);
1172e8d8bef9SDimitry Andric     auto AndOp = MIB.buildAnd(SwitchTy, SwitchVal, CstMask);
1173e8d8bef9SDimitry Andric     auto CstZero = MIB.buildConstant(SwitchTy, 0);
1174e8d8bef9SDimitry Andric     Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), AndOp, CstZero)
1175e8d8bef9SDimitry Andric               .getReg(0);
1176e8d8bef9SDimitry Andric   }
1177e8d8bef9SDimitry Andric 
1178e8d8bef9SDimitry Andric   // The branch probability from SwitchBB to B.TargetBB is B.ExtraProb.
1179e8d8bef9SDimitry Andric   addSuccessorWithProb(SwitchBB, B.TargetBB, B.ExtraProb);
1180e8d8bef9SDimitry Andric   // The branch probability from SwitchBB to NextMBB is BranchProbToNext.
1181e8d8bef9SDimitry Andric   addSuccessorWithProb(SwitchBB, NextMBB, BranchProbToNext);
1182e8d8bef9SDimitry Andric   // It is not guaranteed that the sum of B.ExtraProb and BranchProbToNext is
1183e8d8bef9SDimitry Andric   // one as they are relative probabilities (and thus work more like weights),
1184e8d8bef9SDimitry Andric   // and hence we need to normalize them to let the sum of them become one.
1185e8d8bef9SDimitry Andric   SwitchBB->normalizeSuccProbs();
1186e8d8bef9SDimitry Andric 
1187e8d8bef9SDimitry Andric   // Record the fact that the IR edge from the header to the bit test target
1188e8d8bef9SDimitry Andric   // will go through our new block. Neeeded for PHIs to have nodes added.
1189e8d8bef9SDimitry Andric   addMachineCFGPred({BB.Parent->getBasicBlock(), B.TargetBB->getBasicBlock()},
1190e8d8bef9SDimitry Andric                     SwitchBB);
1191e8d8bef9SDimitry Andric 
1192e8d8bef9SDimitry Andric   MIB.buildBrCond(Cmp, *B.TargetBB);
1193e8d8bef9SDimitry Andric 
1194e8d8bef9SDimitry Andric   // Avoid emitting unnecessary branches to the next block.
1195e8d8bef9SDimitry Andric   if (NextMBB != SwitchBB->getNextNode())
1196e8d8bef9SDimitry Andric     MIB.buildBr(*NextMBB);
1197e8d8bef9SDimitry Andric }
1198e8d8bef9SDimitry Andric 
lowerBitTestWorkItem(SwitchCG::SwitchWorkListItem W,MachineBasicBlock * SwitchMBB,MachineBasicBlock * CurMBB,MachineBasicBlock * DefaultMBB,MachineIRBuilder & MIB,MachineFunction::iterator BBI,BranchProbability DefaultProb,BranchProbability UnhandledProbs,SwitchCG::CaseClusterIt I,MachineBasicBlock * Fallthrough,bool FallthroughUnreachable)1199e8d8bef9SDimitry Andric bool IRTranslator::lowerBitTestWorkItem(
1200e8d8bef9SDimitry Andric     SwitchCG::SwitchWorkListItem W, MachineBasicBlock *SwitchMBB,
1201e8d8bef9SDimitry Andric     MachineBasicBlock *CurMBB, MachineBasicBlock *DefaultMBB,
1202e8d8bef9SDimitry Andric     MachineIRBuilder &MIB, MachineFunction::iterator BBI,
1203e8d8bef9SDimitry Andric     BranchProbability DefaultProb, BranchProbability UnhandledProbs,
1204e8d8bef9SDimitry Andric     SwitchCG::CaseClusterIt I, MachineBasicBlock *Fallthrough,
1205e8d8bef9SDimitry Andric     bool FallthroughUnreachable) {
1206e8d8bef9SDimitry Andric   using namespace SwitchCG;
1207e8d8bef9SDimitry Andric   MachineFunction *CurMF = SwitchMBB->getParent();
1208e8d8bef9SDimitry Andric   // FIXME: Optimize away range check based on pivot comparisons.
1209e8d8bef9SDimitry Andric   BitTestBlock *BTB = &SL->BitTestCases[I->BTCasesIndex];
1210e8d8bef9SDimitry Andric   // The bit test blocks haven't been inserted yet; insert them here.
1211e8d8bef9SDimitry Andric   for (BitTestCase &BTC : BTB->Cases)
1212e8d8bef9SDimitry Andric     CurMF->insert(BBI, BTC.ThisBB);
1213e8d8bef9SDimitry Andric 
1214e8d8bef9SDimitry Andric   // Fill in fields of the BitTestBlock.
1215e8d8bef9SDimitry Andric   BTB->Parent = CurMBB;
1216e8d8bef9SDimitry Andric   BTB->Default = Fallthrough;
1217e8d8bef9SDimitry Andric 
1218e8d8bef9SDimitry Andric   BTB->DefaultProb = UnhandledProbs;
1219e8d8bef9SDimitry Andric   // If the cases in bit test don't form a contiguous range, we evenly
1220e8d8bef9SDimitry Andric   // distribute the probability on the edge to Fallthrough to two
1221e8d8bef9SDimitry Andric   // successors of CurMBB.
1222e8d8bef9SDimitry Andric   if (!BTB->ContiguousRange) {
1223e8d8bef9SDimitry Andric     BTB->Prob += DefaultProb / 2;
1224e8d8bef9SDimitry Andric     BTB->DefaultProb -= DefaultProb / 2;
1225e8d8bef9SDimitry Andric   }
1226e8d8bef9SDimitry Andric 
1227349cc55cSDimitry Andric   if (FallthroughUnreachable)
1228349cc55cSDimitry Andric     BTB->FallthroughUnreachable = true;
1229e8d8bef9SDimitry Andric 
1230e8d8bef9SDimitry Andric   // If we're in the right place, emit the bit test header right now.
1231e8d8bef9SDimitry Andric   if (CurMBB == SwitchMBB) {
1232e8d8bef9SDimitry Andric     emitBitTestHeader(*BTB, SwitchMBB);
1233e8d8bef9SDimitry Andric     BTB->Emitted = true;
1234e8d8bef9SDimitry Andric   }
1235e8d8bef9SDimitry Andric   return true;
1236e8d8bef9SDimitry Andric }
1237e8d8bef9SDimitry Andric 
lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W,Value * Cond,MachineBasicBlock * SwitchMBB,MachineBasicBlock * DefaultMBB,MachineIRBuilder & MIB)12380b57cec5SDimitry Andric bool IRTranslator::lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W,
12390b57cec5SDimitry Andric                                        Value *Cond,
12400b57cec5SDimitry Andric                                        MachineBasicBlock *SwitchMBB,
12410b57cec5SDimitry Andric                                        MachineBasicBlock *DefaultMBB,
12420b57cec5SDimitry Andric                                        MachineIRBuilder &MIB) {
12430b57cec5SDimitry Andric   using namespace SwitchCG;
12440b57cec5SDimitry Andric   MachineFunction *CurMF = FuncInfo.MF;
12450b57cec5SDimitry Andric   MachineBasicBlock *NextMBB = nullptr;
12460b57cec5SDimitry Andric   MachineFunction::iterator BBI(W.MBB);
12470b57cec5SDimitry Andric   if (++BBI != FuncInfo.MF->end())
12480b57cec5SDimitry Andric     NextMBB = &*BBI;
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric   if (EnableOpts) {
12510b57cec5SDimitry Andric     // Here, we order cases by probability so the most likely case will be
12520b57cec5SDimitry Andric     // checked first. However, two clusters can have the same probability in
12530b57cec5SDimitry Andric     // which case their relative ordering is non-deterministic. So we use Low
12540b57cec5SDimitry Andric     // as a tie-breaker as clusters are guaranteed to never overlap.
12550b57cec5SDimitry Andric     llvm::sort(W.FirstCluster, W.LastCluster + 1,
12560b57cec5SDimitry Andric                [](const CaseCluster &a, const CaseCluster &b) {
12570b57cec5SDimitry Andric                  return a.Prob != b.Prob
12580b57cec5SDimitry Andric                             ? a.Prob > b.Prob
12590b57cec5SDimitry Andric                             : a.Low->getValue().slt(b.Low->getValue());
12600b57cec5SDimitry Andric                });
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric     // Rearrange the case blocks so that the last one falls through if possible
12630b57cec5SDimitry Andric     // without changing the order of probabilities.
12640b57cec5SDimitry Andric     for (CaseClusterIt I = W.LastCluster; I > W.FirstCluster;) {
12650b57cec5SDimitry Andric       --I;
12660b57cec5SDimitry Andric       if (I->Prob > W.LastCluster->Prob)
12670b57cec5SDimitry Andric         break;
12680b57cec5SDimitry Andric       if (I->Kind == CC_Range && I->MBB == NextMBB) {
12690b57cec5SDimitry Andric         std::swap(*I, *W.LastCluster);
12700b57cec5SDimitry Andric         break;
12710b57cec5SDimitry Andric       }
12720b57cec5SDimitry Andric     }
12730b57cec5SDimitry Andric   }
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric   // Compute total probability.
12760b57cec5SDimitry Andric   BranchProbability DefaultProb = W.DefaultProb;
12770b57cec5SDimitry Andric   BranchProbability UnhandledProbs = DefaultProb;
12780b57cec5SDimitry Andric   for (CaseClusterIt I = W.FirstCluster; I <= W.LastCluster; ++I)
12790b57cec5SDimitry Andric     UnhandledProbs += I->Prob;
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric   MachineBasicBlock *CurMBB = W.MBB;
12820b57cec5SDimitry Andric   for (CaseClusterIt I = W.FirstCluster, E = W.LastCluster; I <= E; ++I) {
12830b57cec5SDimitry Andric     bool FallthroughUnreachable = false;
12840b57cec5SDimitry Andric     MachineBasicBlock *Fallthrough;
12850b57cec5SDimitry Andric     if (I == W.LastCluster) {
12860b57cec5SDimitry Andric       // For the last cluster, fall through to the default destination.
12870b57cec5SDimitry Andric       Fallthrough = DefaultMBB;
12880b57cec5SDimitry Andric       FallthroughUnreachable = isa<UnreachableInst>(
12890b57cec5SDimitry Andric           DefaultMBB->getBasicBlock()->getFirstNonPHIOrDbg());
12900b57cec5SDimitry Andric     } else {
12910b57cec5SDimitry Andric       Fallthrough = CurMF->CreateMachineBasicBlock(CurMBB->getBasicBlock());
12920b57cec5SDimitry Andric       CurMF->insert(BBI, Fallthrough);
12930b57cec5SDimitry Andric     }
12940b57cec5SDimitry Andric     UnhandledProbs -= I->Prob;
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric     switch (I->Kind) {
12970b57cec5SDimitry Andric     case CC_BitTests: {
1298e8d8bef9SDimitry Andric       if (!lowerBitTestWorkItem(W, SwitchMBB, CurMBB, DefaultMBB, MIB, BBI,
1299e8d8bef9SDimitry Andric                                 DefaultProb, UnhandledProbs, I, Fallthrough,
1300e8d8bef9SDimitry Andric                                 FallthroughUnreachable)) {
1301e8d8bef9SDimitry Andric         LLVM_DEBUG(dbgs() << "Failed to lower bit test for switch");
1302e8d8bef9SDimitry Andric         return false;
13030b57cec5SDimitry Andric       }
1304e8d8bef9SDimitry Andric       break;
1305e8d8bef9SDimitry Andric     }
1306e8d8bef9SDimitry Andric 
13070b57cec5SDimitry Andric     case CC_JumpTable: {
13080b57cec5SDimitry Andric       if (!lowerJumpTableWorkItem(W, SwitchMBB, CurMBB, DefaultMBB, MIB, BBI,
13090b57cec5SDimitry Andric                                   UnhandledProbs, I, Fallthrough,
13100b57cec5SDimitry Andric                                   FallthroughUnreachable)) {
13110b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Failed to lower jump table");
13120b57cec5SDimitry Andric         return false;
13130b57cec5SDimitry Andric       }
13140b57cec5SDimitry Andric       break;
13150b57cec5SDimitry Andric     }
13160b57cec5SDimitry Andric     case CC_Range: {
13170b57cec5SDimitry Andric       if (!lowerSwitchRangeWorkItem(I, Cond, Fallthrough,
13180b57cec5SDimitry Andric                                     FallthroughUnreachable, UnhandledProbs,
13190b57cec5SDimitry Andric                                     CurMBB, MIB, SwitchMBB)) {
13200b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Failed to lower switch range");
13210b57cec5SDimitry Andric         return false;
13220b57cec5SDimitry Andric       }
13230b57cec5SDimitry Andric       break;
13240b57cec5SDimitry Andric     }
13250b57cec5SDimitry Andric     }
13260b57cec5SDimitry Andric     CurMBB = Fallthrough;
13270b57cec5SDimitry Andric   }
13280b57cec5SDimitry Andric 
13290b57cec5SDimitry Andric   return true;
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric 
translateIndirectBr(const User & U,MachineIRBuilder & MIRBuilder)13320b57cec5SDimitry Andric bool IRTranslator::translateIndirectBr(const User &U,
13330b57cec5SDimitry Andric                                        MachineIRBuilder &MIRBuilder) {
13340b57cec5SDimitry Andric   const IndirectBrInst &BrInst = cast<IndirectBrInst>(U);
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   const Register Tgt = getOrCreateVReg(*BrInst.getAddress());
13370b57cec5SDimitry Andric   MIRBuilder.buildBrIndirect(Tgt);
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric   // Link successors.
13405ffd83dbSDimitry Andric   SmallPtrSet<const BasicBlock *, 32> AddedSuccessors;
13410b57cec5SDimitry Andric   MachineBasicBlock &CurBB = MIRBuilder.getMBB();
13425ffd83dbSDimitry Andric   for (const BasicBlock *Succ : successors(&BrInst)) {
13435ffd83dbSDimitry Andric     // It's legal for indirectbr instructions to have duplicate blocks in the
13445ffd83dbSDimitry Andric     // destination list. We don't allow this in MIR. Skip anything that's
13455ffd83dbSDimitry Andric     // already a successor.
13465ffd83dbSDimitry Andric     if (!AddedSuccessors.insert(Succ).second)
13475ffd83dbSDimitry Andric       continue;
13480b57cec5SDimitry Andric     CurBB.addSuccessor(&getMBB(*Succ));
13495ffd83dbSDimitry Andric   }
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   return true;
13520b57cec5SDimitry Andric }
13530b57cec5SDimitry Andric 
isSwiftError(const Value * V)13540b57cec5SDimitry Andric static bool isSwiftError(const Value *V) {
13550b57cec5SDimitry Andric   if (auto Arg = dyn_cast<Argument>(V))
13560b57cec5SDimitry Andric     return Arg->hasSwiftErrorAttr();
13570b57cec5SDimitry Andric   if (auto AI = dyn_cast<AllocaInst>(V))
13580b57cec5SDimitry Andric     return AI->isSwiftError();
13590b57cec5SDimitry Andric   return false;
13600b57cec5SDimitry Andric }
13610b57cec5SDimitry Andric 
translateLoad(const User & U,MachineIRBuilder & MIRBuilder)13620b57cec5SDimitry Andric bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
13630b57cec5SDimitry Andric   const LoadInst &LI = cast<LoadInst>(U);
13640fca6ea1SDimitry Andric   TypeSize StoreSize = DL->getTypeStoreSize(LI.getType());
13650fca6ea1SDimitry Andric   if (StoreSize.isZero())
13660b57cec5SDimitry Andric     return true;
13670b57cec5SDimitry Andric 
13680b57cec5SDimitry Andric   ArrayRef<Register> Regs = getOrCreateVRegs(LI);
13690b57cec5SDimitry Andric   ArrayRef<uint64_t> Offsets = *VMap.getOffsets(LI);
13700b57cec5SDimitry Andric   Register Base = getOrCreateVReg(*LI.getPointerOperand());
1371fcaf7f86SDimitry Andric   AAMDNodes AAInfo = LI.getAAMetadata();
13720b57cec5SDimitry Andric 
1373fcaf7f86SDimitry Andric   const Value *Ptr = LI.getPointerOperand();
137406c3fb27SDimitry Andric   Type *OffsetIRTy = DL->getIndexType(Ptr->getType());
13750b57cec5SDimitry Andric   LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
13760b57cec5SDimitry Andric 
1377fcaf7f86SDimitry Andric   if (CLI->supportSwiftError() && isSwiftError(Ptr)) {
13780b57cec5SDimitry Andric     assert(Regs.size() == 1 && "swifterror should be single pointer");
1379fcaf7f86SDimitry Andric     Register VReg =
1380fcaf7f86SDimitry Andric         SwiftError.getOrCreateVRegUseAt(&LI, &MIRBuilder.getMBB(), Ptr);
13810b57cec5SDimitry Andric     MIRBuilder.buildCopy(Regs[0], VReg);
13820b57cec5SDimitry Andric     return true;
13830b57cec5SDimitry Andric   }
13840b57cec5SDimitry Andric 
1385bdd1243dSDimitry Andric   MachineMemOperand::Flags Flags =
13860fca6ea1SDimitry Andric       TLI->getLoadMemOperandFlags(LI, *DL, AC, LibInfo);
1387fcaf7f86SDimitry Andric   if (AA && !(Flags & MachineMemOperand::MOInvariant)) {
1388fcaf7f86SDimitry Andric     if (AA->pointsToConstantMemory(
1389fcaf7f86SDimitry Andric             MemoryLocation(Ptr, LocationSize::precise(StoreSize), AAInfo))) {
1390fcaf7f86SDimitry Andric       Flags |= MachineMemOperand::MOInvariant;
1391fcaf7f86SDimitry Andric     }
1392fcaf7f86SDimitry Andric   }
13935ffd83dbSDimitry Andric 
13948bcb0991SDimitry Andric   const MDNode *Ranges =
13958bcb0991SDimitry Andric       Regs.size() == 1 ? LI.getMetadata(LLVMContext::MD_range) : nullptr;
13960b57cec5SDimitry Andric   for (unsigned i = 0; i < Regs.size(); ++i) {
13970b57cec5SDimitry Andric     Register Addr;
1398480093f4SDimitry Andric     MIRBuilder.materializePtrAdd(Addr, Base, OffsetTy, Offsets[i] / 8);
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric     MachinePointerInfo Ptr(LI.getPointerOperand(), Offsets[i] / 8);
14015ffd83dbSDimitry Andric     Align BaseAlign = getMemOpAlign(LI);
14020b57cec5SDimitry Andric     auto MMO = MF->getMachineMemOperand(
1403fe6060f1SDimitry Andric         Ptr, Flags, MRI->getType(Regs[i]),
1404fcaf7f86SDimitry Andric         commonAlignment(BaseAlign, Offsets[i] / 8), AAInfo, Ranges,
14050b57cec5SDimitry Andric         LI.getSyncScopeID(), LI.getOrdering());
14060b57cec5SDimitry Andric     MIRBuilder.buildLoad(Regs[i], Addr, *MMO);
14070b57cec5SDimitry Andric   }
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   return true;
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric 
translateStore(const User & U,MachineIRBuilder & MIRBuilder)14120b57cec5SDimitry Andric bool IRTranslator::translateStore(const User &U, MachineIRBuilder &MIRBuilder) {
14130b57cec5SDimitry Andric   const StoreInst &SI = cast<StoreInst>(U);
14140fca6ea1SDimitry Andric   if (DL->getTypeStoreSize(SI.getValueOperand()->getType()).isZero())
14150b57cec5SDimitry Andric     return true;
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric   ArrayRef<Register> Vals = getOrCreateVRegs(*SI.getValueOperand());
14180b57cec5SDimitry Andric   ArrayRef<uint64_t> Offsets = *VMap.getOffsets(*SI.getValueOperand());
14190b57cec5SDimitry Andric   Register Base = getOrCreateVReg(*SI.getPointerOperand());
14200b57cec5SDimitry Andric 
142106c3fb27SDimitry Andric   Type *OffsetIRTy = DL->getIndexType(SI.getPointerOperandType());
14220b57cec5SDimitry Andric   LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric   if (CLI->supportSwiftError() && isSwiftError(SI.getPointerOperand())) {
14250b57cec5SDimitry Andric     assert(Vals.size() == 1 && "swifterror should be single pointer");
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric     Register VReg = SwiftError.getOrCreateVRegDefAt(&SI, &MIRBuilder.getMBB(),
14280b57cec5SDimitry Andric                                                     SI.getPointerOperand());
14290b57cec5SDimitry Andric     MIRBuilder.buildCopy(VReg, Vals[0]);
14300b57cec5SDimitry Andric     return true;
14310b57cec5SDimitry Andric   }
14320b57cec5SDimitry Andric 
14330fca6ea1SDimitry Andric   MachineMemOperand::Flags Flags = TLI->getStoreMemOperandFlags(SI, *DL);
14345ffd83dbSDimitry Andric 
14350b57cec5SDimitry Andric   for (unsigned i = 0; i < Vals.size(); ++i) {
14360b57cec5SDimitry Andric     Register Addr;
1437480093f4SDimitry Andric     MIRBuilder.materializePtrAdd(Addr, Base, OffsetTy, Offsets[i] / 8);
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric     MachinePointerInfo Ptr(SI.getPointerOperand(), Offsets[i] / 8);
14405ffd83dbSDimitry Andric     Align BaseAlign = getMemOpAlign(SI);
14410b57cec5SDimitry Andric     auto MMO = MF->getMachineMemOperand(
1442fe6060f1SDimitry Andric         Ptr, Flags, MRI->getType(Vals[i]),
1443349cc55cSDimitry Andric         commonAlignment(BaseAlign, Offsets[i] / 8), SI.getAAMetadata(), nullptr,
14440b57cec5SDimitry Andric         SI.getSyncScopeID(), SI.getOrdering());
14450b57cec5SDimitry Andric     MIRBuilder.buildStore(Vals[i], Addr, *MMO);
14460b57cec5SDimitry Andric   }
14470b57cec5SDimitry Andric   return true;
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
getOffsetFromIndices(const User & U,const DataLayout & DL)14500b57cec5SDimitry Andric static uint64_t getOffsetFromIndices(const User &U, const DataLayout &DL) {
14510b57cec5SDimitry Andric   const Value *Src = U.getOperand(0);
14520b57cec5SDimitry Andric   Type *Int32Ty = Type::getInt32Ty(U.getContext());
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric   // getIndexedOffsetInType is designed for GEPs, so the first index is the
14550b57cec5SDimitry Andric   // usual array element rather than looking into the actual aggregate.
14560b57cec5SDimitry Andric   SmallVector<Value *, 1> Indices;
14570b57cec5SDimitry Andric   Indices.push_back(ConstantInt::get(Int32Ty, 0));
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric   if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(&U)) {
14600b57cec5SDimitry Andric     for (auto Idx : EVI->indices())
14610b57cec5SDimitry Andric       Indices.push_back(ConstantInt::get(Int32Ty, Idx));
14620b57cec5SDimitry Andric   } else if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(&U)) {
14630b57cec5SDimitry Andric     for (auto Idx : IVI->indices())
14640b57cec5SDimitry Andric       Indices.push_back(ConstantInt::get(Int32Ty, Idx));
14650b57cec5SDimitry Andric   } else {
14660b57cec5SDimitry Andric     for (unsigned i = 1; i < U.getNumOperands(); ++i)
14670b57cec5SDimitry Andric       Indices.push_back(U.getOperand(i));
14680b57cec5SDimitry Andric   }
14690b57cec5SDimitry Andric 
14700b57cec5SDimitry Andric   return 8 * static_cast<uint64_t>(
14710b57cec5SDimitry Andric                  DL.getIndexedOffsetInType(Src->getType(), Indices));
14720b57cec5SDimitry Andric }
14730b57cec5SDimitry Andric 
translateExtractValue(const User & U,MachineIRBuilder & MIRBuilder)14740b57cec5SDimitry Andric bool IRTranslator::translateExtractValue(const User &U,
14750b57cec5SDimitry Andric                                          MachineIRBuilder &MIRBuilder) {
14760b57cec5SDimitry Andric   const Value *Src = U.getOperand(0);
14770b57cec5SDimitry Andric   uint64_t Offset = getOffsetFromIndices(U, *DL);
14780b57cec5SDimitry Andric   ArrayRef<Register> SrcRegs = getOrCreateVRegs(*Src);
14790b57cec5SDimitry Andric   ArrayRef<uint64_t> Offsets = *VMap.getOffsets(*Src);
14800b57cec5SDimitry Andric   unsigned Idx = llvm::lower_bound(Offsets, Offset) - Offsets.begin();
14810b57cec5SDimitry Andric   auto &DstRegs = allocateVRegs(U);
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric   for (unsigned i = 0; i < DstRegs.size(); ++i)
14840b57cec5SDimitry Andric     DstRegs[i] = SrcRegs[Idx++];
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric   return true;
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
translateInsertValue(const User & U,MachineIRBuilder & MIRBuilder)14890b57cec5SDimitry Andric bool IRTranslator::translateInsertValue(const User &U,
14900b57cec5SDimitry Andric                                         MachineIRBuilder &MIRBuilder) {
14910b57cec5SDimitry Andric   const Value *Src = U.getOperand(0);
14920b57cec5SDimitry Andric   uint64_t Offset = getOffsetFromIndices(U, *DL);
14930b57cec5SDimitry Andric   auto &DstRegs = allocateVRegs(U);
14940b57cec5SDimitry Andric   ArrayRef<uint64_t> DstOffsets = *VMap.getOffsets(U);
14950b57cec5SDimitry Andric   ArrayRef<Register> SrcRegs = getOrCreateVRegs(*Src);
14960b57cec5SDimitry Andric   ArrayRef<Register> InsertedRegs = getOrCreateVRegs(*U.getOperand(1));
1497fcaf7f86SDimitry Andric   auto *InsertedIt = InsertedRegs.begin();
14980b57cec5SDimitry Andric 
14990b57cec5SDimitry Andric   for (unsigned i = 0; i < DstRegs.size(); ++i) {
15000b57cec5SDimitry Andric     if (DstOffsets[i] >= Offset && InsertedIt != InsertedRegs.end())
15010b57cec5SDimitry Andric       DstRegs[i] = *InsertedIt++;
15020b57cec5SDimitry Andric     else
15030b57cec5SDimitry Andric       DstRegs[i] = SrcRegs[i];
15040b57cec5SDimitry Andric   }
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric   return true;
15070b57cec5SDimitry Andric }
15080b57cec5SDimitry Andric 
translateSelect(const User & U,MachineIRBuilder & MIRBuilder)15090b57cec5SDimitry Andric bool IRTranslator::translateSelect(const User &U,
15100b57cec5SDimitry Andric                                    MachineIRBuilder &MIRBuilder) {
15110b57cec5SDimitry Andric   Register Tst = getOrCreateVReg(*U.getOperand(0));
15120b57cec5SDimitry Andric   ArrayRef<Register> ResRegs = getOrCreateVRegs(U);
15130b57cec5SDimitry Andric   ArrayRef<Register> Op0Regs = getOrCreateVRegs(*U.getOperand(1));
15140b57cec5SDimitry Andric   ArrayRef<Register> Op1Regs = getOrCreateVRegs(*U.getOperand(2));
15150b57cec5SDimitry Andric 
151606c3fb27SDimitry Andric   uint32_t Flags = 0;
15175ffd83dbSDimitry Andric   if (const SelectInst *SI = dyn_cast<SelectInst>(&U))
15185ffd83dbSDimitry Andric     Flags = MachineInstr::copyFlagsFromInstruction(*SI);
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric   for (unsigned i = 0; i < ResRegs.size(); ++i) {
15215ffd83dbSDimitry Andric     MIRBuilder.buildSelect(ResRegs[i], Tst, Op0Regs[i], Op1Regs[i], Flags);
15220b57cec5SDimitry Andric   }
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric   return true;
15250b57cec5SDimitry Andric }
15260b57cec5SDimitry Andric 
translateCopy(const User & U,const Value & V,MachineIRBuilder & MIRBuilder)15275ffd83dbSDimitry Andric bool IRTranslator::translateCopy(const User &U, const Value &V,
15285ffd83dbSDimitry Andric                                  MachineIRBuilder &MIRBuilder) {
15295ffd83dbSDimitry Andric   Register Src = getOrCreateVReg(V);
15305ffd83dbSDimitry Andric   auto &Regs = *VMap.getVRegs(U);
15315ffd83dbSDimitry Andric   if (Regs.empty()) {
15325ffd83dbSDimitry Andric     Regs.push_back(Src);
15335ffd83dbSDimitry Andric     VMap.getOffsets(U)->push_back(0);
15345ffd83dbSDimitry Andric   } else {
15355ffd83dbSDimitry Andric     // If we already assigned a vreg for this instruction, we can't change that.
15365ffd83dbSDimitry Andric     // Emit a copy to satisfy the users we already emitted.
15375ffd83dbSDimitry Andric     MIRBuilder.buildCopy(Regs[0], Src);
15385ffd83dbSDimitry Andric   }
15395ffd83dbSDimitry Andric   return true;
15405ffd83dbSDimitry Andric }
15415ffd83dbSDimitry Andric 
translateBitCast(const User & U,MachineIRBuilder & MIRBuilder)15420b57cec5SDimitry Andric bool IRTranslator::translateBitCast(const User &U,
15430b57cec5SDimitry Andric                                     MachineIRBuilder &MIRBuilder) {
15440b57cec5SDimitry Andric   // If we're bitcasting to the source type, we can reuse the source vreg.
15450b57cec5SDimitry Andric   if (getLLTForType(*U.getOperand(0)->getType(), *DL) ==
154606c3fb27SDimitry Andric       getLLTForType(*U.getType(), *DL)) {
154706c3fb27SDimitry Andric     // If the source is a ConstantInt then it was probably created by
154806c3fb27SDimitry Andric     // ConstantHoisting and we should leave it alone.
154906c3fb27SDimitry Andric     if (isa<ConstantInt>(U.getOperand(0)))
155006c3fb27SDimitry Andric       return translateCast(TargetOpcode::G_CONSTANT_FOLD_BARRIER, U,
155106c3fb27SDimitry Andric                            MIRBuilder);
15525ffd83dbSDimitry Andric     return translateCopy(U, *U.getOperand(0), MIRBuilder);
155306c3fb27SDimitry Andric   }
15545ffd83dbSDimitry Andric 
15550b57cec5SDimitry Andric   return translateCast(TargetOpcode::G_BITCAST, U, MIRBuilder);
15560b57cec5SDimitry Andric }
15570b57cec5SDimitry Andric 
translateCast(unsigned Opcode,const User & U,MachineIRBuilder & MIRBuilder)15580b57cec5SDimitry Andric bool IRTranslator::translateCast(unsigned Opcode, const User &U,
15590b57cec5SDimitry Andric                                  MachineIRBuilder &MIRBuilder) {
15605f757f3fSDimitry Andric   if (U.getType()->getScalarType()->isBFloatTy() ||
15615f757f3fSDimitry Andric       U.getOperand(0)->getType()->getScalarType()->isBFloatTy())
15625f757f3fSDimitry Andric     return false;
15630fca6ea1SDimitry Andric 
15640fca6ea1SDimitry Andric   uint32_t Flags = 0;
15650fca6ea1SDimitry Andric   if (const Instruction *I = dyn_cast<Instruction>(&U))
15660fca6ea1SDimitry Andric     Flags = MachineInstr::copyFlagsFromInstruction(*I);
15670fca6ea1SDimitry Andric 
15680b57cec5SDimitry Andric   Register Op = getOrCreateVReg(*U.getOperand(0));
15690b57cec5SDimitry Andric   Register Res = getOrCreateVReg(U);
15700fca6ea1SDimitry Andric   MIRBuilder.buildInstr(Opcode, {Res}, {Op}, Flags);
15710b57cec5SDimitry Andric   return true;
15720b57cec5SDimitry Andric }
15730b57cec5SDimitry Andric 
translateGetElementPtr(const User & U,MachineIRBuilder & MIRBuilder)15740b57cec5SDimitry Andric bool IRTranslator::translateGetElementPtr(const User &U,
15750b57cec5SDimitry Andric                                           MachineIRBuilder &MIRBuilder) {
15760b57cec5SDimitry Andric   Value &Op0 = *U.getOperand(0);
15770b57cec5SDimitry Andric   Register BaseReg = getOrCreateVReg(Op0);
15780b57cec5SDimitry Andric   Type *PtrIRTy = Op0.getType();
15790b57cec5SDimitry Andric   LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
158006c3fb27SDimitry Andric   Type *OffsetIRTy = DL->getIndexType(PtrIRTy);
15810b57cec5SDimitry Andric   LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
15820b57cec5SDimitry Andric 
15835f757f3fSDimitry Andric   uint32_t Flags = 0;
15840fca6ea1SDimitry Andric   if (const Instruction *I = dyn_cast<Instruction>(&U))
15850fca6ea1SDimitry Andric     Flags = MachineInstr::copyFlagsFromInstruction(*I);
15865f757f3fSDimitry Andric 
15875ffd83dbSDimitry Andric   // Normalize Vector GEP - all scalar operands should be converted to the
15885ffd83dbSDimitry Andric   // splat vector.
15895ffd83dbSDimitry Andric   unsigned VectorWidth = 0;
1590fe6060f1SDimitry Andric 
1591fe6060f1SDimitry Andric   // True if we should use a splat vector; using VectorWidth alone is not
1592fe6060f1SDimitry Andric   // sufficient.
1593fe6060f1SDimitry Andric   bool WantSplatVector = false;
1594fe6060f1SDimitry Andric   if (auto *VT = dyn_cast<VectorType>(U.getType())) {
15955ffd83dbSDimitry Andric     VectorWidth = cast<FixedVectorType>(VT)->getNumElements();
1596fe6060f1SDimitry Andric     // We don't produce 1 x N vectors; those are treated as scalars.
1597fe6060f1SDimitry Andric     WantSplatVector = VectorWidth > 1;
1598fe6060f1SDimitry Andric   }
15995ffd83dbSDimitry Andric 
16005ffd83dbSDimitry Andric   // We might need to splat the base pointer into a vector if the offsets
16015ffd83dbSDimitry Andric   // are vectors.
1602fe6060f1SDimitry Andric   if (WantSplatVector && !PtrTy.isVector()) {
16030fca6ea1SDimitry Andric     BaseReg = MIRBuilder
16040fca6ea1SDimitry Andric                   .buildSplatBuildVector(LLT::fixed_vector(VectorWidth, PtrTy),
16050fca6ea1SDimitry Andric                                          BaseReg)
16065ffd83dbSDimitry Andric                   .getReg(0);
16075ffd83dbSDimitry Andric     PtrIRTy = FixedVectorType::get(PtrIRTy, VectorWidth);
16085ffd83dbSDimitry Andric     PtrTy = getLLTForType(*PtrIRTy, *DL);
160906c3fb27SDimitry Andric     OffsetIRTy = DL->getIndexType(PtrIRTy);
16105ffd83dbSDimitry Andric     OffsetTy = getLLTForType(*OffsetIRTy, *DL);
16115ffd83dbSDimitry Andric   }
16125ffd83dbSDimitry Andric 
16130b57cec5SDimitry Andric   int64_t Offset = 0;
16140b57cec5SDimitry Andric   for (gep_type_iterator GTI = gep_type_begin(&U), E = gep_type_end(&U);
16150b57cec5SDimitry Andric        GTI != E; ++GTI) {
16160b57cec5SDimitry Andric     const Value *Idx = GTI.getOperand();
16170b57cec5SDimitry Andric     if (StructType *StTy = GTI.getStructTypeOrNull()) {
16180b57cec5SDimitry Andric       unsigned Field = cast<Constant>(Idx)->getUniqueInteger().getZExtValue();
16190b57cec5SDimitry Andric       Offset += DL->getStructLayout(StTy)->getElementOffset(Field);
16200b57cec5SDimitry Andric       continue;
16210b57cec5SDimitry Andric     } else {
16221db9f3b2SDimitry Andric       uint64_t ElementSize = GTI.getSequentialElementStride(*DL);
16230b57cec5SDimitry Andric 
16240b57cec5SDimitry Andric       // If this is a scalar constant or a splat vector of constants,
16250b57cec5SDimitry Andric       // handle it quickly.
16260b57cec5SDimitry Andric       if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
16275f757f3fSDimitry Andric         if (std::optional<int64_t> Val = CI->getValue().trySExtValue()) {
16285f757f3fSDimitry Andric           Offset += ElementSize * *Val;
16290b57cec5SDimitry Andric           continue;
16300b57cec5SDimitry Andric         }
16315f757f3fSDimitry Andric       }
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric       if (Offset != 0) {
16340b57cec5SDimitry Andric         auto OffsetMIB = MIRBuilder.buildConstant({OffsetTy}, Offset);
1635480093f4SDimitry Andric         BaseReg = MIRBuilder.buildPtrAdd(PtrTy, BaseReg, OffsetMIB.getReg(0))
1636480093f4SDimitry Andric                       .getReg(0);
16370b57cec5SDimitry Andric         Offset = 0;
16380b57cec5SDimitry Andric       }
16390b57cec5SDimitry Andric 
16400b57cec5SDimitry Andric       Register IdxReg = getOrCreateVReg(*Idx);
16415ffd83dbSDimitry Andric       LLT IdxTy = MRI->getType(IdxReg);
16425ffd83dbSDimitry Andric       if (IdxTy != OffsetTy) {
1643fe6060f1SDimitry Andric         if (!IdxTy.isVector() && WantSplatVector) {
16440fca6ea1SDimitry Andric           IdxReg = MIRBuilder
16450fca6ea1SDimitry Andric                        .buildSplatBuildVector(OffsetTy.changeElementType(IdxTy),
16460fca6ea1SDimitry Andric                                               IdxReg)
16470fca6ea1SDimitry Andric                        .getReg(0);
16485ffd83dbSDimitry Andric         }
16495ffd83dbSDimitry Andric 
16508bcb0991SDimitry Andric         IdxReg = MIRBuilder.buildSExtOrTrunc(OffsetTy, IdxReg).getReg(0);
16515ffd83dbSDimitry Andric       }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric       // N = N + Idx * ElementSize;
16540b57cec5SDimitry Andric       // Avoid doing it for ElementSize of 1.
16550b57cec5SDimitry Andric       Register GepOffsetReg;
16560b57cec5SDimitry Andric       if (ElementSize != 1) {
16570b57cec5SDimitry Andric         auto ElementSizeMIB = MIRBuilder.buildConstant(
16580b57cec5SDimitry Andric             getLLTForType(*OffsetIRTy, *DL), ElementSize);
16598bcb0991SDimitry Andric         GepOffsetReg =
16605ffd83dbSDimitry Andric             MIRBuilder.buildMul(OffsetTy, IdxReg, ElementSizeMIB).getReg(0);
16610b57cec5SDimitry Andric       } else
16620b57cec5SDimitry Andric         GepOffsetReg = IdxReg;
16630b57cec5SDimitry Andric 
1664480093f4SDimitry Andric       BaseReg = MIRBuilder.buildPtrAdd(PtrTy, BaseReg, GepOffsetReg).getReg(0);
16650b57cec5SDimitry Andric     }
16660b57cec5SDimitry Andric   }
16670b57cec5SDimitry Andric 
16680b57cec5SDimitry Andric   if (Offset != 0) {
16690b57cec5SDimitry Andric     auto OffsetMIB =
16705ffd83dbSDimitry Andric         MIRBuilder.buildConstant(OffsetTy, Offset);
16715f757f3fSDimitry Andric 
16725f757f3fSDimitry Andric     if (int64_t(Offset) >= 0 && cast<GEPOperator>(U).isInBounds())
16735f757f3fSDimitry Andric       Flags |= MachineInstr::MIFlag::NoUWrap;
16745f757f3fSDimitry Andric 
16755f757f3fSDimitry Andric     MIRBuilder.buildPtrAdd(getOrCreateVReg(U), BaseReg, OffsetMIB.getReg(0),
16765f757f3fSDimitry Andric                            Flags);
16770b57cec5SDimitry Andric     return true;
16780b57cec5SDimitry Andric   }
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric   MIRBuilder.buildCopy(getOrCreateVReg(U), BaseReg);
16810b57cec5SDimitry Andric   return true;
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric 
translateMemFunc(const CallInst & CI,MachineIRBuilder & MIRBuilder,unsigned Opcode)16848bcb0991SDimitry Andric bool IRTranslator::translateMemFunc(const CallInst &CI,
16850b57cec5SDimitry Andric                                     MachineIRBuilder &MIRBuilder,
1686e8d8bef9SDimitry Andric                                     unsigned Opcode) {
1687fcaf7f86SDimitry Andric   const Value *SrcPtr = CI.getArgOperand(1);
16880b57cec5SDimitry Andric   // If the source is undef, then just emit a nop.
1689fcaf7f86SDimitry Andric   if (isa<UndefValue>(SrcPtr))
16900b57cec5SDimitry Andric     return true;
16918bcb0991SDimitry Andric 
1692e8d8bef9SDimitry Andric   SmallVector<Register, 3> SrcRegs;
1693e8d8bef9SDimitry Andric 
1694e8d8bef9SDimitry Andric   unsigned MinPtrSize = UINT_MAX;
1695e8d8bef9SDimitry Andric   for (auto AI = CI.arg_begin(), AE = CI.arg_end(); std::next(AI) != AE; ++AI) {
1696e8d8bef9SDimitry Andric     Register SrcReg = getOrCreateVReg(**AI);
1697e8d8bef9SDimitry Andric     LLT SrcTy = MRI->getType(SrcReg);
1698e8d8bef9SDimitry Andric     if (SrcTy.isPointer())
1699fe6060f1SDimitry Andric       MinPtrSize = std::min<unsigned>(SrcTy.getSizeInBits(), MinPtrSize);
1700e8d8bef9SDimitry Andric     SrcRegs.push_back(SrcReg);
1701e8d8bef9SDimitry Andric   }
1702e8d8bef9SDimitry Andric 
1703e8d8bef9SDimitry Andric   LLT SizeTy = LLT::scalar(MinPtrSize);
1704e8d8bef9SDimitry Andric 
1705e8d8bef9SDimitry Andric   // The size operand should be the minimum of the pointer sizes.
1706e8d8bef9SDimitry Andric   Register &SizeOpReg = SrcRegs[SrcRegs.size() - 1];
1707e8d8bef9SDimitry Andric   if (MRI->getType(SizeOpReg) != SizeTy)
1708e8d8bef9SDimitry Andric     SizeOpReg = MIRBuilder.buildZExtOrTrunc(SizeTy, SizeOpReg).getReg(0);
1709e8d8bef9SDimitry Andric 
1710e8d8bef9SDimitry Andric   auto ICall = MIRBuilder.buildInstr(Opcode);
1711e8d8bef9SDimitry Andric   for (Register SrcReg : SrcRegs)
1712e8d8bef9SDimitry Andric     ICall.addUse(SrcReg);
17138bcb0991SDimitry Andric 
17145ffd83dbSDimitry Andric   Align DstAlign;
17155ffd83dbSDimitry Andric   Align SrcAlign;
17168bcb0991SDimitry Andric   unsigned IsVol =
1717349cc55cSDimitry Andric       cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1))->getZExtValue();
17188bcb0991SDimitry Andric 
1719fcaf7f86SDimitry Andric   ConstantInt *CopySize = nullptr;
1720fcaf7f86SDimitry Andric 
17218bcb0991SDimitry Andric   if (auto *MCI = dyn_cast<MemCpyInst>(&CI)) {
17225ffd83dbSDimitry Andric     DstAlign = MCI->getDestAlign().valueOrOne();
17235ffd83dbSDimitry Andric     SrcAlign = MCI->getSourceAlign().valueOrOne();
1724fcaf7f86SDimitry Andric     CopySize = dyn_cast<ConstantInt>(MCI->getArgOperand(2));
1725fe6060f1SDimitry Andric   } else if (auto *MCI = dyn_cast<MemCpyInlineInst>(&CI)) {
1726fe6060f1SDimitry Andric     DstAlign = MCI->getDestAlign().valueOrOne();
1727fe6060f1SDimitry Andric     SrcAlign = MCI->getSourceAlign().valueOrOne();
1728fcaf7f86SDimitry Andric     CopySize = dyn_cast<ConstantInt>(MCI->getArgOperand(2));
17298bcb0991SDimitry Andric   } else if (auto *MMI = dyn_cast<MemMoveInst>(&CI)) {
17305ffd83dbSDimitry Andric     DstAlign = MMI->getDestAlign().valueOrOne();
17315ffd83dbSDimitry Andric     SrcAlign = MMI->getSourceAlign().valueOrOne();
1732fcaf7f86SDimitry Andric     CopySize = dyn_cast<ConstantInt>(MMI->getArgOperand(2));
17338bcb0991SDimitry Andric   } else {
17348bcb0991SDimitry Andric     auto *MSI = cast<MemSetInst>(&CI);
17355ffd83dbSDimitry Andric     DstAlign = MSI->getDestAlign().valueOrOne();
17360b57cec5SDimitry Andric   }
17370b57cec5SDimitry Andric 
1738fe6060f1SDimitry Andric   if (Opcode != TargetOpcode::G_MEMCPY_INLINE) {
17398bcb0991SDimitry Andric     // We need to propagate the tail call flag from the IR inst as an argument.
17408bcb0991SDimitry Andric     // Otherwise, we have to pessimize and assume later that we cannot tail call
17418bcb0991SDimitry Andric     // any memory intrinsics.
17428bcb0991SDimitry Andric     ICall.addImm(CI.isTailCall() ? 1 : 0);
1743fe6060f1SDimitry Andric   }
17440b57cec5SDimitry Andric 
17458bcb0991SDimitry Andric   // Create mem operands to store the alignment and volatile info.
1746fcaf7f86SDimitry Andric   MachineMemOperand::Flags LoadFlags = MachineMemOperand::MOLoad;
1747fcaf7f86SDimitry Andric   MachineMemOperand::Flags StoreFlags = MachineMemOperand::MOStore;
1748fcaf7f86SDimitry Andric   if (IsVol) {
1749fcaf7f86SDimitry Andric     LoadFlags |= MachineMemOperand::MOVolatile;
1750fcaf7f86SDimitry Andric     StoreFlags |= MachineMemOperand::MOVolatile;
1751fcaf7f86SDimitry Andric   }
1752fcaf7f86SDimitry Andric 
1753fcaf7f86SDimitry Andric   AAMDNodes AAInfo = CI.getAAMetadata();
1754fcaf7f86SDimitry Andric   if (AA && CopySize &&
1755fcaf7f86SDimitry Andric       AA->pointsToConstantMemory(MemoryLocation(
1756fcaf7f86SDimitry Andric           SrcPtr, LocationSize::precise(CopySize->getZExtValue()), AAInfo))) {
1757fcaf7f86SDimitry Andric     LoadFlags |= MachineMemOperand::MOInvariant;
1758fcaf7f86SDimitry Andric 
1759fcaf7f86SDimitry Andric     // FIXME: pointsToConstantMemory probably does not imply dereferenceable,
1760fcaf7f86SDimitry Andric     // but the previous usage implied it did. Probably should check
1761fcaf7f86SDimitry Andric     // isDereferenceableAndAlignedPointer.
1762fcaf7f86SDimitry Andric     LoadFlags |= MachineMemOperand::MODereferenceable;
1763fcaf7f86SDimitry Andric   }
1764fcaf7f86SDimitry Andric 
1765fcaf7f86SDimitry Andric   ICall.addMemOperand(
1766fcaf7f86SDimitry Andric       MF->getMachineMemOperand(MachinePointerInfo(CI.getArgOperand(0)),
1767fcaf7f86SDimitry Andric                                StoreFlags, 1, DstAlign, AAInfo));
1768e8d8bef9SDimitry Andric   if (Opcode != TargetOpcode::G_MEMSET)
17698bcb0991SDimitry Andric     ICall.addMemOperand(MF->getMachineMemOperand(
1770fcaf7f86SDimitry Andric         MachinePointerInfo(SrcPtr), LoadFlags, 1, SrcAlign, AAInfo));
17710b57cec5SDimitry Andric 
17728bcb0991SDimitry Andric   return true;
17730b57cec5SDimitry Andric }
17740b57cec5SDimitry Andric 
translateTrap(const CallInst & CI,MachineIRBuilder & MIRBuilder,unsigned Opcode)17750fca6ea1SDimitry Andric bool IRTranslator::translateTrap(const CallInst &CI,
17760fca6ea1SDimitry Andric                                  MachineIRBuilder &MIRBuilder,
17770fca6ea1SDimitry Andric                                  unsigned Opcode) {
17780fca6ea1SDimitry Andric   StringRef TrapFuncName =
17790fca6ea1SDimitry Andric       CI.getAttributes().getFnAttr("trap-func-name").getValueAsString();
17800fca6ea1SDimitry Andric   if (TrapFuncName.empty()) {
17810fca6ea1SDimitry Andric     if (Opcode == TargetOpcode::G_UBSANTRAP) {
17820fca6ea1SDimitry Andric       uint64_t Code = cast<ConstantInt>(CI.getOperand(0))->getZExtValue();
17830fca6ea1SDimitry Andric       MIRBuilder.buildInstr(Opcode, {}, ArrayRef<llvm::SrcOp>{Code});
17840fca6ea1SDimitry Andric     } else {
17850fca6ea1SDimitry Andric       MIRBuilder.buildInstr(Opcode);
17860fca6ea1SDimitry Andric     }
17870fca6ea1SDimitry Andric     return true;
17880fca6ea1SDimitry Andric   }
17890fca6ea1SDimitry Andric 
17900fca6ea1SDimitry Andric   CallLowering::CallLoweringInfo Info;
17910fca6ea1SDimitry Andric   if (Opcode == TargetOpcode::G_UBSANTRAP)
17920fca6ea1SDimitry Andric     Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)),
17930fca6ea1SDimitry Andric                              CI.getArgOperand(0)->getType(), 0});
17940fca6ea1SDimitry Andric 
17950fca6ea1SDimitry Andric   Info.Callee = MachineOperand::CreateES(TrapFuncName.data());
17960fca6ea1SDimitry Andric   Info.CB = &CI;
17970fca6ea1SDimitry Andric   Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0};
17980fca6ea1SDimitry Andric   return CLI->lowerCall(MIRBuilder, Info);
17990fca6ea1SDimitry Andric }
18000fca6ea1SDimitry Andric 
translateVectorInterleave2Intrinsic(const CallInst & CI,MachineIRBuilder & MIRBuilder)18010fca6ea1SDimitry Andric bool IRTranslator::translateVectorInterleave2Intrinsic(
18020fca6ea1SDimitry Andric     const CallInst &CI, MachineIRBuilder &MIRBuilder) {
18030fca6ea1SDimitry Andric   assert(CI.getIntrinsicID() == Intrinsic::vector_interleave2 &&
18040fca6ea1SDimitry Andric          "This function can only be called on the interleave2 intrinsic!");
18050fca6ea1SDimitry Andric   // Canonicalize interleave2 to G_SHUFFLE_VECTOR (similar to SelectionDAG).
18060fca6ea1SDimitry Andric   Register Op0 = getOrCreateVReg(*CI.getOperand(0));
18070fca6ea1SDimitry Andric   Register Op1 = getOrCreateVReg(*CI.getOperand(1));
18080fca6ea1SDimitry Andric   Register Res = getOrCreateVReg(CI);
18090fca6ea1SDimitry Andric 
18100fca6ea1SDimitry Andric   LLT OpTy = MRI->getType(Op0);
18110fca6ea1SDimitry Andric   MIRBuilder.buildShuffleVector(Res, Op0, Op1,
18120fca6ea1SDimitry Andric                                 createInterleaveMask(OpTy.getNumElements(), 2));
18130fca6ea1SDimitry Andric 
18140fca6ea1SDimitry Andric   return true;
18150fca6ea1SDimitry Andric }
18160fca6ea1SDimitry Andric 
translateVectorDeinterleave2Intrinsic(const CallInst & CI,MachineIRBuilder & MIRBuilder)18170fca6ea1SDimitry Andric bool IRTranslator::translateVectorDeinterleave2Intrinsic(
18180fca6ea1SDimitry Andric     const CallInst &CI, MachineIRBuilder &MIRBuilder) {
18190fca6ea1SDimitry Andric   assert(CI.getIntrinsicID() == Intrinsic::vector_deinterleave2 &&
18200fca6ea1SDimitry Andric          "This function can only be called on the deinterleave2 intrinsic!");
18210fca6ea1SDimitry Andric   // Canonicalize deinterleave2 to shuffles that extract sub-vectors (similar to
18220fca6ea1SDimitry Andric   // SelectionDAG).
18230fca6ea1SDimitry Andric   Register Op = getOrCreateVReg(*CI.getOperand(0));
18240fca6ea1SDimitry Andric   auto Undef = MIRBuilder.buildUndef(MRI->getType(Op));
18250fca6ea1SDimitry Andric   ArrayRef<Register> Res = getOrCreateVRegs(CI);
18260fca6ea1SDimitry Andric 
18270fca6ea1SDimitry Andric   LLT ResTy = MRI->getType(Res[0]);
18280fca6ea1SDimitry Andric   MIRBuilder.buildShuffleVector(Res[0], Op, Undef,
18290fca6ea1SDimitry Andric                                 createStrideMask(0, 2, ResTy.getNumElements()));
18300fca6ea1SDimitry Andric   MIRBuilder.buildShuffleVector(Res[1], Op, Undef,
18310fca6ea1SDimitry Andric                                 createStrideMask(1, 2, ResTy.getNumElements()));
18320fca6ea1SDimitry Andric 
18330fca6ea1SDimitry Andric   return true;
18340fca6ea1SDimitry Andric }
18350fca6ea1SDimitry Andric 
getStackGuard(Register DstReg,MachineIRBuilder & MIRBuilder)18360b57cec5SDimitry Andric void IRTranslator::getStackGuard(Register DstReg,
18370b57cec5SDimitry Andric                                  MachineIRBuilder &MIRBuilder) {
18380b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
18390b57cec5SDimitry Andric   MRI->setRegClass(DstReg, TRI->getPointerRegClass(*MF));
18405ffd83dbSDimitry Andric   auto MIB =
18415ffd83dbSDimitry Andric       MIRBuilder.buildInstr(TargetOpcode::LOAD_STACK_GUARD, {DstReg}, {});
18420b57cec5SDimitry Andric 
18430fca6ea1SDimitry Andric   Value *Global = TLI->getSDagStackGuard(*MF->getFunction().getParent());
18440b57cec5SDimitry Andric   if (!Global)
18450b57cec5SDimitry Andric     return;
18460b57cec5SDimitry Andric 
1847fe6060f1SDimitry Andric   unsigned AddrSpace = Global->getType()->getPointerAddressSpace();
1848fe6060f1SDimitry Andric   LLT PtrTy = LLT::pointer(AddrSpace, DL->getPointerSizeInBits(AddrSpace));
1849fe6060f1SDimitry Andric 
18500b57cec5SDimitry Andric   MachinePointerInfo MPInfo(Global);
18510b57cec5SDimitry Andric   auto Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant |
18520b57cec5SDimitry Andric                MachineMemOperand::MODereferenceable;
1853fe6060f1SDimitry Andric   MachineMemOperand *MemRef = MF->getMachineMemOperand(
1854fe6060f1SDimitry Andric       MPInfo, Flags, PtrTy, DL->getPointerABIAlignment(AddrSpace));
18550b57cec5SDimitry Andric   MIB.setMemRefs({MemRef});
18560b57cec5SDimitry Andric }
18570b57cec5SDimitry Andric 
translateOverflowIntrinsic(const CallInst & CI,unsigned Op,MachineIRBuilder & MIRBuilder)18580b57cec5SDimitry Andric bool IRTranslator::translateOverflowIntrinsic(const CallInst &CI, unsigned Op,
18590b57cec5SDimitry Andric                                               MachineIRBuilder &MIRBuilder) {
18600b57cec5SDimitry Andric   ArrayRef<Register> ResRegs = getOrCreateVRegs(CI);
18615ffd83dbSDimitry Andric   MIRBuilder.buildInstr(
18625ffd83dbSDimitry Andric       Op, {ResRegs[0], ResRegs[1]},
18635ffd83dbSDimitry Andric       {getOrCreateVReg(*CI.getOperand(0)), getOrCreateVReg(*CI.getOperand(1))});
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   return true;
18660b57cec5SDimitry Andric }
18670b57cec5SDimitry Andric 
translateFixedPointIntrinsic(unsigned Op,const CallInst & CI,MachineIRBuilder & MIRBuilder)1868e8d8bef9SDimitry Andric bool IRTranslator::translateFixedPointIntrinsic(unsigned Op, const CallInst &CI,
1869e8d8bef9SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
1870e8d8bef9SDimitry Andric   Register Dst = getOrCreateVReg(CI);
1871e8d8bef9SDimitry Andric   Register Src0 = getOrCreateVReg(*CI.getOperand(0));
1872e8d8bef9SDimitry Andric   Register Src1 = getOrCreateVReg(*CI.getOperand(1));
1873e8d8bef9SDimitry Andric   uint64_t Scale = cast<ConstantInt>(CI.getOperand(2))->getZExtValue();
1874e8d8bef9SDimitry Andric   MIRBuilder.buildInstr(Op, {Dst}, { Src0, Src1, Scale });
1875e8d8bef9SDimitry Andric   return true;
1876e8d8bef9SDimitry Andric }
1877e8d8bef9SDimitry Andric 
getSimpleIntrinsicOpcode(Intrinsic::ID ID)18780b57cec5SDimitry Andric unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
18790b57cec5SDimitry Andric   switch (ID) {
18800b57cec5SDimitry Andric     default:
18810b57cec5SDimitry Andric       break;
18820fca6ea1SDimitry Andric     case Intrinsic::acos:
18830fca6ea1SDimitry Andric       return TargetOpcode::G_FACOS;
18840fca6ea1SDimitry Andric     case Intrinsic::asin:
18850fca6ea1SDimitry Andric       return TargetOpcode::G_FASIN;
18860fca6ea1SDimitry Andric     case Intrinsic::atan:
18870fca6ea1SDimitry Andric       return TargetOpcode::G_FATAN;
18880b57cec5SDimitry Andric     case Intrinsic::bswap:
18890b57cec5SDimitry Andric       return TargetOpcode::G_BSWAP;
18908bcb0991SDimitry Andric     case Intrinsic::bitreverse:
18918bcb0991SDimitry Andric       return TargetOpcode::G_BITREVERSE;
18925ffd83dbSDimitry Andric     case Intrinsic::fshl:
18935ffd83dbSDimitry Andric       return TargetOpcode::G_FSHL;
18945ffd83dbSDimitry Andric     case Intrinsic::fshr:
18955ffd83dbSDimitry Andric       return TargetOpcode::G_FSHR;
18960b57cec5SDimitry Andric     case Intrinsic::ceil:
18970b57cec5SDimitry Andric       return TargetOpcode::G_FCEIL;
18980b57cec5SDimitry Andric     case Intrinsic::cos:
18990b57cec5SDimitry Andric       return TargetOpcode::G_FCOS;
19000fca6ea1SDimitry Andric     case Intrinsic::cosh:
19010fca6ea1SDimitry Andric       return TargetOpcode::G_FCOSH;
19020b57cec5SDimitry Andric     case Intrinsic::ctpop:
19030b57cec5SDimitry Andric       return TargetOpcode::G_CTPOP;
19040b57cec5SDimitry Andric     case Intrinsic::exp:
19050b57cec5SDimitry Andric       return TargetOpcode::G_FEXP;
19060b57cec5SDimitry Andric     case Intrinsic::exp2:
19070b57cec5SDimitry Andric       return TargetOpcode::G_FEXP2;
19085f757f3fSDimitry Andric     case Intrinsic::exp10:
19095f757f3fSDimitry Andric       return TargetOpcode::G_FEXP10;
19100b57cec5SDimitry Andric     case Intrinsic::fabs:
19110b57cec5SDimitry Andric       return TargetOpcode::G_FABS;
19120b57cec5SDimitry Andric     case Intrinsic::copysign:
19130b57cec5SDimitry Andric       return TargetOpcode::G_FCOPYSIGN;
19140b57cec5SDimitry Andric     case Intrinsic::minnum:
19150b57cec5SDimitry Andric       return TargetOpcode::G_FMINNUM;
19160b57cec5SDimitry Andric     case Intrinsic::maxnum:
19170b57cec5SDimitry Andric       return TargetOpcode::G_FMAXNUM;
19180b57cec5SDimitry Andric     case Intrinsic::minimum:
19190b57cec5SDimitry Andric       return TargetOpcode::G_FMINIMUM;
19200b57cec5SDimitry Andric     case Intrinsic::maximum:
19210b57cec5SDimitry Andric       return TargetOpcode::G_FMAXIMUM;
19220b57cec5SDimitry Andric     case Intrinsic::canonicalize:
19230b57cec5SDimitry Andric       return TargetOpcode::G_FCANONICALIZE;
19240b57cec5SDimitry Andric     case Intrinsic::floor:
19250b57cec5SDimitry Andric       return TargetOpcode::G_FFLOOR;
19260b57cec5SDimitry Andric     case Intrinsic::fma:
19270b57cec5SDimitry Andric       return TargetOpcode::G_FMA;
19280b57cec5SDimitry Andric     case Intrinsic::log:
19290b57cec5SDimitry Andric       return TargetOpcode::G_FLOG;
19300b57cec5SDimitry Andric     case Intrinsic::log2:
19310b57cec5SDimitry Andric       return TargetOpcode::G_FLOG2;
19320b57cec5SDimitry Andric     case Intrinsic::log10:
19330b57cec5SDimitry Andric       return TargetOpcode::G_FLOG10;
193406c3fb27SDimitry Andric     case Intrinsic::ldexp:
193506c3fb27SDimitry Andric       return TargetOpcode::G_FLDEXP;
19360b57cec5SDimitry Andric     case Intrinsic::nearbyint:
19370b57cec5SDimitry Andric       return TargetOpcode::G_FNEARBYINT;
19380b57cec5SDimitry Andric     case Intrinsic::pow:
19390b57cec5SDimitry Andric       return TargetOpcode::G_FPOW;
1940e8d8bef9SDimitry Andric     case Intrinsic::powi:
1941e8d8bef9SDimitry Andric       return TargetOpcode::G_FPOWI;
19420b57cec5SDimitry Andric     case Intrinsic::rint:
19430b57cec5SDimitry Andric       return TargetOpcode::G_FRINT;
19440b57cec5SDimitry Andric     case Intrinsic::round:
19450b57cec5SDimitry Andric       return TargetOpcode::G_INTRINSIC_ROUND;
1946e8d8bef9SDimitry Andric     case Intrinsic::roundeven:
1947e8d8bef9SDimitry Andric       return TargetOpcode::G_INTRINSIC_ROUNDEVEN;
19480b57cec5SDimitry Andric     case Intrinsic::sin:
19490b57cec5SDimitry Andric       return TargetOpcode::G_FSIN;
19500fca6ea1SDimitry Andric     case Intrinsic::sinh:
19510fca6ea1SDimitry Andric       return TargetOpcode::G_FSINH;
19520b57cec5SDimitry Andric     case Intrinsic::sqrt:
19530b57cec5SDimitry Andric       return TargetOpcode::G_FSQRT;
19540fca6ea1SDimitry Andric     case Intrinsic::tan:
19550fca6ea1SDimitry Andric       return TargetOpcode::G_FTAN;
19560fca6ea1SDimitry Andric     case Intrinsic::tanh:
19570fca6ea1SDimitry Andric       return TargetOpcode::G_FTANH;
19580b57cec5SDimitry Andric     case Intrinsic::trunc:
19590b57cec5SDimitry Andric       return TargetOpcode::G_INTRINSIC_TRUNC;
1960480093f4SDimitry Andric     case Intrinsic::readcyclecounter:
1961480093f4SDimitry Andric       return TargetOpcode::G_READCYCLECOUNTER;
19620fca6ea1SDimitry Andric     case Intrinsic::readsteadycounter:
19630fca6ea1SDimitry Andric       return TargetOpcode::G_READSTEADYCOUNTER;
19645ffd83dbSDimitry Andric     case Intrinsic::ptrmask:
19655ffd83dbSDimitry Andric       return TargetOpcode::G_PTRMASK;
1966e8d8bef9SDimitry Andric     case Intrinsic::lrint:
1967e8d8bef9SDimitry Andric       return TargetOpcode::G_INTRINSIC_LRINT;
19680fca6ea1SDimitry Andric     case Intrinsic::llrint:
19690fca6ea1SDimitry Andric       return TargetOpcode::G_INTRINSIC_LLRINT;
1970e8d8bef9SDimitry Andric     // FADD/FMUL require checking the FMF, so are handled elsewhere.
1971e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_fmin:
1972e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_FMIN;
1973e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_fmax:
1974e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_FMAX;
19755f757f3fSDimitry Andric     case Intrinsic::vector_reduce_fminimum:
19765f757f3fSDimitry Andric       return TargetOpcode::G_VECREDUCE_FMINIMUM;
19775f757f3fSDimitry Andric     case Intrinsic::vector_reduce_fmaximum:
19785f757f3fSDimitry Andric       return TargetOpcode::G_VECREDUCE_FMAXIMUM;
1979e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_add:
1980e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_ADD;
1981e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_mul:
1982e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_MUL;
1983e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_and:
1984e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_AND;
1985e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_or:
1986e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_OR;
1987e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_xor:
1988e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_XOR;
1989e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_smax:
1990e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_SMAX;
1991e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_smin:
1992e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_SMIN;
1993e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_umax:
1994e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_UMAX;
1995e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_umin:
1996e8d8bef9SDimitry Andric       return TargetOpcode::G_VECREDUCE_UMIN;
19970fca6ea1SDimitry Andric     case Intrinsic::experimental_vector_compress:
19980fca6ea1SDimitry Andric       return TargetOpcode::G_VECTOR_COMPRESS;
1999349cc55cSDimitry Andric     case Intrinsic::lround:
2000349cc55cSDimitry Andric       return TargetOpcode::G_LROUND;
2001349cc55cSDimitry Andric     case Intrinsic::llround:
2002349cc55cSDimitry Andric       return TargetOpcode::G_LLROUND;
2003297eecfbSDimitry Andric     case Intrinsic::get_fpenv:
2004297eecfbSDimitry Andric       return TargetOpcode::G_GET_FPENV;
20055f757f3fSDimitry Andric     case Intrinsic::get_fpmode:
20065f757f3fSDimitry Andric       return TargetOpcode::G_GET_FPMODE;
20070b57cec5SDimitry Andric   }
20080b57cec5SDimitry Andric   return Intrinsic::not_intrinsic;
20090b57cec5SDimitry Andric }
20100b57cec5SDimitry Andric 
translateSimpleIntrinsic(const CallInst & CI,Intrinsic::ID ID,MachineIRBuilder & MIRBuilder)20110b57cec5SDimitry Andric bool IRTranslator::translateSimpleIntrinsic(const CallInst &CI,
20120b57cec5SDimitry Andric                                             Intrinsic::ID ID,
20130b57cec5SDimitry Andric                                             MachineIRBuilder &MIRBuilder) {
20140b57cec5SDimitry Andric 
20150b57cec5SDimitry Andric   unsigned Op = getSimpleIntrinsicOpcode(ID);
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   // Is this a simple intrinsic?
20180b57cec5SDimitry Andric   if (Op == Intrinsic::not_intrinsic)
20190b57cec5SDimitry Andric     return false;
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   // Yes. Let's translate it.
20220b57cec5SDimitry Andric   SmallVector<llvm::SrcOp, 4> VRegs;
2023fcaf7f86SDimitry Andric   for (const auto &Arg : CI.args())
20240b57cec5SDimitry Andric     VRegs.push_back(getOrCreateVReg(*Arg));
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   MIRBuilder.buildInstr(Op, {getOrCreateVReg(CI)}, VRegs,
20270b57cec5SDimitry Andric                         MachineInstr::copyFlagsFromInstruction(CI));
20280b57cec5SDimitry Andric   return true;
20290b57cec5SDimitry Andric }
20300b57cec5SDimitry Andric 
20315ffd83dbSDimitry Andric // TODO: Include ConstainedOps.def when all strict instructions are defined.
getConstrainedOpcode(Intrinsic::ID ID)20325ffd83dbSDimitry Andric static unsigned getConstrainedOpcode(Intrinsic::ID ID) {
20335ffd83dbSDimitry Andric   switch (ID) {
20345ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_fadd:
20355ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FADD;
20365ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_fsub:
20375ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FSUB;
20385ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_fmul:
20395ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FMUL;
20405ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_fdiv:
20415ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FDIV;
20425ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_frem:
20435ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FREM;
20445ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_fma:
20455ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FMA;
20465ffd83dbSDimitry Andric   case Intrinsic::experimental_constrained_sqrt:
20475ffd83dbSDimitry Andric     return TargetOpcode::G_STRICT_FSQRT;
204806c3fb27SDimitry Andric   case Intrinsic::experimental_constrained_ldexp:
204906c3fb27SDimitry Andric     return TargetOpcode::G_STRICT_FLDEXP;
20505ffd83dbSDimitry Andric   default:
20515ffd83dbSDimitry Andric     return 0;
20525ffd83dbSDimitry Andric   }
20535ffd83dbSDimitry Andric }
20545ffd83dbSDimitry Andric 
translateConstrainedFPIntrinsic(const ConstrainedFPIntrinsic & FPI,MachineIRBuilder & MIRBuilder)20555ffd83dbSDimitry Andric bool IRTranslator::translateConstrainedFPIntrinsic(
20565ffd83dbSDimitry Andric   const ConstrainedFPIntrinsic &FPI, MachineIRBuilder &MIRBuilder) {
205781ad6265SDimitry Andric   fp::ExceptionBehavior EB = *FPI.getExceptionBehavior();
20585ffd83dbSDimitry Andric 
20595ffd83dbSDimitry Andric   unsigned Opcode = getConstrainedOpcode(FPI.getIntrinsicID());
20605ffd83dbSDimitry Andric   if (!Opcode)
20615ffd83dbSDimitry Andric     return false;
20625ffd83dbSDimitry Andric 
206306c3fb27SDimitry Andric   uint32_t Flags = MachineInstr::copyFlagsFromInstruction(FPI);
20645ffd83dbSDimitry Andric   if (EB == fp::ExceptionBehavior::ebIgnore)
20655ffd83dbSDimitry Andric     Flags |= MachineInstr::NoFPExcept;
20665ffd83dbSDimitry Andric 
20675ffd83dbSDimitry Andric   SmallVector<llvm::SrcOp, 4> VRegs;
20680fca6ea1SDimitry Andric   for (unsigned I = 0, E = FPI.getNonMetadataArgCount(); I != E; ++I)
20690fca6ea1SDimitry Andric     VRegs.push_back(getOrCreateVReg(*FPI.getArgOperand(I)));
20705ffd83dbSDimitry Andric 
20715ffd83dbSDimitry Andric   MIRBuilder.buildInstr(Opcode, {getOrCreateVReg(FPI)}, VRegs, Flags);
20725ffd83dbSDimitry Andric   return true;
20735ffd83dbSDimitry Andric }
20745ffd83dbSDimitry Andric 
getArgPhysReg(Argument & Arg)207506c3fb27SDimitry Andric std::optional<MCRegister> IRTranslator::getArgPhysReg(Argument &Arg) {
207606c3fb27SDimitry Andric   auto VRegs = getOrCreateVRegs(Arg);
207706c3fb27SDimitry Andric   if (VRegs.size() != 1)
207806c3fb27SDimitry Andric     return std::nullopt;
207906c3fb27SDimitry Andric 
208006c3fb27SDimitry Andric   // Arguments are lowered as a copy of a livein physical register.
208106c3fb27SDimitry Andric   auto *VRegDef = MF->getRegInfo().getVRegDef(VRegs[0]);
208206c3fb27SDimitry Andric   if (!VRegDef || !VRegDef->isCopy())
208306c3fb27SDimitry Andric     return std::nullopt;
208406c3fb27SDimitry Andric   return VRegDef->getOperand(1).getReg().asMCReg();
208506c3fb27SDimitry Andric }
208606c3fb27SDimitry Andric 
translateIfEntryValueArgument(bool isDeclare,Value * Val,const DILocalVariable * Var,const DIExpression * Expr,const DebugLoc & DL,MachineIRBuilder & MIRBuilder)20877a6dacacSDimitry Andric bool IRTranslator::translateIfEntryValueArgument(bool isDeclare, Value *Val,
20887a6dacacSDimitry Andric                                                  const DILocalVariable *Var,
20897a6dacacSDimitry Andric                                                  const DIExpression *Expr,
20907a6dacacSDimitry Andric                                                  const DebugLoc &DL,
209106c3fb27SDimitry Andric                                                  MachineIRBuilder &MIRBuilder) {
20927a6dacacSDimitry Andric   auto *Arg = dyn_cast<Argument>(Val);
209306c3fb27SDimitry Andric   if (!Arg)
209406c3fb27SDimitry Andric     return false;
209506c3fb27SDimitry Andric 
209606c3fb27SDimitry Andric   if (!Expr->isEntryValue())
209706c3fb27SDimitry Andric     return false;
209806c3fb27SDimitry Andric 
209906c3fb27SDimitry Andric   std::optional<MCRegister> PhysReg = getArgPhysReg(*Arg);
210006c3fb27SDimitry Andric   if (!PhysReg) {
21017a6dacacSDimitry Andric     LLVM_DEBUG(dbgs() << "Dropping dbg." << (isDeclare ? "declare" : "value")
21027a6dacacSDimitry Andric                       << ": expression is entry_value but "
21037a6dacacSDimitry Andric                       << "couldn't find a physical register\n");
21047a6dacacSDimitry Andric     LLVM_DEBUG(dbgs() << *Var << "\n");
210506c3fb27SDimitry Andric     return true;
210606c3fb27SDimitry Andric   }
210706c3fb27SDimitry Andric 
21087a6dacacSDimitry Andric   if (isDeclare) {
21095f757f3fSDimitry Andric     // Append an op deref to account for the fact that this is a dbg_declare.
21105f757f3fSDimitry Andric     Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
21117a6dacacSDimitry Andric     MF->setVariableDbgInfo(Var, Expr, *PhysReg, DL);
21127a6dacacSDimitry Andric   } else {
21137a6dacacSDimitry Andric     MIRBuilder.buildDirectDbgValue(*PhysReg, Var, Expr);
21147a6dacacSDimitry Andric   }
21157a6dacacSDimitry Andric 
211606c3fb27SDimitry Andric   return true;
211706c3fb27SDimitry Andric }
211806c3fb27SDimitry Andric 
getConvOpcode(Intrinsic::ID ID)21190fca6ea1SDimitry Andric static unsigned getConvOpcode(Intrinsic::ID ID) {
21200fca6ea1SDimitry Andric   switch (ID) {
21210fca6ea1SDimitry Andric   default:
21220fca6ea1SDimitry Andric     llvm_unreachable("Unexpected intrinsic");
21230fca6ea1SDimitry Andric   case Intrinsic::experimental_convergence_anchor:
21240fca6ea1SDimitry Andric     return TargetOpcode::CONVERGENCECTRL_ANCHOR;
21250fca6ea1SDimitry Andric   case Intrinsic::experimental_convergence_entry:
21260fca6ea1SDimitry Andric     return TargetOpcode::CONVERGENCECTRL_ENTRY;
21270fca6ea1SDimitry Andric   case Intrinsic::experimental_convergence_loop:
21280fca6ea1SDimitry Andric     return TargetOpcode::CONVERGENCECTRL_LOOP;
21290fca6ea1SDimitry Andric   }
21300fca6ea1SDimitry Andric }
21310fca6ea1SDimitry Andric 
translateConvergenceControlIntrinsic(const CallInst & CI,Intrinsic::ID ID,MachineIRBuilder & MIRBuilder)21320fca6ea1SDimitry Andric bool IRTranslator::translateConvergenceControlIntrinsic(
21330fca6ea1SDimitry Andric     const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder) {
21340fca6ea1SDimitry Andric   MachineInstrBuilder MIB = MIRBuilder.buildInstr(getConvOpcode(ID));
21350fca6ea1SDimitry Andric   Register OutputReg = getOrCreateConvergenceTokenVReg(CI);
21360fca6ea1SDimitry Andric   MIB.addDef(OutputReg);
21370fca6ea1SDimitry Andric 
21380fca6ea1SDimitry Andric   if (ID == Intrinsic::experimental_convergence_loop) {
21390fca6ea1SDimitry Andric     auto Bundle = CI.getOperandBundle(LLVMContext::OB_convergencectrl);
21400fca6ea1SDimitry Andric     assert(Bundle && "Expected a convergence control token.");
21410fca6ea1SDimitry Andric     Register InputReg =
21420fca6ea1SDimitry Andric         getOrCreateConvergenceTokenVReg(*Bundle->Inputs[0].get());
21430fca6ea1SDimitry Andric     MIB.addUse(InputReg);
21440fca6ea1SDimitry Andric   }
21450fca6ea1SDimitry Andric 
21460fca6ea1SDimitry Andric   return true;
21470fca6ea1SDimitry Andric }
21480fca6ea1SDimitry Andric 
translateKnownIntrinsic(const CallInst & CI,Intrinsic::ID ID,MachineIRBuilder & MIRBuilder)21490b57cec5SDimitry Andric bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
21500b57cec5SDimitry Andric                                            MachineIRBuilder &MIRBuilder) {
2151fe6060f1SDimitry Andric   if (auto *MI = dyn_cast<AnyMemIntrinsic>(&CI)) {
2152fe6060f1SDimitry Andric     if (ORE->enabled()) {
2153bdd1243dSDimitry Andric       if (MemoryOpRemark::canHandle(MI, *LibInfo)) {
2154bdd1243dSDimitry Andric         MemoryOpRemark R(*ORE, "gisel-irtranslator-memsize", *DL, *LibInfo);
2155fe6060f1SDimitry Andric         R.visit(MI);
2156fe6060f1SDimitry Andric       }
2157fe6060f1SDimitry Andric     }
2158fe6060f1SDimitry Andric   }
21590b57cec5SDimitry Andric 
21600b57cec5SDimitry Andric   // If this is a simple intrinsic (that is, we just need to add a def of
21610b57cec5SDimitry Andric   // a vreg, and uses for each arg operand, then translate it.
21620b57cec5SDimitry Andric   if (translateSimpleIntrinsic(CI, ID, MIRBuilder))
21630b57cec5SDimitry Andric     return true;
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric   switch (ID) {
21660b57cec5SDimitry Andric   default:
21670b57cec5SDimitry Andric     break;
21680b57cec5SDimitry Andric   case Intrinsic::lifetime_start:
21690b57cec5SDimitry Andric   case Intrinsic::lifetime_end: {
21700b57cec5SDimitry Andric     // No stack colouring in O0, discard region information.
21715f757f3fSDimitry Andric     if (MF->getTarget().getOptLevel() == CodeGenOptLevel::None)
21720b57cec5SDimitry Andric       return true;
21730b57cec5SDimitry Andric 
21740b57cec5SDimitry Andric     unsigned Op = ID == Intrinsic::lifetime_start ? TargetOpcode::LIFETIME_START
21750b57cec5SDimitry Andric                                                   : TargetOpcode::LIFETIME_END;
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric     // Get the underlying objects for the location passed on the lifetime
21780b57cec5SDimitry Andric     // marker.
21790b57cec5SDimitry Andric     SmallVector<const Value *, 4> Allocas;
2180e8d8bef9SDimitry Andric     getUnderlyingObjects(CI.getArgOperand(1), Allocas);
21810b57cec5SDimitry Andric 
21820b57cec5SDimitry Andric     // Iterate over each underlying object, creating lifetime markers for each
21830b57cec5SDimitry Andric     // static alloca. Quit if we find a non-static alloca.
21840b57cec5SDimitry Andric     for (const Value *V : Allocas) {
21850b57cec5SDimitry Andric       const AllocaInst *AI = dyn_cast<AllocaInst>(V);
21860b57cec5SDimitry Andric       if (!AI)
21870b57cec5SDimitry Andric         continue;
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric       if (!AI->isStaticAlloca())
21900b57cec5SDimitry Andric         return true;
21910b57cec5SDimitry Andric 
21920b57cec5SDimitry Andric       MIRBuilder.buildInstr(Op).addFrameIndex(getOrCreateFrameIndex(*AI));
21930b57cec5SDimitry Andric     }
21940b57cec5SDimitry Andric     return true;
21950b57cec5SDimitry Andric   }
21960b57cec5SDimitry Andric   case Intrinsic::dbg_declare: {
21970b57cec5SDimitry Andric     const DbgDeclareInst &DI = cast<DbgDeclareInst>(CI);
21980b57cec5SDimitry Andric     assert(DI.getVariable() && "Missing variable");
21997a6dacacSDimitry Andric     translateDbgDeclareRecord(DI.getAddress(), DI.hasArgList(), DI.getVariable(),
22007a6dacacSDimitry Andric                        DI.getExpression(), DI.getDebugLoc(), MIRBuilder);
22010b57cec5SDimitry Andric     return true;
22020b57cec5SDimitry Andric   }
22030b57cec5SDimitry Andric   case Intrinsic::dbg_label: {
22040b57cec5SDimitry Andric     const DbgLabelInst &DI = cast<DbgLabelInst>(CI);
22050b57cec5SDimitry Andric     assert(DI.getLabel() && "Missing label");
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric     assert(DI.getLabel()->isValidLocationForIntrinsic(
22080b57cec5SDimitry Andric                MIRBuilder.getDebugLoc()) &&
22090b57cec5SDimitry Andric            "Expected inlined-at fields to agree");
22100b57cec5SDimitry Andric 
22110b57cec5SDimitry Andric     MIRBuilder.buildDbgLabel(DI.getLabel());
22120b57cec5SDimitry Andric     return true;
22130b57cec5SDimitry Andric   }
22140b57cec5SDimitry Andric   case Intrinsic::vaend:
22150b57cec5SDimitry Andric     // No target I know of cares about va_end. Certainly no in-tree target
22160b57cec5SDimitry Andric     // does. Simplest intrinsic ever!
22170b57cec5SDimitry Andric     return true;
22180b57cec5SDimitry Andric   case Intrinsic::vastart: {
22190b57cec5SDimitry Andric     Value *Ptr = CI.getArgOperand(0);
22200fca6ea1SDimitry Andric     unsigned ListSize = TLI->getVaListSizeInBits(*DL) / 8;
22215f757f3fSDimitry Andric     Align Alignment = getKnownAlignment(Ptr, *DL);
22220b57cec5SDimitry Andric 
22235ffd83dbSDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::G_VASTART, {}, {getOrCreateVReg(*Ptr)})
22245ffd83dbSDimitry Andric         .addMemOperand(MF->getMachineMemOperand(MachinePointerInfo(Ptr),
22255ffd83dbSDimitry Andric                                                 MachineMemOperand::MOStore,
22265f757f3fSDimitry Andric                                                 ListSize, Alignment));
22270b57cec5SDimitry Andric     return true;
22280b57cec5SDimitry Andric   }
22290fca6ea1SDimitry Andric   case Intrinsic::dbg_assign:
22300fca6ea1SDimitry Andric     // A dbg.assign is a dbg.value with more information about stack locations,
22310fca6ea1SDimitry Andric     // typically produced during optimisation of variables with leaked
22320fca6ea1SDimitry Andric     // addresses. We can treat it like a normal dbg_value intrinsic here; to
22330fca6ea1SDimitry Andric     // benefit from the full analysis of stack/SSA locations, GlobalISel would
22340fca6ea1SDimitry Andric     // need to register for and use the AssignmentTrackingAnalysis pass.
22350fca6ea1SDimitry Andric     [[fallthrough]];
22360b57cec5SDimitry Andric   case Intrinsic::dbg_value: {
22370b57cec5SDimitry Andric     // This form of DBG_VALUE is target-independent.
22380b57cec5SDimitry Andric     const DbgValueInst &DI = cast<DbgValueInst>(CI);
22397a6dacacSDimitry Andric     translateDbgValueRecord(DI.getValue(), DI.hasArgList(), DI.getVariable(),
22407a6dacacSDimitry Andric                        DI.getExpression(), DI.getDebugLoc(), MIRBuilder);
22410b57cec5SDimitry Andric     return true;
22420b57cec5SDimitry Andric   }
22430b57cec5SDimitry Andric   case Intrinsic::uadd_with_overflow:
22440b57cec5SDimitry Andric     return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDO, MIRBuilder);
22450b57cec5SDimitry Andric   case Intrinsic::sadd_with_overflow:
22460b57cec5SDimitry Andric     return translateOverflowIntrinsic(CI, TargetOpcode::G_SADDO, MIRBuilder);
22470b57cec5SDimitry Andric   case Intrinsic::usub_with_overflow:
22480b57cec5SDimitry Andric     return translateOverflowIntrinsic(CI, TargetOpcode::G_USUBO, MIRBuilder);
22490b57cec5SDimitry Andric   case Intrinsic::ssub_with_overflow:
22500b57cec5SDimitry Andric     return translateOverflowIntrinsic(CI, TargetOpcode::G_SSUBO, MIRBuilder);
22510b57cec5SDimitry Andric   case Intrinsic::umul_with_overflow:
22520b57cec5SDimitry Andric     return translateOverflowIntrinsic(CI, TargetOpcode::G_UMULO, MIRBuilder);
22530b57cec5SDimitry Andric   case Intrinsic::smul_with_overflow:
22540b57cec5SDimitry Andric     return translateOverflowIntrinsic(CI, TargetOpcode::G_SMULO, MIRBuilder);
22555ffd83dbSDimitry Andric   case Intrinsic::uadd_sat:
22565ffd83dbSDimitry Andric     return translateBinaryOp(TargetOpcode::G_UADDSAT, CI, MIRBuilder);
22575ffd83dbSDimitry Andric   case Intrinsic::sadd_sat:
22585ffd83dbSDimitry Andric     return translateBinaryOp(TargetOpcode::G_SADDSAT, CI, MIRBuilder);
22595ffd83dbSDimitry Andric   case Intrinsic::usub_sat:
22605ffd83dbSDimitry Andric     return translateBinaryOp(TargetOpcode::G_USUBSAT, CI, MIRBuilder);
22615ffd83dbSDimitry Andric   case Intrinsic::ssub_sat:
22625ffd83dbSDimitry Andric     return translateBinaryOp(TargetOpcode::G_SSUBSAT, CI, MIRBuilder);
2263e8d8bef9SDimitry Andric   case Intrinsic::ushl_sat:
2264e8d8bef9SDimitry Andric     return translateBinaryOp(TargetOpcode::G_USHLSAT, CI, MIRBuilder);
2265e8d8bef9SDimitry Andric   case Intrinsic::sshl_sat:
2266e8d8bef9SDimitry Andric     return translateBinaryOp(TargetOpcode::G_SSHLSAT, CI, MIRBuilder);
2267e8d8bef9SDimitry Andric   case Intrinsic::umin:
2268e8d8bef9SDimitry Andric     return translateBinaryOp(TargetOpcode::G_UMIN, CI, MIRBuilder);
2269e8d8bef9SDimitry Andric   case Intrinsic::umax:
2270e8d8bef9SDimitry Andric     return translateBinaryOp(TargetOpcode::G_UMAX, CI, MIRBuilder);
2271e8d8bef9SDimitry Andric   case Intrinsic::smin:
2272e8d8bef9SDimitry Andric     return translateBinaryOp(TargetOpcode::G_SMIN, CI, MIRBuilder);
2273e8d8bef9SDimitry Andric   case Intrinsic::smax:
2274e8d8bef9SDimitry Andric     return translateBinaryOp(TargetOpcode::G_SMAX, CI, MIRBuilder);
2275e8d8bef9SDimitry Andric   case Intrinsic::abs:
2276e8d8bef9SDimitry Andric     // TODO: Preserve "int min is poison" arg in GMIR?
2277e8d8bef9SDimitry Andric     return translateUnaryOp(TargetOpcode::G_ABS, CI, MIRBuilder);
2278e8d8bef9SDimitry Andric   case Intrinsic::smul_fix:
2279e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_SMULFIX, CI, MIRBuilder);
2280e8d8bef9SDimitry Andric   case Intrinsic::umul_fix:
2281e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_UMULFIX, CI, MIRBuilder);
2282e8d8bef9SDimitry Andric   case Intrinsic::smul_fix_sat:
2283e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_SMULFIXSAT, CI, MIRBuilder);
2284e8d8bef9SDimitry Andric   case Intrinsic::umul_fix_sat:
2285e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_UMULFIXSAT, CI, MIRBuilder);
2286e8d8bef9SDimitry Andric   case Intrinsic::sdiv_fix:
2287e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_SDIVFIX, CI, MIRBuilder);
2288e8d8bef9SDimitry Andric   case Intrinsic::udiv_fix:
2289e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_UDIVFIX, CI, MIRBuilder);
2290e8d8bef9SDimitry Andric   case Intrinsic::sdiv_fix_sat:
2291e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_SDIVFIXSAT, CI, MIRBuilder);
2292e8d8bef9SDimitry Andric   case Intrinsic::udiv_fix_sat:
2293e8d8bef9SDimitry Andric     return translateFixedPointIntrinsic(TargetOpcode::G_UDIVFIXSAT, CI, MIRBuilder);
22940b57cec5SDimitry Andric   case Intrinsic::fmuladd: {
22950b57cec5SDimitry Andric     const TargetMachine &TM = MF->getTarget();
22960b57cec5SDimitry Andric     Register Dst = getOrCreateVReg(CI);
22970b57cec5SDimitry Andric     Register Op0 = getOrCreateVReg(*CI.getArgOperand(0));
22980b57cec5SDimitry Andric     Register Op1 = getOrCreateVReg(*CI.getArgOperand(1));
22990b57cec5SDimitry Andric     Register Op2 = getOrCreateVReg(*CI.getArgOperand(2));
23000b57cec5SDimitry Andric     if (TM.Options.AllowFPOpFusion != FPOpFusion::Strict &&
23010fca6ea1SDimitry Andric         TLI->isFMAFasterThanFMulAndFAdd(*MF,
23020fca6ea1SDimitry Andric                                         TLI->getValueType(*DL, CI.getType()))) {
23030b57cec5SDimitry Andric       // TODO: Revisit this to see if we should move this part of the
23040b57cec5SDimitry Andric       // lowering to the combiner.
23055ffd83dbSDimitry Andric       MIRBuilder.buildFMA(Dst, Op0, Op1, Op2,
23060b57cec5SDimitry Andric                           MachineInstr::copyFlagsFromInstruction(CI));
23070b57cec5SDimitry Andric     } else {
23080b57cec5SDimitry Andric       LLT Ty = getLLTForType(*CI.getType(), *DL);
23095ffd83dbSDimitry Andric       auto FMul = MIRBuilder.buildFMul(
23105ffd83dbSDimitry Andric           Ty, Op0, Op1, MachineInstr::copyFlagsFromInstruction(CI));
23115ffd83dbSDimitry Andric       MIRBuilder.buildFAdd(Dst, FMul, Op2,
23120b57cec5SDimitry Andric                            MachineInstr::copyFlagsFromInstruction(CI));
23130b57cec5SDimitry Andric     }
23140b57cec5SDimitry Andric     return true;
23150b57cec5SDimitry Andric   }
2316e8d8bef9SDimitry Andric   case Intrinsic::convert_from_fp16:
2317e8d8bef9SDimitry Andric     // FIXME: This intrinsic should probably be removed from the IR.
2318e8d8bef9SDimitry Andric     MIRBuilder.buildFPExt(getOrCreateVReg(CI),
2319e8d8bef9SDimitry Andric                           getOrCreateVReg(*CI.getArgOperand(0)),
2320e8d8bef9SDimitry Andric                           MachineInstr::copyFlagsFromInstruction(CI));
2321e8d8bef9SDimitry Andric     return true;
2322e8d8bef9SDimitry Andric   case Intrinsic::convert_to_fp16:
2323e8d8bef9SDimitry Andric     // FIXME: This intrinsic should probably be removed from the IR.
2324e8d8bef9SDimitry Andric     MIRBuilder.buildFPTrunc(getOrCreateVReg(CI),
2325e8d8bef9SDimitry Andric                             getOrCreateVReg(*CI.getArgOperand(0)),
2326e8d8bef9SDimitry Andric                             MachineInstr::copyFlagsFromInstruction(CI));
2327e8d8bef9SDimitry Andric     return true;
232806c3fb27SDimitry Andric   case Intrinsic::frexp: {
232906c3fb27SDimitry Andric     ArrayRef<Register> VRegs = getOrCreateVRegs(CI);
233006c3fb27SDimitry Andric     MIRBuilder.buildFFrexp(VRegs[0], VRegs[1],
233106c3fb27SDimitry Andric                            getOrCreateVReg(*CI.getArgOperand(0)),
233206c3fb27SDimitry Andric                            MachineInstr::copyFlagsFromInstruction(CI));
233306c3fb27SDimitry Andric     return true;
233406c3fb27SDimitry Andric   }
2335fe6060f1SDimitry Andric   case Intrinsic::memcpy_inline:
2336fe6060f1SDimitry Andric     return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMCPY_INLINE);
23370b57cec5SDimitry Andric   case Intrinsic::memcpy:
2338e8d8bef9SDimitry Andric     return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMCPY);
23390b57cec5SDimitry Andric   case Intrinsic::memmove:
2340e8d8bef9SDimitry Andric     return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMMOVE);
23410b57cec5SDimitry Andric   case Intrinsic::memset:
2342e8d8bef9SDimitry Andric     return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMSET);
23430b57cec5SDimitry Andric   case Intrinsic::eh_typeid_for: {
23440b57cec5SDimitry Andric     GlobalValue *GV = ExtractTypeInfo(CI.getArgOperand(0));
23450b57cec5SDimitry Andric     Register Reg = getOrCreateVReg(CI);
23460b57cec5SDimitry Andric     unsigned TypeID = MF->getTypeIDFor(GV);
23470b57cec5SDimitry Andric     MIRBuilder.buildConstant(Reg, TypeID);
23480b57cec5SDimitry Andric     return true;
23490b57cec5SDimitry Andric   }
23508bcb0991SDimitry Andric   case Intrinsic::objectsize:
23518bcb0991SDimitry Andric     llvm_unreachable("llvm.objectsize.* should have been lowered already");
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric   case Intrinsic::is_constant:
23548bcb0991SDimitry Andric     llvm_unreachable("llvm.is.constant.* should have been lowered already");
23558bcb0991SDimitry Andric 
23560b57cec5SDimitry Andric   case Intrinsic::stackguard:
23570b57cec5SDimitry Andric     getStackGuard(getOrCreateVReg(CI), MIRBuilder);
23580b57cec5SDimitry Andric     return true;
23590b57cec5SDimitry Andric   case Intrinsic::stackprotector: {
23600b57cec5SDimitry Andric     LLT PtrTy = getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
2361753f127fSDimitry Andric     Register GuardVal;
23620fca6ea1SDimitry Andric     if (TLI->useLoadStackGuardNode()) {
2363753f127fSDimitry Andric       GuardVal = MRI->createGenericVirtualRegister(PtrTy);
23640b57cec5SDimitry Andric       getStackGuard(GuardVal, MIRBuilder);
2365753f127fSDimitry Andric     } else
2366753f127fSDimitry Andric       GuardVal = getOrCreateVReg(*CI.getArgOperand(0)); // The guard's value.
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric     AllocaInst *Slot = cast<AllocaInst>(CI.getArgOperand(1));
23690b57cec5SDimitry Andric     int FI = getOrCreateFrameIndex(*Slot);
23700b57cec5SDimitry Andric     MF->getFrameInfo().setStackProtectorIndex(FI);
23710b57cec5SDimitry Andric 
23720b57cec5SDimitry Andric     MIRBuilder.buildStore(
23730b57cec5SDimitry Andric         GuardVal, getOrCreateVReg(*Slot),
23740b57cec5SDimitry Andric         *MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(*MF, FI),
23750b57cec5SDimitry Andric                                   MachineMemOperand::MOStore |
23760b57cec5SDimitry Andric                                       MachineMemOperand::MOVolatile,
2377fe6060f1SDimitry Andric                                   PtrTy, Align(8)));
23780b57cec5SDimitry Andric     return true;
23790b57cec5SDimitry Andric   }
23800b57cec5SDimitry Andric   case Intrinsic::stacksave: {
23815f757f3fSDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::G_STACKSAVE, {getOrCreateVReg(CI)}, {});
23820b57cec5SDimitry Andric     return true;
23830b57cec5SDimitry Andric   }
23840b57cec5SDimitry Andric   case Intrinsic::stackrestore: {
23855f757f3fSDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::G_STACKRESTORE, {},
23865f757f3fSDimitry Andric                           {getOrCreateVReg(*CI.getArgOperand(0))});
23870b57cec5SDimitry Andric     return true;
23880b57cec5SDimitry Andric   }
23890b57cec5SDimitry Andric   case Intrinsic::cttz:
23900b57cec5SDimitry Andric   case Intrinsic::ctlz: {
23910b57cec5SDimitry Andric     ConstantInt *Cst = cast<ConstantInt>(CI.getArgOperand(1));
23920b57cec5SDimitry Andric     bool isTrailing = ID == Intrinsic::cttz;
23930b57cec5SDimitry Andric     unsigned Opcode = isTrailing
23940b57cec5SDimitry Andric                           ? Cst->isZero() ? TargetOpcode::G_CTTZ
23950b57cec5SDimitry Andric                                           : TargetOpcode::G_CTTZ_ZERO_UNDEF
23960b57cec5SDimitry Andric                           : Cst->isZero() ? TargetOpcode::G_CTLZ
23970b57cec5SDimitry Andric                                           : TargetOpcode::G_CTLZ_ZERO_UNDEF;
23985ffd83dbSDimitry Andric     MIRBuilder.buildInstr(Opcode, {getOrCreateVReg(CI)},
23995ffd83dbSDimitry Andric                           {getOrCreateVReg(*CI.getArgOperand(0))});
24000b57cec5SDimitry Andric     return true;
24010b57cec5SDimitry Andric   }
24020b57cec5SDimitry Andric   case Intrinsic::invariant_start: {
24030b57cec5SDimitry Andric     LLT PtrTy = getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
24040b57cec5SDimitry Andric     Register Undef = MRI->createGenericVirtualRegister(PtrTy);
24050b57cec5SDimitry Andric     MIRBuilder.buildUndef(Undef);
24060b57cec5SDimitry Andric     return true;
24070b57cec5SDimitry Andric   }
24080b57cec5SDimitry Andric   case Intrinsic::invariant_end:
24090b57cec5SDimitry Andric     return true;
2410e8d8bef9SDimitry Andric   case Intrinsic::expect:
2411e8d8bef9SDimitry Andric   case Intrinsic::annotation:
2412e8d8bef9SDimitry Andric   case Intrinsic::ptr_annotation:
2413e8d8bef9SDimitry Andric   case Intrinsic::launder_invariant_group:
2414e8d8bef9SDimitry Andric   case Intrinsic::strip_invariant_group: {
2415e8d8bef9SDimitry Andric     // Drop the intrinsic, but forward the value.
2416e8d8bef9SDimitry Andric     MIRBuilder.buildCopy(getOrCreateVReg(CI),
2417e8d8bef9SDimitry Andric                          getOrCreateVReg(*CI.getArgOperand(0)));
2418e8d8bef9SDimitry Andric     return true;
2419e8d8bef9SDimitry Andric   }
24200b57cec5SDimitry Andric   case Intrinsic::assume:
2421e8d8bef9SDimitry Andric   case Intrinsic::experimental_noalias_scope_decl:
24220b57cec5SDimitry Andric   case Intrinsic::var_annotation:
24230b57cec5SDimitry Andric   case Intrinsic::sideeffect:
24240b57cec5SDimitry Andric     // Discard annotate attributes, assumptions, and artificial side-effects.
24250b57cec5SDimitry Andric     return true;
24265ffd83dbSDimitry Andric   case Intrinsic::read_volatile_register:
2427480093f4SDimitry Andric   case Intrinsic::read_register: {
2428480093f4SDimitry Andric     Value *Arg = CI.getArgOperand(0);
24295ffd83dbSDimitry Andric     MIRBuilder
24305ffd83dbSDimitry Andric         .buildInstr(TargetOpcode::G_READ_REGISTER, {getOrCreateVReg(CI)}, {})
2431480093f4SDimitry Andric         .addMetadata(cast<MDNode>(cast<MetadataAsValue>(Arg)->getMetadata()));
2432480093f4SDimitry Andric     return true;
2433480093f4SDimitry Andric   }
24345ffd83dbSDimitry Andric   case Intrinsic::write_register: {
24355ffd83dbSDimitry Andric     Value *Arg = CI.getArgOperand(0);
24365ffd83dbSDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::G_WRITE_REGISTER)
24375ffd83dbSDimitry Andric       .addMetadata(cast<MDNode>(cast<MetadataAsValue>(Arg)->getMetadata()))
24385ffd83dbSDimitry Andric       .addUse(getOrCreateVReg(*CI.getArgOperand(1)));
24390b57cec5SDimitry Andric     return true;
24400b57cec5SDimitry Andric   }
2441e8d8bef9SDimitry Andric   case Intrinsic::localescape: {
2442e8d8bef9SDimitry Andric     MachineBasicBlock &EntryMBB = MF->front();
2443e8d8bef9SDimitry Andric     StringRef EscapedName = GlobalValue::dropLLVMManglingEscape(MF->getName());
2444e8d8bef9SDimitry Andric 
2445e8d8bef9SDimitry Andric     // Directly emit some LOCAL_ESCAPE machine instrs. Label assignment emission
2446e8d8bef9SDimitry Andric     // is the same on all targets.
2447349cc55cSDimitry Andric     for (unsigned Idx = 0, E = CI.arg_size(); Idx < E; ++Idx) {
2448e8d8bef9SDimitry Andric       Value *Arg = CI.getArgOperand(Idx)->stripPointerCasts();
2449e8d8bef9SDimitry Andric       if (isa<ConstantPointerNull>(Arg))
2450e8d8bef9SDimitry Andric         continue; // Skip null pointers. They represent a hole in index space.
2451e8d8bef9SDimitry Andric 
2452e8d8bef9SDimitry Andric       int FI = getOrCreateFrameIndex(*cast<AllocaInst>(Arg));
2453e8d8bef9SDimitry Andric       MCSymbol *FrameAllocSym =
24540fca6ea1SDimitry Andric           MF->getContext().getOrCreateFrameAllocSymbol(EscapedName, Idx);
2455e8d8bef9SDimitry Andric 
2456e8d8bef9SDimitry Andric       // This should be inserted at the start of the entry block.
2457e8d8bef9SDimitry Andric       auto LocalEscape =
2458e8d8bef9SDimitry Andric           MIRBuilder.buildInstrNoInsert(TargetOpcode::LOCAL_ESCAPE)
2459e8d8bef9SDimitry Andric               .addSym(FrameAllocSym)
2460e8d8bef9SDimitry Andric               .addFrameIndex(FI);
2461e8d8bef9SDimitry Andric 
2462e8d8bef9SDimitry Andric       EntryMBB.insert(EntryMBB.begin(), LocalEscape);
2463e8d8bef9SDimitry Andric     }
2464e8d8bef9SDimitry Andric 
2465e8d8bef9SDimitry Andric     return true;
2466e8d8bef9SDimitry Andric   }
2467e8d8bef9SDimitry Andric   case Intrinsic::vector_reduce_fadd:
2468e8d8bef9SDimitry Andric   case Intrinsic::vector_reduce_fmul: {
2469e8d8bef9SDimitry Andric     // Need to check for the reassoc flag to decide whether we want a
2470e8d8bef9SDimitry Andric     // sequential reduction opcode or not.
2471e8d8bef9SDimitry Andric     Register Dst = getOrCreateVReg(CI);
2472e8d8bef9SDimitry Andric     Register ScalarSrc = getOrCreateVReg(*CI.getArgOperand(0));
2473e8d8bef9SDimitry Andric     Register VecSrc = getOrCreateVReg(*CI.getArgOperand(1));
2474e8d8bef9SDimitry Andric     unsigned Opc = 0;
2475e8d8bef9SDimitry Andric     if (!CI.hasAllowReassoc()) {
2476e8d8bef9SDimitry Andric       // The sequential ordering case.
2477e8d8bef9SDimitry Andric       Opc = ID == Intrinsic::vector_reduce_fadd
2478e8d8bef9SDimitry Andric                 ? TargetOpcode::G_VECREDUCE_SEQ_FADD
2479e8d8bef9SDimitry Andric                 : TargetOpcode::G_VECREDUCE_SEQ_FMUL;
2480e8d8bef9SDimitry Andric       MIRBuilder.buildInstr(Opc, {Dst}, {ScalarSrc, VecSrc},
2481e8d8bef9SDimitry Andric                             MachineInstr::copyFlagsFromInstruction(CI));
2482e8d8bef9SDimitry Andric       return true;
2483e8d8bef9SDimitry Andric     }
2484e8d8bef9SDimitry Andric     // We split the operation into a separate G_FADD/G_FMUL + the reduce,
2485e8d8bef9SDimitry Andric     // since the associativity doesn't matter.
2486e8d8bef9SDimitry Andric     unsigned ScalarOpc;
2487e8d8bef9SDimitry Andric     if (ID == Intrinsic::vector_reduce_fadd) {
2488e8d8bef9SDimitry Andric       Opc = TargetOpcode::G_VECREDUCE_FADD;
2489e8d8bef9SDimitry Andric       ScalarOpc = TargetOpcode::G_FADD;
2490e8d8bef9SDimitry Andric     } else {
2491e8d8bef9SDimitry Andric       Opc = TargetOpcode::G_VECREDUCE_FMUL;
2492e8d8bef9SDimitry Andric       ScalarOpc = TargetOpcode::G_FMUL;
2493e8d8bef9SDimitry Andric     }
2494e8d8bef9SDimitry Andric     LLT DstTy = MRI->getType(Dst);
2495e8d8bef9SDimitry Andric     auto Rdx = MIRBuilder.buildInstr(
2496e8d8bef9SDimitry Andric         Opc, {DstTy}, {VecSrc}, MachineInstr::copyFlagsFromInstruction(CI));
2497e8d8bef9SDimitry Andric     MIRBuilder.buildInstr(ScalarOpc, {Dst}, {ScalarSrc, Rdx},
2498e8d8bef9SDimitry Andric                           MachineInstr::copyFlagsFromInstruction(CI));
2499e8d8bef9SDimitry Andric 
2500e8d8bef9SDimitry Andric     return true;
2501e8d8bef9SDimitry Andric   }
2502349cc55cSDimitry Andric   case Intrinsic::trap:
25030fca6ea1SDimitry Andric     return translateTrap(CI, MIRBuilder, TargetOpcode::G_TRAP);
2504349cc55cSDimitry Andric   case Intrinsic::debugtrap:
25050fca6ea1SDimitry Andric     return translateTrap(CI, MIRBuilder, TargetOpcode::G_DEBUGTRAP);
25060fca6ea1SDimitry Andric   case Intrinsic::ubsantrap:
25070fca6ea1SDimitry Andric     return translateTrap(CI, MIRBuilder, TargetOpcode::G_UBSANTRAP);
25080fca6ea1SDimitry Andric   case Intrinsic::allow_runtime_check:
25090fca6ea1SDimitry Andric   case Intrinsic::allow_ubsan_check:
25100fca6ea1SDimitry Andric     MIRBuilder.buildCopy(getOrCreateVReg(CI),
25110fca6ea1SDimitry Andric                          getOrCreateVReg(*ConstantInt::getTrue(CI.getType())));
25120fca6ea1SDimitry Andric     return true;
25135f757f3fSDimitry Andric   case Intrinsic::amdgcn_cs_chain:
25145f757f3fSDimitry Andric     return translateCallBase(CI, MIRBuilder);
251581ad6265SDimitry Andric   case Intrinsic::fptrunc_round: {
251606c3fb27SDimitry Andric     uint32_t Flags = MachineInstr::copyFlagsFromInstruction(CI);
251781ad6265SDimitry Andric 
251881ad6265SDimitry Andric     // Convert the metadata argument to a constant integer
251981ad6265SDimitry Andric     Metadata *MD = cast<MetadataAsValue>(CI.getArgOperand(1))->getMetadata();
2520bdd1243dSDimitry Andric     std::optional<RoundingMode> RoundMode =
252181ad6265SDimitry Andric         convertStrToRoundingMode(cast<MDString>(MD)->getString());
252281ad6265SDimitry Andric 
252381ad6265SDimitry Andric     // Add the Rounding mode as an integer
252481ad6265SDimitry Andric     MIRBuilder
252581ad6265SDimitry Andric         .buildInstr(TargetOpcode::G_INTRINSIC_FPTRUNC_ROUND,
252681ad6265SDimitry Andric                     {getOrCreateVReg(CI)},
252781ad6265SDimitry Andric                     {getOrCreateVReg(*CI.getArgOperand(0))}, Flags)
252881ad6265SDimitry Andric         .addImm((int)*RoundMode);
252981ad6265SDimitry Andric 
253081ad6265SDimitry Andric     return true;
253181ad6265SDimitry Andric   }
2532bdd1243dSDimitry Andric   case Intrinsic::is_fpclass: {
2533bdd1243dSDimitry Andric     Value *FpValue = CI.getOperand(0);
2534bdd1243dSDimitry Andric     ConstantInt *TestMaskValue = cast<ConstantInt>(CI.getOperand(1));
2535bdd1243dSDimitry Andric 
2536bdd1243dSDimitry Andric     MIRBuilder
2537bdd1243dSDimitry Andric         .buildInstr(TargetOpcode::G_IS_FPCLASS, {getOrCreateVReg(CI)},
2538bdd1243dSDimitry Andric                     {getOrCreateVReg(*FpValue)})
2539bdd1243dSDimitry Andric         .addImm(TestMaskValue->getZExtValue());
2540bdd1243dSDimitry Andric 
2541bdd1243dSDimitry Andric     return true;
2542bdd1243dSDimitry Andric   }
2543297eecfbSDimitry Andric   case Intrinsic::set_fpenv: {
2544297eecfbSDimitry Andric     Value *FPEnv = CI.getOperand(0);
25450fca6ea1SDimitry Andric     MIRBuilder.buildSetFPEnv(getOrCreateVReg(*FPEnv));
2546297eecfbSDimitry Andric     return true;
2547297eecfbSDimitry Andric   }
25480fca6ea1SDimitry Andric   case Intrinsic::reset_fpenv:
25490fca6ea1SDimitry Andric     MIRBuilder.buildResetFPEnv();
2550297eecfbSDimitry Andric     return true;
25515f757f3fSDimitry Andric   case Intrinsic::set_fpmode: {
25525f757f3fSDimitry Andric     Value *FPState = CI.getOperand(0);
25530fca6ea1SDimitry Andric     MIRBuilder.buildSetFPMode(getOrCreateVReg(*FPState));
25545f757f3fSDimitry Andric     return true;
25555f757f3fSDimitry Andric   }
25560fca6ea1SDimitry Andric   case Intrinsic::reset_fpmode:
25570fca6ea1SDimitry Andric     MIRBuilder.buildResetFPMode();
25580fca6ea1SDimitry Andric     return true;
25590fca6ea1SDimitry Andric   case Intrinsic::vscale: {
25600fca6ea1SDimitry Andric     MIRBuilder.buildVScale(getOrCreateVReg(CI), 1);
25615f757f3fSDimitry Andric     return true;
25625f757f3fSDimitry Andric   }
25630fca6ea1SDimitry Andric   case Intrinsic::scmp:
25640fca6ea1SDimitry Andric     MIRBuilder.buildSCmp(getOrCreateVReg(CI),
25650fca6ea1SDimitry Andric                          getOrCreateVReg(*CI.getOperand(0)),
25660fca6ea1SDimitry Andric                          getOrCreateVReg(*CI.getOperand(1)));
25670fca6ea1SDimitry Andric     return true;
25680fca6ea1SDimitry Andric   case Intrinsic::ucmp:
25690fca6ea1SDimitry Andric     MIRBuilder.buildUCmp(getOrCreateVReg(CI),
25700fca6ea1SDimitry Andric                          getOrCreateVReg(*CI.getOperand(0)),
25710fca6ea1SDimitry Andric                          getOrCreateVReg(*CI.getOperand(1)));
25720fca6ea1SDimitry Andric     return true;
25735f757f3fSDimitry Andric   case Intrinsic::prefetch: {
25745f757f3fSDimitry Andric     Value *Addr = CI.getOperand(0);
25755f757f3fSDimitry Andric     unsigned RW = cast<ConstantInt>(CI.getOperand(1))->getZExtValue();
25765f757f3fSDimitry Andric     unsigned Locality = cast<ConstantInt>(CI.getOperand(2))->getZExtValue();
25775f757f3fSDimitry Andric     unsigned CacheType = cast<ConstantInt>(CI.getOperand(3))->getZExtValue();
25785f757f3fSDimitry Andric 
25795f757f3fSDimitry Andric     auto Flags = RW ? MachineMemOperand::MOStore : MachineMemOperand::MOLoad;
25805f757f3fSDimitry Andric     auto &MMO = *MF->getMachineMemOperand(MachinePointerInfo(Addr), Flags,
25815f757f3fSDimitry Andric                                           LLT(), Align());
25825f757f3fSDimitry Andric 
25835f757f3fSDimitry Andric     MIRBuilder.buildPrefetch(getOrCreateVReg(*Addr), RW, Locality, CacheType,
25845f757f3fSDimitry Andric                              MMO);
25855f757f3fSDimitry Andric 
25865f757f3fSDimitry Andric     return true;
25875f757f3fSDimitry Andric   }
25880fca6ea1SDimitry Andric 
25890fca6ea1SDimitry Andric   case Intrinsic::vector_interleave2:
25900fca6ea1SDimitry Andric   case Intrinsic::vector_deinterleave2: {
25910fca6ea1SDimitry Andric     // Both intrinsics have at least one operand.
25920fca6ea1SDimitry Andric     Value *Op0 = CI.getOperand(0);
25930fca6ea1SDimitry Andric     LLT ResTy = getLLTForType(*Op0->getType(), MIRBuilder.getDataLayout());
25940fca6ea1SDimitry Andric     if (!ResTy.isFixedVector())
25950fca6ea1SDimitry Andric       return false;
25960fca6ea1SDimitry Andric 
25970fca6ea1SDimitry Andric     if (CI.getIntrinsicID() == Intrinsic::vector_interleave2)
25980fca6ea1SDimitry Andric       return translateVectorInterleave2Intrinsic(CI, MIRBuilder);
25990fca6ea1SDimitry Andric 
26000fca6ea1SDimitry Andric     return translateVectorDeinterleave2Intrinsic(CI, MIRBuilder);
26010fca6ea1SDimitry Andric   }
26020fca6ea1SDimitry Andric 
26035ffd83dbSDimitry Andric #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)  \
26045ffd83dbSDimitry Andric   case Intrinsic::INTRINSIC:
26055ffd83dbSDimitry Andric #include "llvm/IR/ConstrainedOps.def"
26065ffd83dbSDimitry Andric     return translateConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(CI),
26075ffd83dbSDimitry Andric                                            MIRBuilder);
26080fca6ea1SDimitry Andric   case Intrinsic::experimental_convergence_anchor:
26090fca6ea1SDimitry Andric   case Intrinsic::experimental_convergence_entry:
26100fca6ea1SDimitry Andric   case Intrinsic::experimental_convergence_loop:
26110fca6ea1SDimitry Andric     return translateConvergenceControlIntrinsic(CI, ID, MIRBuilder);
26125ffd83dbSDimitry Andric   }
26135ffd83dbSDimitry Andric   return false;
26145ffd83dbSDimitry Andric }
26155ffd83dbSDimitry Andric 
translateInlineAsm(const CallBase & CB,MachineIRBuilder & MIRBuilder)26165ffd83dbSDimitry Andric bool IRTranslator::translateInlineAsm(const CallBase &CB,
26178bcb0991SDimitry Andric                                       MachineIRBuilder &MIRBuilder) {
26185ffd83dbSDimitry Andric 
26195ffd83dbSDimitry Andric   const InlineAsmLowering *ALI = MF->getSubtarget().getInlineAsmLowering();
26205ffd83dbSDimitry Andric 
26215ffd83dbSDimitry Andric   if (!ALI) {
26225ffd83dbSDimitry Andric     LLVM_DEBUG(
26235ffd83dbSDimitry Andric         dbgs() << "Inline asm lowering is not supported for this target yet\n");
26245ffd83dbSDimitry Andric     return false;
26255ffd83dbSDimitry Andric   }
26265ffd83dbSDimitry Andric 
26275ffd83dbSDimitry Andric   return ALI->lowerInlineAsm(
26285ffd83dbSDimitry Andric       MIRBuilder, CB, [&](const Value &Val) { return getOrCreateVRegs(Val); });
26295ffd83dbSDimitry Andric }
26305ffd83dbSDimitry Andric 
translateCallBase(const CallBase & CB,MachineIRBuilder & MIRBuilder)26315ffd83dbSDimitry Andric bool IRTranslator::translateCallBase(const CallBase &CB,
26325ffd83dbSDimitry Andric                                      MachineIRBuilder &MIRBuilder) {
26335ffd83dbSDimitry Andric   ArrayRef<Register> Res = getOrCreateVRegs(CB);
26348bcb0991SDimitry Andric 
26358bcb0991SDimitry Andric   SmallVector<ArrayRef<Register>, 8> Args;
26368bcb0991SDimitry Andric   Register SwiftInVReg = 0;
26378bcb0991SDimitry Andric   Register SwiftErrorVReg = 0;
2638fcaf7f86SDimitry Andric   for (const auto &Arg : CB.args()) {
26398bcb0991SDimitry Andric     if (CLI->supportSwiftError() && isSwiftError(Arg)) {
26408bcb0991SDimitry Andric       assert(SwiftInVReg == 0 && "Expected only one swift error argument");
26418bcb0991SDimitry Andric       LLT Ty = getLLTForType(*Arg->getType(), *DL);
26428bcb0991SDimitry Andric       SwiftInVReg = MRI->createGenericVirtualRegister(Ty);
26438bcb0991SDimitry Andric       MIRBuilder.buildCopy(SwiftInVReg, SwiftError.getOrCreateVRegUseAt(
26445ffd83dbSDimitry Andric                                             &CB, &MIRBuilder.getMBB(), Arg));
2645bdd1243dSDimitry Andric       Args.emplace_back(ArrayRef(SwiftInVReg));
26468bcb0991SDimitry Andric       SwiftErrorVReg =
26475ffd83dbSDimitry Andric           SwiftError.getOrCreateVRegDefAt(&CB, &MIRBuilder.getMBB(), Arg);
26488bcb0991SDimitry Andric       continue;
26498bcb0991SDimitry Andric     }
26508bcb0991SDimitry Andric     Args.push_back(getOrCreateVRegs(*Arg));
26518bcb0991SDimitry Andric   }
26528bcb0991SDimitry Andric 
2653fe6060f1SDimitry Andric   if (auto *CI = dyn_cast<CallInst>(&CB)) {
2654fe6060f1SDimitry Andric     if (ORE->enabled()) {
2655bdd1243dSDimitry Andric       if (MemoryOpRemark::canHandle(CI, *LibInfo)) {
2656bdd1243dSDimitry Andric         MemoryOpRemark R(*ORE, "gisel-irtranslator-memsize", *DL, *LibInfo);
2657fe6060f1SDimitry Andric         R.visit(CI);
2658fe6060f1SDimitry Andric       }
2659fe6060f1SDimitry Andric     }
2660fe6060f1SDimitry Andric   }
2661fe6060f1SDimitry Andric 
26620fca6ea1SDimitry Andric   std::optional<CallLowering::PtrAuthInfo> PAI;
26630fca6ea1SDimitry Andric   if (auto Bundle = CB.getOperandBundle(LLVMContext::OB_ptrauth)) {
26640fca6ea1SDimitry Andric     // Functions should never be ptrauth-called directly.
26650fca6ea1SDimitry Andric     assert(!CB.getCalledFunction() && "invalid direct ptrauth call");
26660fca6ea1SDimitry Andric 
26670fca6ea1SDimitry Andric     const Value *Key = Bundle->Inputs[0];
26680fca6ea1SDimitry Andric     const Value *Discriminator = Bundle->Inputs[1];
26690fca6ea1SDimitry Andric 
26700fca6ea1SDimitry Andric     // Look through ptrauth constants to try to eliminate the matching bundle
26710fca6ea1SDimitry Andric     // and turn this into a direct call with no ptrauth.
26720fca6ea1SDimitry Andric     // CallLowering will use the raw pointer if it doesn't find the PAI.
26730fca6ea1SDimitry Andric     const auto *CalleeCPA = dyn_cast<ConstantPtrAuth>(CB.getCalledOperand());
26740fca6ea1SDimitry Andric     if (!CalleeCPA || !isa<Function>(CalleeCPA->getPointer()) ||
26750fca6ea1SDimitry Andric         !CalleeCPA->isKnownCompatibleWith(Key, Discriminator, *DL)) {
26760fca6ea1SDimitry Andric       // If we can't make it direct, package the bundle into PAI.
26770fca6ea1SDimitry Andric       Register DiscReg = getOrCreateVReg(*Discriminator);
26780fca6ea1SDimitry Andric       PAI = CallLowering::PtrAuthInfo{cast<ConstantInt>(Key)->getZExtValue(),
26790fca6ea1SDimitry Andric                                       DiscReg};
26800fca6ea1SDimitry Andric     }
26810fca6ea1SDimitry Andric   }
26820fca6ea1SDimitry Andric 
26830fca6ea1SDimitry Andric   Register ConvergenceCtrlToken = 0;
26840fca6ea1SDimitry Andric   if (auto Bundle = CB.getOperandBundle(LLVMContext::OB_convergencectrl)) {
26850fca6ea1SDimitry Andric     const auto &Token = *Bundle->Inputs[0].get();
26860fca6ea1SDimitry Andric     ConvergenceCtrlToken = getOrCreateConvergenceTokenVReg(Token);
26870fca6ea1SDimitry Andric   }
26880fca6ea1SDimitry Andric 
26898bcb0991SDimitry Andric   // We don't set HasCalls on MFI here yet because call lowering may decide to
26908bcb0991SDimitry Andric   // optimize into tail calls. Instead, we defer that to selection where a final
26918bcb0991SDimitry Andric   // scan is done to check if any instructions are calls.
26920fca6ea1SDimitry Andric   bool Success = CLI->lowerCall(
26930fca6ea1SDimitry Andric       MIRBuilder, CB, Res, Args, SwiftErrorVReg, PAI, ConvergenceCtrlToken,
26945ffd83dbSDimitry Andric       [&]() { return getOrCreateVReg(*CB.getCalledOperand()); });
26958bcb0991SDimitry Andric 
26968bcb0991SDimitry Andric   // Check if we just inserted a tail call.
26978bcb0991SDimitry Andric   if (Success) {
26988bcb0991SDimitry Andric     assert(!HasTailCall && "Can't tail call return twice from block?");
26998bcb0991SDimitry Andric     const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
27008bcb0991SDimitry Andric     HasTailCall = TII->isTailCall(*std::prev(MIRBuilder.getInsertPt()));
27018bcb0991SDimitry Andric   }
27028bcb0991SDimitry Andric 
27038bcb0991SDimitry Andric   return Success;
27048bcb0991SDimitry Andric }
27058bcb0991SDimitry Andric 
translateCall(const User & U,MachineIRBuilder & MIRBuilder)27060b57cec5SDimitry Andric bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
27070b57cec5SDimitry Andric   const CallInst &CI = cast<CallInst>(U);
27080b57cec5SDimitry Andric   auto TII = MF->getTarget().getIntrinsicInfo();
27090b57cec5SDimitry Andric   const Function *F = CI.getCalledFunction();
27100b57cec5SDimitry Andric 
27115f757f3fSDimitry Andric   // FIXME: support Windows dllimport function calls and calls through
27125f757f3fSDimitry Andric   // weak symbols.
2713480093f4SDimitry Andric   if (F && (F->hasDLLImportStorageClass() ||
2714480093f4SDimitry Andric             (MF->getTarget().getTargetTriple().isOSWindows() &&
2715480093f4SDimitry Andric              F->hasExternalWeakLinkage())))
2716480093f4SDimitry Andric     return false;
2717480093f4SDimitry Andric 
2718480093f4SDimitry Andric   // FIXME: support control flow guard targets.
2719480093f4SDimitry Andric   if (CI.countOperandBundlesOfType(LLVMContext::OB_cfguardtarget))
27200b57cec5SDimitry Andric     return false;
27210b57cec5SDimitry Andric 
2722bdd1243dSDimitry Andric   // FIXME: support statepoints and related.
2723bdd1243dSDimitry Andric   if (isa<GCStatepointInst, GCRelocateInst, GCResultInst>(U))
2724bdd1243dSDimitry Andric     return false;
2725bdd1243dSDimitry Andric 
27260b57cec5SDimitry Andric   if (CI.isInlineAsm())
27270b57cec5SDimitry Andric     return translateInlineAsm(CI, MIRBuilder);
27280b57cec5SDimitry Andric 
2729349cc55cSDimitry Andric   diagnoseDontCall(CI);
2730349cc55cSDimitry Andric 
27310b57cec5SDimitry Andric   Intrinsic::ID ID = Intrinsic::not_intrinsic;
27320b57cec5SDimitry Andric   if (F && F->isIntrinsic()) {
27330b57cec5SDimitry Andric     ID = F->getIntrinsicID();
27340b57cec5SDimitry Andric     if (TII && ID == Intrinsic::not_intrinsic)
27350b57cec5SDimitry Andric       ID = static_cast<Intrinsic::ID>(TII->getIntrinsicID(F));
27360b57cec5SDimitry Andric   }
27370b57cec5SDimitry Andric 
27388bcb0991SDimitry Andric   if (!F || !F->isIntrinsic() || ID == Intrinsic::not_intrinsic)
27395ffd83dbSDimitry Andric     return translateCallBase(CI, MIRBuilder);
27400b57cec5SDimitry Andric 
27410b57cec5SDimitry Andric   assert(ID != Intrinsic::not_intrinsic && "unknown intrinsic");
27420b57cec5SDimitry Andric 
27430b57cec5SDimitry Andric   if (translateKnownIntrinsic(CI, ID, MIRBuilder))
27440b57cec5SDimitry Andric     return true;
27450b57cec5SDimitry Andric 
27460b57cec5SDimitry Andric   ArrayRef<Register> ResultRegs;
27470b57cec5SDimitry Andric   if (!CI.getType()->isVoidTy())
27480b57cec5SDimitry Andric     ResultRegs = getOrCreateVRegs(CI);
27490b57cec5SDimitry Andric 
27500b57cec5SDimitry Andric   // Ignore the callsite attributes. Backend code is most likely not expecting
27510b57cec5SDimitry Andric   // an intrinsic to sometimes have side effects and sometimes not.
27525f757f3fSDimitry Andric   MachineInstrBuilder MIB = MIRBuilder.buildIntrinsic(ID, ResultRegs);
27530b57cec5SDimitry Andric   if (isa<FPMathOperator>(CI))
27540b57cec5SDimitry Andric     MIB->copyIRFlags(CI);
27550b57cec5SDimitry Andric 
2756fcaf7f86SDimitry Andric   for (const auto &Arg : enumerate(CI.args())) {
27578bcb0991SDimitry Andric     // If this is required to be an immediate, don't materialize it in a
27588bcb0991SDimitry Andric     // register.
27598bcb0991SDimitry Andric     if (CI.paramHasAttr(Arg.index(), Attribute::ImmArg)) {
27608bcb0991SDimitry Andric       if (ConstantInt *CI = dyn_cast<ConstantInt>(Arg.value())) {
27618bcb0991SDimitry Andric         // imm arguments are more convenient than cimm (and realistically
27628bcb0991SDimitry Andric         // probably sufficient), so use them.
27638bcb0991SDimitry Andric         assert(CI->getBitWidth() <= 64 &&
27648bcb0991SDimitry Andric                "large intrinsic immediates not handled");
27658bcb0991SDimitry Andric         MIB.addImm(CI->getSExtValue());
27668bcb0991SDimitry Andric       } else {
27678bcb0991SDimitry Andric         MIB.addFPImm(cast<ConstantFP>(Arg.value()));
27688bcb0991SDimitry Andric       }
2769349cc55cSDimitry Andric     } else if (auto *MDVal = dyn_cast<MetadataAsValue>(Arg.value())) {
2770349cc55cSDimitry Andric       auto *MD = MDVal->getMetadata();
2771349cc55cSDimitry Andric       auto *MDN = dyn_cast<MDNode>(MD);
2772349cc55cSDimitry Andric       if (!MDN) {
2773349cc55cSDimitry Andric         if (auto *ConstMD = dyn_cast<ConstantAsMetadata>(MD))
2774349cc55cSDimitry Andric           MDN = MDNode::get(MF->getFunction().getContext(), ConstMD);
2775349cc55cSDimitry Andric         else // This was probably an MDString.
2776e8d8bef9SDimitry Andric           return false;
2777349cc55cSDimitry Andric       }
2778e8d8bef9SDimitry Andric       MIB.addMetadata(MDN);
27798bcb0991SDimitry Andric     } else {
27808bcb0991SDimitry Andric       ArrayRef<Register> VRegs = getOrCreateVRegs(*Arg.value());
27810b57cec5SDimitry Andric       if (VRegs.size() > 1)
27820b57cec5SDimitry Andric         return false;
27830b57cec5SDimitry Andric       MIB.addUse(VRegs[0]);
27840b57cec5SDimitry Andric     }
27858bcb0991SDimitry Andric   }
27860b57cec5SDimitry Andric 
27870b57cec5SDimitry Andric   // Add a MachineMemOperand if it is a target mem intrinsic.
27880b57cec5SDimitry Andric   TargetLowering::IntrinsicInfo Info;
27890b57cec5SDimitry Andric   // TODO: Add a GlobalISel version of getTgtMemIntrinsic.
27900fca6ea1SDimitry Andric   if (TLI->getTgtMemIntrinsic(Info, CI, *MF, ID)) {
279181ad6265SDimitry Andric     Align Alignment = Info.align.value_or(
27925ffd83dbSDimitry Andric         DL->getABITypeAlign(Info.memVT.getTypeForEVT(F->getContext())));
2793fe6060f1SDimitry Andric     LLT MemTy = Info.memVT.isSimple()
2794fe6060f1SDimitry Andric                     ? getLLTForMVT(Info.memVT.getSimpleVT())
2795fe6060f1SDimitry Andric                     : LLT::scalar(Info.memVT.getStoreSizeInBits());
2796bdd1243dSDimitry Andric 
2797bdd1243dSDimitry Andric     // TODO: We currently just fallback to address space 0 if getTgtMemIntrinsic
2798bdd1243dSDimitry Andric     //       didn't yield anything useful.
2799bdd1243dSDimitry Andric     MachinePointerInfo MPI;
2800bdd1243dSDimitry Andric     if (Info.ptrVal)
2801bdd1243dSDimitry Andric       MPI = MachinePointerInfo(Info.ptrVal, Info.offset);
2802bdd1243dSDimitry Andric     else if (Info.fallbackAddressSpace)
2803bdd1243dSDimitry Andric       MPI = MachinePointerInfo(*Info.fallbackAddressSpace);
2804bdd1243dSDimitry Andric     MIB.addMemOperand(
2805bdd1243dSDimitry Andric         MF->getMachineMemOperand(MPI, Info.flags, MemTy, Alignment, CI.getAAMetadata()));
28060b57cec5SDimitry Andric   }
28070b57cec5SDimitry Andric 
28080fca6ea1SDimitry Andric   if (CI.isConvergent()) {
28090fca6ea1SDimitry Andric     if (auto Bundle = CI.getOperandBundle(LLVMContext::OB_convergencectrl)) {
28100fca6ea1SDimitry Andric       auto *Token = Bundle->Inputs[0].get();
28110fca6ea1SDimitry Andric       Register TokenReg = getOrCreateVReg(*Token);
28120fca6ea1SDimitry Andric       MIB.addUse(TokenReg, RegState::Implicit);
28130fca6ea1SDimitry Andric     }
28140fca6ea1SDimitry Andric   }
28150fca6ea1SDimitry Andric 
28160b57cec5SDimitry Andric   return true;
28170b57cec5SDimitry Andric }
28180b57cec5SDimitry Andric 
findUnwindDestinations(const BasicBlock * EHPadBB,BranchProbability Prob,SmallVectorImpl<std::pair<MachineBasicBlock *,BranchProbability>> & UnwindDests)2819e8d8bef9SDimitry Andric bool IRTranslator::findUnwindDestinations(
2820e8d8bef9SDimitry Andric     const BasicBlock *EHPadBB,
2821e8d8bef9SDimitry Andric     BranchProbability Prob,
2822e8d8bef9SDimitry Andric     SmallVectorImpl<std::pair<MachineBasicBlock *, BranchProbability>>
2823e8d8bef9SDimitry Andric         &UnwindDests) {
2824e8d8bef9SDimitry Andric   EHPersonality Personality = classifyEHPersonality(
2825e8d8bef9SDimitry Andric       EHPadBB->getParent()->getFunction().getPersonalityFn());
2826e8d8bef9SDimitry Andric   bool IsMSVCCXX = Personality == EHPersonality::MSVC_CXX;
2827e8d8bef9SDimitry Andric   bool IsCoreCLR = Personality == EHPersonality::CoreCLR;
2828e8d8bef9SDimitry Andric   bool IsWasmCXX = Personality == EHPersonality::Wasm_CXX;
2829e8d8bef9SDimitry Andric   bool IsSEH = isAsynchronousEHPersonality(Personality);
2830e8d8bef9SDimitry Andric 
2831e8d8bef9SDimitry Andric   if (IsWasmCXX) {
2832e8d8bef9SDimitry Andric     // Ignore this for now.
2833e8d8bef9SDimitry Andric     return false;
2834e8d8bef9SDimitry Andric   }
2835e8d8bef9SDimitry Andric 
2836e8d8bef9SDimitry Andric   while (EHPadBB) {
2837e8d8bef9SDimitry Andric     const Instruction *Pad = EHPadBB->getFirstNonPHI();
2838e8d8bef9SDimitry Andric     BasicBlock *NewEHPadBB = nullptr;
2839e8d8bef9SDimitry Andric     if (isa<LandingPadInst>(Pad)) {
2840e8d8bef9SDimitry Andric       // Stop on landingpads. They are not funclets.
2841e8d8bef9SDimitry Andric       UnwindDests.emplace_back(&getMBB(*EHPadBB), Prob);
2842e8d8bef9SDimitry Andric       break;
2843e8d8bef9SDimitry Andric     }
2844e8d8bef9SDimitry Andric     if (isa<CleanupPadInst>(Pad)) {
2845e8d8bef9SDimitry Andric       // Stop on cleanup pads. Cleanups are always funclet entries for all known
2846e8d8bef9SDimitry Andric       // personalities.
2847e8d8bef9SDimitry Andric       UnwindDests.emplace_back(&getMBB(*EHPadBB), Prob);
2848e8d8bef9SDimitry Andric       UnwindDests.back().first->setIsEHScopeEntry();
2849e8d8bef9SDimitry Andric       UnwindDests.back().first->setIsEHFuncletEntry();
2850e8d8bef9SDimitry Andric       break;
2851e8d8bef9SDimitry Andric     }
2852e8d8bef9SDimitry Andric     if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Pad)) {
2853e8d8bef9SDimitry Andric       // Add the catchpad handlers to the possible destinations.
2854e8d8bef9SDimitry Andric       for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
2855e8d8bef9SDimitry Andric         UnwindDests.emplace_back(&getMBB(*CatchPadBB), Prob);
2856e8d8bef9SDimitry Andric         // For MSVC++ and the CLR, catchblocks are funclets and need prologues.
2857e8d8bef9SDimitry Andric         if (IsMSVCCXX || IsCoreCLR)
2858e8d8bef9SDimitry Andric           UnwindDests.back().first->setIsEHFuncletEntry();
2859e8d8bef9SDimitry Andric         if (!IsSEH)
2860e8d8bef9SDimitry Andric           UnwindDests.back().first->setIsEHScopeEntry();
2861e8d8bef9SDimitry Andric       }
2862e8d8bef9SDimitry Andric       NewEHPadBB = CatchSwitch->getUnwindDest();
2863e8d8bef9SDimitry Andric     } else {
2864e8d8bef9SDimitry Andric       continue;
2865e8d8bef9SDimitry Andric     }
2866e8d8bef9SDimitry Andric 
2867e8d8bef9SDimitry Andric     BranchProbabilityInfo *BPI = FuncInfo.BPI;
2868e8d8bef9SDimitry Andric     if (BPI && NewEHPadBB)
2869e8d8bef9SDimitry Andric       Prob *= BPI->getEdgeProbability(EHPadBB, NewEHPadBB);
2870e8d8bef9SDimitry Andric     EHPadBB = NewEHPadBB;
2871e8d8bef9SDimitry Andric   }
2872e8d8bef9SDimitry Andric   return true;
2873e8d8bef9SDimitry Andric }
2874e8d8bef9SDimitry Andric 
translateInvoke(const User & U,MachineIRBuilder & MIRBuilder)28750b57cec5SDimitry Andric bool IRTranslator::translateInvoke(const User &U,
28760b57cec5SDimitry Andric                                    MachineIRBuilder &MIRBuilder) {
28770b57cec5SDimitry Andric   const InvokeInst &I = cast<InvokeInst>(U);
28780b57cec5SDimitry Andric   MCContext &Context = MF->getContext();
28790b57cec5SDimitry Andric 
28800b57cec5SDimitry Andric   const BasicBlock *ReturnBB = I.getSuccessor(0);
28810b57cec5SDimitry Andric   const BasicBlock *EHPadBB = I.getSuccessor(1);
28820b57cec5SDimitry Andric 
28835ffd83dbSDimitry Andric   const Function *Fn = I.getCalledFunction();
28840b57cec5SDimitry Andric 
28850b57cec5SDimitry Andric   // FIXME: support invoking patchpoint and statepoint intrinsics.
28860b57cec5SDimitry Andric   if (Fn && Fn->isIntrinsic())
28870b57cec5SDimitry Andric     return false;
28880b57cec5SDimitry Andric 
28890b57cec5SDimitry Andric   // FIXME: support whatever these are.
28900fca6ea1SDimitry Andric   if (I.hasDeoptState())
28910b57cec5SDimitry Andric     return false;
28920b57cec5SDimitry Andric 
2893480093f4SDimitry Andric   // FIXME: support control flow guard targets.
2894480093f4SDimitry Andric   if (I.countOperandBundlesOfType(LLVMContext::OB_cfguardtarget))
2895480093f4SDimitry Andric     return false;
2896480093f4SDimitry Andric 
28970b57cec5SDimitry Andric   // FIXME: support Windows exception handling.
2898e8d8bef9SDimitry Andric   if (!isa<LandingPadInst>(EHPadBB->getFirstNonPHI()))
28990b57cec5SDimitry Andric     return false;
29000b57cec5SDimitry Andric 
29015f757f3fSDimitry Andric   // FIXME: support Windows dllimport function calls and calls through
29025f757f3fSDimitry Andric   // weak symbols.
29035f757f3fSDimitry Andric   if (Fn && (Fn->hasDLLImportStorageClass() ||
29045f757f3fSDimitry Andric             (MF->getTarget().getTargetTriple().isOSWindows() &&
29055f757f3fSDimitry Andric              Fn->hasExternalWeakLinkage())))
29065f757f3fSDimitry Andric     return false;
29075f757f3fSDimitry Andric 
2908349cc55cSDimitry Andric   bool LowerInlineAsm = I.isInlineAsm();
2909349cc55cSDimitry Andric   bool NeedEHLabel = true;
2910fe6060f1SDimitry Andric 
29110b57cec5SDimitry Andric   // Emit the actual call, bracketed by EH_LABELs so that the MF knows about
29120b57cec5SDimitry Andric   // the region covered by the try.
2913349cc55cSDimitry Andric   MCSymbol *BeginSymbol = nullptr;
2914349cc55cSDimitry Andric   if (NeedEHLabel) {
2915bdd1243dSDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::G_INVOKE_REGION_START);
2916349cc55cSDimitry Andric     BeginSymbol = Context.createTempSymbol();
29170b57cec5SDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol);
2918349cc55cSDimitry Andric   }
29190b57cec5SDimitry Andric 
2920fe6060f1SDimitry Andric   if (LowerInlineAsm) {
2921fe6060f1SDimitry Andric     if (!translateInlineAsm(I, MIRBuilder))
2922fe6060f1SDimitry Andric       return false;
2923fe6060f1SDimitry Andric   } else if (!translateCallBase(I, MIRBuilder))
29240b57cec5SDimitry Andric     return false;
29250b57cec5SDimitry Andric 
2926349cc55cSDimitry Andric   MCSymbol *EndSymbol = nullptr;
2927349cc55cSDimitry Andric   if (NeedEHLabel) {
2928349cc55cSDimitry Andric     EndSymbol = Context.createTempSymbol();
29290b57cec5SDimitry Andric     MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(EndSymbol);
2930349cc55cSDimitry Andric   }
29310b57cec5SDimitry Andric 
2932e8d8bef9SDimitry Andric   SmallVector<std::pair<MachineBasicBlock *, BranchProbability>, 1> UnwindDests;
2933e8d8bef9SDimitry Andric   BranchProbabilityInfo *BPI = FuncInfo.BPI;
2934e8d8bef9SDimitry Andric   MachineBasicBlock *InvokeMBB = &MIRBuilder.getMBB();
2935e8d8bef9SDimitry Andric   BranchProbability EHPadBBProb =
2936e8d8bef9SDimitry Andric       BPI ? BPI->getEdgeProbability(InvokeMBB->getBasicBlock(), EHPadBB)
2937e8d8bef9SDimitry Andric           : BranchProbability::getZero();
2938e8d8bef9SDimitry Andric 
2939e8d8bef9SDimitry Andric   if (!findUnwindDestinations(EHPadBB, EHPadBBProb, UnwindDests))
2940e8d8bef9SDimitry Andric     return false;
2941e8d8bef9SDimitry Andric 
29420b57cec5SDimitry Andric   MachineBasicBlock &EHPadMBB = getMBB(*EHPadBB),
29430b57cec5SDimitry Andric                     &ReturnMBB = getMBB(*ReturnBB);
2944e8d8bef9SDimitry Andric   // Update successor info.
2945e8d8bef9SDimitry Andric   addSuccessorWithProb(InvokeMBB, &ReturnMBB);
2946e8d8bef9SDimitry Andric   for (auto &UnwindDest : UnwindDests) {
2947e8d8bef9SDimitry Andric     UnwindDest.first->setIsEHPad();
2948e8d8bef9SDimitry Andric     addSuccessorWithProb(InvokeMBB, UnwindDest.first, UnwindDest.second);
2949e8d8bef9SDimitry Andric   }
2950e8d8bef9SDimitry Andric   InvokeMBB->normalizeSuccProbs();
29510b57cec5SDimitry Andric 
2952349cc55cSDimitry Andric   if (NeedEHLabel) {
2953349cc55cSDimitry Andric     assert(BeginSymbol && "Expected a begin symbol!");
2954349cc55cSDimitry Andric     assert(EndSymbol && "Expected an end symbol!");
2955e8d8bef9SDimitry Andric     MF->addInvoke(&EHPadMBB, BeginSymbol, EndSymbol);
2956349cc55cSDimitry Andric   }
2957349cc55cSDimitry Andric 
2958e8d8bef9SDimitry Andric   MIRBuilder.buildBr(ReturnMBB);
29590b57cec5SDimitry Andric   return true;
29600b57cec5SDimitry Andric }
29610b57cec5SDimitry Andric 
translateCallBr(const User & U,MachineIRBuilder & MIRBuilder)29620b57cec5SDimitry Andric bool IRTranslator::translateCallBr(const User &U,
29630b57cec5SDimitry Andric                                    MachineIRBuilder &MIRBuilder) {
29640b57cec5SDimitry Andric   // FIXME: Implement this.
29650b57cec5SDimitry Andric   return false;
29660b57cec5SDimitry Andric }
29670b57cec5SDimitry Andric 
translateLandingPad(const User & U,MachineIRBuilder & MIRBuilder)29680b57cec5SDimitry Andric bool IRTranslator::translateLandingPad(const User &U,
29690b57cec5SDimitry Andric                                        MachineIRBuilder &MIRBuilder) {
29700b57cec5SDimitry Andric   const LandingPadInst &LP = cast<LandingPadInst>(U);
29710b57cec5SDimitry Andric 
29720b57cec5SDimitry Andric   MachineBasicBlock &MBB = MIRBuilder.getMBB();
29730b57cec5SDimitry Andric 
29740b57cec5SDimitry Andric   MBB.setIsEHPad();
29750b57cec5SDimitry Andric 
29760b57cec5SDimitry Andric   // If there aren't registers to copy the values into (e.g., during SjLj
29770b57cec5SDimitry Andric   // exceptions), then don't bother.
29780b57cec5SDimitry Andric   const Constant *PersonalityFn = MF->getFunction().getPersonalityFn();
29790fca6ea1SDimitry Andric   if (TLI->getExceptionPointerRegister(PersonalityFn) == 0 &&
29800fca6ea1SDimitry Andric       TLI->getExceptionSelectorRegister(PersonalityFn) == 0)
29810b57cec5SDimitry Andric     return true;
29820b57cec5SDimitry Andric 
29830b57cec5SDimitry Andric   // If landingpad's return type is token type, we don't create DAG nodes
29840b57cec5SDimitry Andric   // for its exception pointer and selector value. The extraction of exception
29850b57cec5SDimitry Andric   // pointer or selector value from token type landingpads is not currently
29860b57cec5SDimitry Andric   // supported.
29870b57cec5SDimitry Andric   if (LP.getType()->isTokenTy())
29880b57cec5SDimitry Andric     return true;
29890b57cec5SDimitry Andric 
29900b57cec5SDimitry Andric   // Add a label to mark the beginning of the landing pad.  Deletion of the
29910b57cec5SDimitry Andric   // landing pad can thus be detected via the MachineModuleInfo.
29920b57cec5SDimitry Andric   MIRBuilder.buildInstr(TargetOpcode::EH_LABEL)
29930b57cec5SDimitry Andric     .addSym(MF->addLandingPad(&MBB));
29940b57cec5SDimitry Andric 
2995e8d8bef9SDimitry Andric   // If the unwinder does not preserve all registers, ensure that the
2996e8d8bef9SDimitry Andric   // function marks the clobbered registers as used.
2997e8d8bef9SDimitry Andric   const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
2998e8d8bef9SDimitry Andric   if (auto *RegMask = TRI.getCustomEHPadPreservedMask(*MF))
2999e8d8bef9SDimitry Andric     MF->getRegInfo().addPhysRegsUsedFromRegMask(RegMask);
3000e8d8bef9SDimitry Andric 
30010b57cec5SDimitry Andric   LLT Ty = getLLTForType(*LP.getType(), *DL);
30020b57cec5SDimitry Andric   Register Undef = MRI->createGenericVirtualRegister(Ty);
30030b57cec5SDimitry Andric   MIRBuilder.buildUndef(Undef);
30040b57cec5SDimitry Andric 
30050b57cec5SDimitry Andric   SmallVector<LLT, 2> Tys;
30060b57cec5SDimitry Andric   for (Type *Ty : cast<StructType>(LP.getType())->elements())
30070b57cec5SDimitry Andric     Tys.push_back(getLLTForType(*Ty, *DL));
30080b57cec5SDimitry Andric   assert(Tys.size() == 2 && "Only two-valued landingpads are supported");
30090b57cec5SDimitry Andric 
30100b57cec5SDimitry Andric   // Mark exception register as live in.
30110fca6ea1SDimitry Andric   Register ExceptionReg = TLI->getExceptionPointerRegister(PersonalityFn);
30120b57cec5SDimitry Andric   if (!ExceptionReg)
30130b57cec5SDimitry Andric     return false;
30140b57cec5SDimitry Andric 
30150b57cec5SDimitry Andric   MBB.addLiveIn(ExceptionReg);
30160b57cec5SDimitry Andric   ArrayRef<Register> ResRegs = getOrCreateVRegs(LP);
30170b57cec5SDimitry Andric   MIRBuilder.buildCopy(ResRegs[0], ExceptionReg);
30180b57cec5SDimitry Andric 
30190fca6ea1SDimitry Andric   Register SelectorReg = TLI->getExceptionSelectorRegister(PersonalityFn);
30200b57cec5SDimitry Andric   if (!SelectorReg)
30210b57cec5SDimitry Andric     return false;
30220b57cec5SDimitry Andric 
30230b57cec5SDimitry Andric   MBB.addLiveIn(SelectorReg);
30240b57cec5SDimitry Andric   Register PtrVReg = MRI->createGenericVirtualRegister(Tys[0]);
30250b57cec5SDimitry Andric   MIRBuilder.buildCopy(PtrVReg, SelectorReg);
30260b57cec5SDimitry Andric   MIRBuilder.buildCast(ResRegs[1], PtrVReg);
30270b57cec5SDimitry Andric 
30280b57cec5SDimitry Andric   return true;
30290b57cec5SDimitry Andric }
30300b57cec5SDimitry Andric 
translateAlloca(const User & U,MachineIRBuilder & MIRBuilder)30310b57cec5SDimitry Andric bool IRTranslator::translateAlloca(const User &U,
30320b57cec5SDimitry Andric                                    MachineIRBuilder &MIRBuilder) {
30330b57cec5SDimitry Andric   auto &AI = cast<AllocaInst>(U);
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric   if (AI.isSwiftError())
30360b57cec5SDimitry Andric     return true;
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric   if (AI.isStaticAlloca()) {
30390b57cec5SDimitry Andric     Register Res = getOrCreateVReg(AI);
30400b57cec5SDimitry Andric     int FI = getOrCreateFrameIndex(AI);
30410b57cec5SDimitry Andric     MIRBuilder.buildFrameIndex(Res, FI);
30420b57cec5SDimitry Andric     return true;
30430b57cec5SDimitry Andric   }
30440b57cec5SDimitry Andric 
30450b57cec5SDimitry Andric   // FIXME: support stack probing for Windows.
30460b57cec5SDimitry Andric   if (MF->getTarget().getTargetTriple().isOSWindows())
30470b57cec5SDimitry Andric     return false;
30480b57cec5SDimitry Andric 
30490b57cec5SDimitry Andric   // Now we're in the harder dynamic case.
30500b57cec5SDimitry Andric   Register NumElts = getOrCreateVReg(*AI.getArraySize());
30510b57cec5SDimitry Andric   Type *IntPtrIRTy = DL->getIntPtrType(AI.getType());
30520b57cec5SDimitry Andric   LLT IntPtrTy = getLLTForType(*IntPtrIRTy, *DL);
30530b57cec5SDimitry Andric   if (MRI->getType(NumElts) != IntPtrTy) {
30540b57cec5SDimitry Andric     Register ExtElts = MRI->createGenericVirtualRegister(IntPtrTy);
30550b57cec5SDimitry Andric     MIRBuilder.buildZExtOrTrunc(ExtElts, NumElts);
30560b57cec5SDimitry Andric     NumElts = ExtElts;
30570b57cec5SDimitry Andric   }
30580b57cec5SDimitry Andric 
30595ffd83dbSDimitry Andric   Type *Ty = AI.getAllocatedType();
30605ffd83dbSDimitry Andric 
30610b57cec5SDimitry Andric   Register AllocSize = MRI->createGenericVirtualRegister(IntPtrTy);
30620b57cec5SDimitry Andric   Register TySize =
30638bcb0991SDimitry Andric       getOrCreateVReg(*ConstantInt::get(IntPtrIRTy, DL->getTypeAllocSize(Ty)));
30640b57cec5SDimitry Andric   MIRBuilder.buildMul(AllocSize, NumElts, TySize);
30650b57cec5SDimitry Andric 
30660b57cec5SDimitry Andric   // Round the size of the allocation up to the stack alignment size
30670b57cec5SDimitry Andric   // by add SA-1 to the size. This doesn't overflow because we're computing
30680b57cec5SDimitry Andric   // an address inside an alloca.
30695ffd83dbSDimitry Andric   Align StackAlign = MF->getSubtarget().getFrameLowering()->getStackAlign();
30705ffd83dbSDimitry Andric   auto SAMinusOne = MIRBuilder.buildConstant(IntPtrTy, StackAlign.value() - 1);
30718bcb0991SDimitry Andric   auto AllocAdd = MIRBuilder.buildAdd(IntPtrTy, AllocSize, SAMinusOne,
30728bcb0991SDimitry Andric                                       MachineInstr::NoUWrap);
30738bcb0991SDimitry Andric   auto AlignCst =
30745ffd83dbSDimitry Andric       MIRBuilder.buildConstant(IntPtrTy, ~(uint64_t)(StackAlign.value() - 1));
30758bcb0991SDimitry Andric   auto AlignedAlloc = MIRBuilder.buildAnd(IntPtrTy, AllocAdd, AlignCst);
30760b57cec5SDimitry Andric 
30775ffd83dbSDimitry Andric   Align Alignment = std::max(AI.getAlign(), DL->getPrefTypeAlign(Ty));
30785ffd83dbSDimitry Andric   if (Alignment <= StackAlign)
30795ffd83dbSDimitry Andric     Alignment = Align(1);
30805ffd83dbSDimitry Andric   MIRBuilder.buildDynStackAlloc(getOrCreateVReg(AI), AlignedAlloc, Alignment);
30810b57cec5SDimitry Andric 
30825ffd83dbSDimitry Andric   MF->getFrameInfo().CreateVariableSizedObject(Alignment, &AI);
30830b57cec5SDimitry Andric   assert(MF->getFrameInfo().hasVarSizedObjects());
30840b57cec5SDimitry Andric   return true;
30850b57cec5SDimitry Andric }
30860b57cec5SDimitry Andric 
translateVAArg(const User & U,MachineIRBuilder & MIRBuilder)30870b57cec5SDimitry Andric bool IRTranslator::translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) {
30880b57cec5SDimitry Andric   // FIXME: We may need more info about the type. Because of how LLT works,
30890b57cec5SDimitry Andric   // we're completely discarding the i64/double distinction here (amongst
30900b57cec5SDimitry Andric   // others). Fortunately the ABIs I know of where that matters don't use va_arg
30910b57cec5SDimitry Andric   // anyway but that's not guaranteed.
30925ffd83dbSDimitry Andric   MIRBuilder.buildInstr(TargetOpcode::G_VAARG, {getOrCreateVReg(U)},
30935ffd83dbSDimitry Andric                         {getOrCreateVReg(*U.getOperand(0)),
30945ffd83dbSDimitry Andric                          DL->getABITypeAlign(U.getType()).value()});
30950b57cec5SDimitry Andric   return true;
30960b57cec5SDimitry Andric }
30970b57cec5SDimitry Andric 
translateUnreachable(const User & U,MachineIRBuilder & MIRBuilder)3098349cc55cSDimitry Andric bool IRTranslator::translateUnreachable(const User &U, MachineIRBuilder &MIRBuilder) {
3099349cc55cSDimitry Andric   if (!MF->getTarget().Options.TrapUnreachable)
3100349cc55cSDimitry Andric     return true;
3101349cc55cSDimitry Andric 
3102349cc55cSDimitry Andric   auto &UI = cast<UnreachableInst>(U);
31030fca6ea1SDimitry Andric 
3104349cc55cSDimitry Andric   // We may be able to ignore unreachable behind a noreturn call.
31050fca6ea1SDimitry Andric   if (const CallInst *Call = dyn_cast_or_null<CallInst>(UI.getPrevNode());
31060fca6ea1SDimitry Andric       Call && Call->doesNotReturn()) {
31070fca6ea1SDimitry Andric     if (MF->getTarget().Options.NoTrapAfterNoreturn)
31080fca6ea1SDimitry Andric       return true;
31090fca6ea1SDimitry Andric     // Do not emit an additional trap instruction.
31100fca6ea1SDimitry Andric     if (Call->isNonContinuableTrap())
3111349cc55cSDimitry Andric       return true;
3112349cc55cSDimitry Andric   }
3113349cc55cSDimitry Andric 
31140fca6ea1SDimitry Andric   MIRBuilder.buildTrap();
3115349cc55cSDimitry Andric   return true;
3116349cc55cSDimitry Andric }
3117349cc55cSDimitry Andric 
translateInsertElement(const User & U,MachineIRBuilder & MIRBuilder)31180b57cec5SDimitry Andric bool IRTranslator::translateInsertElement(const User &U,
31190b57cec5SDimitry Andric                                           MachineIRBuilder &MIRBuilder) {
31200b57cec5SDimitry Andric   // If it is a <1 x Ty> vector, use the scalar as it is
31210b57cec5SDimitry Andric   // not a legal vector type in LLT.
31220fca6ea1SDimitry Andric   if (auto *FVT = dyn_cast<FixedVectorType>(U.getType());
31230fca6ea1SDimitry Andric       FVT && FVT->getNumElements() == 1)
31245ffd83dbSDimitry Andric     return translateCopy(U, *U.getOperand(1), MIRBuilder);
31250b57cec5SDimitry Andric 
31260b57cec5SDimitry Andric   Register Res = getOrCreateVReg(U);
31270b57cec5SDimitry Andric   Register Val = getOrCreateVReg(*U.getOperand(0));
31280b57cec5SDimitry Andric   Register Elt = getOrCreateVReg(*U.getOperand(1));
31290fca6ea1SDimitry Andric   unsigned PreferredVecIdxWidth = TLI->getVectorIdxTy(*DL).getSizeInBits();
31300fca6ea1SDimitry Andric   Register Idx;
31310fca6ea1SDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(U.getOperand(2))) {
31320fca6ea1SDimitry Andric     if (CI->getBitWidth() != PreferredVecIdxWidth) {
31330fca6ea1SDimitry Andric       APInt NewIdx = CI->getValue().zextOrTrunc(PreferredVecIdxWidth);
31340fca6ea1SDimitry Andric       auto *NewIdxCI = ConstantInt::get(CI->getContext(), NewIdx);
31350fca6ea1SDimitry Andric       Idx = getOrCreateVReg(*NewIdxCI);
31360fca6ea1SDimitry Andric     }
31370fca6ea1SDimitry Andric   }
31380fca6ea1SDimitry Andric   if (!Idx)
31390fca6ea1SDimitry Andric     Idx = getOrCreateVReg(*U.getOperand(2));
31400fca6ea1SDimitry Andric   if (MRI->getType(Idx).getSizeInBits() != PreferredVecIdxWidth) {
31410fca6ea1SDimitry Andric     const LLT VecIdxTy = LLT::scalar(PreferredVecIdxWidth);
31420fca6ea1SDimitry Andric     Idx = MIRBuilder.buildZExtOrTrunc(VecIdxTy, Idx).getReg(0);
31430fca6ea1SDimitry Andric   }
31440b57cec5SDimitry Andric   MIRBuilder.buildInsertVectorElement(Res, Val, Elt, Idx);
31450b57cec5SDimitry Andric   return true;
31460b57cec5SDimitry Andric }
31470b57cec5SDimitry Andric 
translateExtractElement(const User & U,MachineIRBuilder & MIRBuilder)31480b57cec5SDimitry Andric bool IRTranslator::translateExtractElement(const User &U,
31490b57cec5SDimitry Andric                                            MachineIRBuilder &MIRBuilder) {
31500b57cec5SDimitry Andric   // If it is a <1 x Ty> vector, use the scalar as it is
31510b57cec5SDimitry Andric   // not a legal vector type in LLT.
31525ffd83dbSDimitry Andric   if (cast<FixedVectorType>(U.getOperand(0)->getType())->getNumElements() == 1)
31535ffd83dbSDimitry Andric     return translateCopy(U, *U.getOperand(0), MIRBuilder);
31545ffd83dbSDimitry Andric 
31550b57cec5SDimitry Andric   Register Res = getOrCreateVReg(U);
31560b57cec5SDimitry Andric   Register Val = getOrCreateVReg(*U.getOperand(0));
31570fca6ea1SDimitry Andric   unsigned PreferredVecIdxWidth = TLI->getVectorIdxTy(*DL).getSizeInBits();
31580b57cec5SDimitry Andric   Register Idx;
31590b57cec5SDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(U.getOperand(1))) {
31600b57cec5SDimitry Andric     if (CI->getBitWidth() != PreferredVecIdxWidth) {
3161bdd1243dSDimitry Andric       APInt NewIdx = CI->getValue().zextOrTrunc(PreferredVecIdxWidth);
31620b57cec5SDimitry Andric       auto *NewIdxCI = ConstantInt::get(CI->getContext(), NewIdx);
31630b57cec5SDimitry Andric       Idx = getOrCreateVReg(*NewIdxCI);
31640b57cec5SDimitry Andric     }
31650b57cec5SDimitry Andric   }
31660b57cec5SDimitry Andric   if (!Idx)
31670b57cec5SDimitry Andric     Idx = getOrCreateVReg(*U.getOperand(1));
31680b57cec5SDimitry Andric   if (MRI->getType(Idx).getSizeInBits() != PreferredVecIdxWidth) {
31695ffd83dbSDimitry Andric     const LLT VecIdxTy = LLT::scalar(PreferredVecIdxWidth);
3170bdd1243dSDimitry Andric     Idx = MIRBuilder.buildZExtOrTrunc(VecIdxTy, Idx).getReg(0);
31710b57cec5SDimitry Andric   }
31720b57cec5SDimitry Andric   MIRBuilder.buildExtractVectorElement(Res, Val, Idx);
31730b57cec5SDimitry Andric   return true;
31740b57cec5SDimitry Andric }
31750b57cec5SDimitry Andric 
translateShuffleVector(const User & U,MachineIRBuilder & MIRBuilder)31760b57cec5SDimitry Andric bool IRTranslator::translateShuffleVector(const User &U,
31770b57cec5SDimitry Andric                                           MachineIRBuilder &MIRBuilder) {
31780fca6ea1SDimitry Andric   // A ShuffleVector that has operates on scalable vectors is a splat vector
31790fca6ea1SDimitry Andric   // where the value of the splat vector is the 0th element of the first
31800fca6ea1SDimitry Andric   // operand, since the index mask operand is the zeroinitializer (undef and
31810fca6ea1SDimitry Andric   // poison are treated as zeroinitializer here).
31820fca6ea1SDimitry Andric   if (U.getOperand(0)->getType()->isScalableTy()) {
31830fca6ea1SDimitry Andric     Value *Op0 = U.getOperand(0);
31840fca6ea1SDimitry Andric     auto SplatVal = MIRBuilder.buildExtractVectorElementConstant(
31850fca6ea1SDimitry Andric         LLT::scalar(Op0->getType()->getScalarSizeInBits()),
31860fca6ea1SDimitry Andric         getOrCreateVReg(*Op0), 0);
31870fca6ea1SDimitry Andric     MIRBuilder.buildSplatVector(getOrCreateVReg(U), SplatVal);
31880fca6ea1SDimitry Andric     return true;
31890fca6ea1SDimitry Andric   }
31900fca6ea1SDimitry Andric 
31915ffd83dbSDimitry Andric   ArrayRef<int> Mask;
31925ffd83dbSDimitry Andric   if (auto *SVI = dyn_cast<ShuffleVectorInst>(&U))
31935ffd83dbSDimitry Andric     Mask = SVI->getShuffleMask();
31945ffd83dbSDimitry Andric   else
31955ffd83dbSDimitry Andric     Mask = cast<ConstantExpr>(U).getShuffleMask();
3196480093f4SDimitry Andric   ArrayRef<int> MaskAlloc = MF->allocateShuffleMask(Mask);
31975ffd83dbSDimitry Andric   MIRBuilder
31985ffd83dbSDimitry Andric       .buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {getOrCreateVReg(U)},
31995ffd83dbSDimitry Andric                   {getOrCreateVReg(*U.getOperand(0)),
32005ffd83dbSDimitry Andric                    getOrCreateVReg(*U.getOperand(1))})
3201480093f4SDimitry Andric       .addShuffleMask(MaskAlloc);
32020b57cec5SDimitry Andric   return true;
32030b57cec5SDimitry Andric }
32040b57cec5SDimitry Andric 
translatePHI(const User & U,MachineIRBuilder & MIRBuilder)32050b57cec5SDimitry Andric bool IRTranslator::translatePHI(const User &U, MachineIRBuilder &MIRBuilder) {
32060b57cec5SDimitry Andric   const PHINode &PI = cast<PHINode>(U);
32070b57cec5SDimitry Andric 
32080b57cec5SDimitry Andric   SmallVector<MachineInstr *, 4> Insts;
32090b57cec5SDimitry Andric   for (auto Reg : getOrCreateVRegs(PI)) {
32100b57cec5SDimitry Andric     auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, {Reg}, {});
32110b57cec5SDimitry Andric     Insts.push_back(MIB.getInstr());
32120b57cec5SDimitry Andric   }
32130b57cec5SDimitry Andric 
32140b57cec5SDimitry Andric   PendingPHIs.emplace_back(&PI, std::move(Insts));
32150b57cec5SDimitry Andric   return true;
32160b57cec5SDimitry Andric }
32170b57cec5SDimitry Andric 
translateAtomicCmpXchg(const User & U,MachineIRBuilder & MIRBuilder)32180b57cec5SDimitry Andric bool IRTranslator::translateAtomicCmpXchg(const User &U,
32190b57cec5SDimitry Andric                                           MachineIRBuilder &MIRBuilder) {
32200b57cec5SDimitry Andric   const AtomicCmpXchgInst &I = cast<AtomicCmpXchgInst>(U);
32210b57cec5SDimitry Andric 
32220fca6ea1SDimitry Andric   auto Flags = TLI->getAtomicMemOperandFlags(I, *DL);
32230b57cec5SDimitry Andric 
32240b57cec5SDimitry Andric   auto Res = getOrCreateVRegs(I);
32250b57cec5SDimitry Andric   Register OldValRes = Res[0];
32260b57cec5SDimitry Andric   Register SuccessRes = Res[1];
32270b57cec5SDimitry Andric   Register Addr = getOrCreateVReg(*I.getPointerOperand());
32280b57cec5SDimitry Andric   Register Cmp = getOrCreateVReg(*I.getCompareOperand());
32290b57cec5SDimitry Andric   Register NewVal = getOrCreateVReg(*I.getNewValOperand());
32300b57cec5SDimitry Andric 
32310b57cec5SDimitry Andric   MIRBuilder.buildAtomicCmpXchgWithSuccess(
32320b57cec5SDimitry Andric       OldValRes, SuccessRes, Addr, Cmp, NewVal,
32335ffd83dbSDimitry Andric       *MF->getMachineMemOperand(
3234fe6060f1SDimitry Andric           MachinePointerInfo(I.getPointerOperand()), Flags, MRI->getType(Cmp),
3235349cc55cSDimitry Andric           getMemOpAlign(I), I.getAAMetadata(), nullptr, I.getSyncScopeID(),
3236fe6060f1SDimitry Andric           I.getSuccessOrdering(), I.getFailureOrdering()));
32370b57cec5SDimitry Andric   return true;
32380b57cec5SDimitry Andric }
32390b57cec5SDimitry Andric 
translateAtomicRMW(const User & U,MachineIRBuilder & MIRBuilder)32400b57cec5SDimitry Andric bool IRTranslator::translateAtomicRMW(const User &U,
32410b57cec5SDimitry Andric                                       MachineIRBuilder &MIRBuilder) {
32420b57cec5SDimitry Andric   const AtomicRMWInst &I = cast<AtomicRMWInst>(U);
32430fca6ea1SDimitry Andric   auto Flags = TLI->getAtomicMemOperandFlags(I, *DL);
32440b57cec5SDimitry Andric 
32450b57cec5SDimitry Andric   Register Res = getOrCreateVReg(I);
32460b57cec5SDimitry Andric   Register Addr = getOrCreateVReg(*I.getPointerOperand());
32470b57cec5SDimitry Andric   Register Val = getOrCreateVReg(*I.getValOperand());
32480b57cec5SDimitry Andric 
32490b57cec5SDimitry Andric   unsigned Opcode = 0;
32500b57cec5SDimitry Andric   switch (I.getOperation()) {
32510b57cec5SDimitry Andric   default:
32520b57cec5SDimitry Andric     return false;
32530b57cec5SDimitry Andric   case AtomicRMWInst::Xchg:
32540b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_XCHG;
32550b57cec5SDimitry Andric     break;
32560b57cec5SDimitry Andric   case AtomicRMWInst::Add:
32570b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_ADD;
32580b57cec5SDimitry Andric     break;
32590b57cec5SDimitry Andric   case AtomicRMWInst::Sub:
32600b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_SUB;
32610b57cec5SDimitry Andric     break;
32620b57cec5SDimitry Andric   case AtomicRMWInst::And:
32630b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_AND;
32640b57cec5SDimitry Andric     break;
32650b57cec5SDimitry Andric   case AtomicRMWInst::Nand:
32660b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_NAND;
32670b57cec5SDimitry Andric     break;
32680b57cec5SDimitry Andric   case AtomicRMWInst::Or:
32690b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_OR;
32700b57cec5SDimitry Andric     break;
32710b57cec5SDimitry Andric   case AtomicRMWInst::Xor:
32720b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_XOR;
32730b57cec5SDimitry Andric     break;
32740b57cec5SDimitry Andric   case AtomicRMWInst::Max:
32750b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_MAX;
32760b57cec5SDimitry Andric     break;
32770b57cec5SDimitry Andric   case AtomicRMWInst::Min:
32780b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_MIN;
32790b57cec5SDimitry Andric     break;
32800b57cec5SDimitry Andric   case AtomicRMWInst::UMax:
32810b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_UMAX;
32820b57cec5SDimitry Andric     break;
32830b57cec5SDimitry Andric   case AtomicRMWInst::UMin:
32840b57cec5SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_UMIN;
32850b57cec5SDimitry Andric     break;
32868bcb0991SDimitry Andric   case AtomicRMWInst::FAdd:
32878bcb0991SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_FADD;
32888bcb0991SDimitry Andric     break;
32898bcb0991SDimitry Andric   case AtomicRMWInst::FSub:
32908bcb0991SDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_FSUB;
32918bcb0991SDimitry Andric     break;
3292753f127fSDimitry Andric   case AtomicRMWInst::FMax:
3293753f127fSDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_FMAX;
3294753f127fSDimitry Andric     break;
3295753f127fSDimitry Andric   case AtomicRMWInst::FMin:
3296753f127fSDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_FMIN;
3297753f127fSDimitry Andric     break;
3298bdd1243dSDimitry Andric   case AtomicRMWInst::UIncWrap:
3299bdd1243dSDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_UINC_WRAP;
3300bdd1243dSDimitry Andric     break;
3301bdd1243dSDimitry Andric   case AtomicRMWInst::UDecWrap:
3302bdd1243dSDimitry Andric     Opcode = TargetOpcode::G_ATOMICRMW_UDEC_WRAP;
3303bdd1243dSDimitry Andric     break;
33040b57cec5SDimitry Andric   }
33050b57cec5SDimitry Andric 
33060b57cec5SDimitry Andric   MIRBuilder.buildAtomicRMW(
33070b57cec5SDimitry Andric       Opcode, Res, Addr, Val,
33080b57cec5SDimitry Andric       *MF->getMachineMemOperand(MachinePointerInfo(I.getPointerOperand()),
3309fe6060f1SDimitry Andric                                 Flags, MRI->getType(Val), getMemOpAlign(I),
3310349cc55cSDimitry Andric                                 I.getAAMetadata(), nullptr, I.getSyncScopeID(),
3311fe6060f1SDimitry Andric                                 I.getOrdering()));
33120b57cec5SDimitry Andric   return true;
33130b57cec5SDimitry Andric }
33140b57cec5SDimitry Andric 
translateFence(const User & U,MachineIRBuilder & MIRBuilder)33150b57cec5SDimitry Andric bool IRTranslator::translateFence(const User &U,
33160b57cec5SDimitry Andric                                   MachineIRBuilder &MIRBuilder) {
33170b57cec5SDimitry Andric   const FenceInst &Fence = cast<FenceInst>(U);
33180b57cec5SDimitry Andric   MIRBuilder.buildFence(static_cast<unsigned>(Fence.getOrdering()),
33190b57cec5SDimitry Andric                         Fence.getSyncScopeID());
33200b57cec5SDimitry Andric   return true;
33210b57cec5SDimitry Andric }
33220b57cec5SDimitry Andric 
translateFreeze(const User & U,MachineIRBuilder & MIRBuilder)33235ffd83dbSDimitry Andric bool IRTranslator::translateFreeze(const User &U,
33245ffd83dbSDimitry Andric                                    MachineIRBuilder &MIRBuilder) {
33255ffd83dbSDimitry Andric   const ArrayRef<Register> DstRegs = getOrCreateVRegs(U);
33265ffd83dbSDimitry Andric   const ArrayRef<Register> SrcRegs = getOrCreateVRegs(*U.getOperand(0));
33275ffd83dbSDimitry Andric 
33285ffd83dbSDimitry Andric   assert(DstRegs.size() == SrcRegs.size() &&
33295ffd83dbSDimitry Andric          "Freeze with different source and destination type?");
33305ffd83dbSDimitry Andric 
33315ffd83dbSDimitry Andric   for (unsigned I = 0; I < DstRegs.size(); ++I) {
33325ffd83dbSDimitry Andric     MIRBuilder.buildFreeze(DstRegs[I], SrcRegs[I]);
33335ffd83dbSDimitry Andric   }
33345ffd83dbSDimitry Andric 
33355ffd83dbSDimitry Andric   return true;
33365ffd83dbSDimitry Andric }
33375ffd83dbSDimitry Andric 
finishPendingPhis()33380b57cec5SDimitry Andric void IRTranslator::finishPendingPhis() {
33390b57cec5SDimitry Andric #ifndef NDEBUG
33400b57cec5SDimitry Andric   DILocationVerifier Verifier;
33410b57cec5SDimitry Andric   GISelObserverWrapper WrapperObserver(&Verifier);
33420b57cec5SDimitry Andric   RAIIDelegateInstaller DelInstall(*MF, &WrapperObserver);
33430b57cec5SDimitry Andric #endif // ifndef NDEBUG
33440b57cec5SDimitry Andric   for (auto &Phi : PendingPHIs) {
33450b57cec5SDimitry Andric     const PHINode *PI = Phi.first;
33467a6dacacSDimitry Andric     if (PI->getType()->isEmptyTy())
33477a6dacacSDimitry Andric       continue;
33480b57cec5SDimitry Andric     ArrayRef<MachineInstr *> ComponentPHIs = Phi.second;
33490b57cec5SDimitry Andric     MachineBasicBlock *PhiMBB = ComponentPHIs[0]->getParent();
33500b57cec5SDimitry Andric     EntryBuilder->setDebugLoc(PI->getDebugLoc());
33510b57cec5SDimitry Andric #ifndef NDEBUG
33520b57cec5SDimitry Andric     Verifier.setCurrentInst(PI);
33530b57cec5SDimitry Andric #endif // ifndef NDEBUG
33540b57cec5SDimitry Andric 
33550b57cec5SDimitry Andric     SmallSet<const MachineBasicBlock *, 16> SeenPreds;
33560b57cec5SDimitry Andric     for (unsigned i = 0; i < PI->getNumIncomingValues(); ++i) {
33570b57cec5SDimitry Andric       auto IRPred = PI->getIncomingBlock(i);
33580b57cec5SDimitry Andric       ArrayRef<Register> ValRegs = getOrCreateVRegs(*PI->getIncomingValue(i));
3359fcaf7f86SDimitry Andric       for (auto *Pred : getMachinePredBBs({IRPred, PI->getParent()})) {
33600b57cec5SDimitry Andric         if (SeenPreds.count(Pred) || !PhiMBB->isPredecessor(Pred))
33610b57cec5SDimitry Andric           continue;
33620b57cec5SDimitry Andric         SeenPreds.insert(Pred);
33630b57cec5SDimitry Andric         for (unsigned j = 0; j < ValRegs.size(); ++j) {
33640b57cec5SDimitry Andric           MachineInstrBuilder MIB(*MF, ComponentPHIs[j]);
33650b57cec5SDimitry Andric           MIB.addUse(ValRegs[j]);
33660b57cec5SDimitry Andric           MIB.addMBB(Pred);
33670b57cec5SDimitry Andric         }
33680b57cec5SDimitry Andric       }
33690b57cec5SDimitry Andric     }
33700b57cec5SDimitry Andric   }
33710b57cec5SDimitry Andric }
33720b57cec5SDimitry Andric 
translateDbgValueRecord(Value * V,bool HasArgList,const DILocalVariable * Variable,const DIExpression * Expression,const DebugLoc & DL,MachineIRBuilder & MIRBuilder)33737a6dacacSDimitry Andric void IRTranslator::translateDbgValueRecord(Value *V, bool HasArgList,
33747a6dacacSDimitry Andric                                      const DILocalVariable *Variable,
33757a6dacacSDimitry Andric                                      const DIExpression *Expression,
33767a6dacacSDimitry Andric                                      const DebugLoc &DL,
33777a6dacacSDimitry Andric                                      MachineIRBuilder &MIRBuilder) {
33787a6dacacSDimitry Andric   assert(Variable->isValidLocationForIntrinsic(DL) &&
33797a6dacacSDimitry Andric          "Expected inlined-at fields to agree");
33807a6dacacSDimitry Andric   // Act as if we're handling a debug intrinsic.
33817a6dacacSDimitry Andric   MIRBuilder.setDebugLoc(DL);
33827a6dacacSDimitry Andric 
33837a6dacacSDimitry Andric   if (!V || HasArgList) {
33847a6dacacSDimitry Andric     // DI cannot produce a valid DBG_VALUE, so produce an undef DBG_VALUE to
33857a6dacacSDimitry Andric     // terminate any prior location.
33867a6dacacSDimitry Andric     MIRBuilder.buildIndirectDbgValue(0, Variable, Expression);
33877a6dacacSDimitry Andric     return;
33887a6dacacSDimitry Andric   }
33897a6dacacSDimitry Andric 
33907a6dacacSDimitry Andric   if (const auto *CI = dyn_cast<Constant>(V)) {
33917a6dacacSDimitry Andric     MIRBuilder.buildConstDbgValue(*CI, Variable, Expression);
33927a6dacacSDimitry Andric     return;
33937a6dacacSDimitry Andric   }
33947a6dacacSDimitry Andric 
33957a6dacacSDimitry Andric   if (auto *AI = dyn_cast<AllocaInst>(V);
33967a6dacacSDimitry Andric       AI && AI->isStaticAlloca() && Expression->startsWithDeref()) {
33977a6dacacSDimitry Andric     // If the value is an alloca and the expression starts with a
33987a6dacacSDimitry Andric     // dereference, track a stack slot instead of a register, as registers
33997a6dacacSDimitry Andric     // may be clobbered.
34007a6dacacSDimitry Andric     auto ExprOperands = Expression->getElements();
34017a6dacacSDimitry Andric     auto *ExprDerefRemoved =
34027a6dacacSDimitry Andric         DIExpression::get(AI->getContext(), ExprOperands.drop_front());
34037a6dacacSDimitry Andric     MIRBuilder.buildFIDbgValue(getOrCreateFrameIndex(*AI), Variable,
34047a6dacacSDimitry Andric                                ExprDerefRemoved);
34057a6dacacSDimitry Andric     return;
34067a6dacacSDimitry Andric   }
34077a6dacacSDimitry Andric   if (translateIfEntryValueArgument(false, V, Variable, Expression, DL,
34087a6dacacSDimitry Andric                                     MIRBuilder))
34097a6dacacSDimitry Andric     return;
34107a6dacacSDimitry Andric   for (Register Reg : getOrCreateVRegs(*V)) {
34117a6dacacSDimitry Andric     // FIXME: This does not handle register-indirect values at offset 0. The
34127a6dacacSDimitry Andric     // direct/indirect thing shouldn't really be handled by something as
34137a6dacacSDimitry Andric     // implicit as reg+noreg vs reg+imm in the first place, but it seems
34147a6dacacSDimitry Andric     // pretty baked in right now.
34157a6dacacSDimitry Andric     MIRBuilder.buildDirectDbgValue(Reg, Variable, Expression);
34167a6dacacSDimitry Andric   }
34177a6dacacSDimitry Andric   return;
34187a6dacacSDimitry Andric }
34197a6dacacSDimitry Andric 
translateDbgDeclareRecord(Value * Address,bool HasArgList,const DILocalVariable * Variable,const DIExpression * Expression,const DebugLoc & DL,MachineIRBuilder & MIRBuilder)34207a6dacacSDimitry Andric void IRTranslator::translateDbgDeclareRecord(Value *Address, bool HasArgList,
34217a6dacacSDimitry Andric                                      const DILocalVariable *Variable,
34227a6dacacSDimitry Andric                                      const DIExpression *Expression,
34237a6dacacSDimitry Andric                                      const DebugLoc &DL,
34247a6dacacSDimitry Andric                                      MachineIRBuilder &MIRBuilder) {
34257a6dacacSDimitry Andric   if (!Address || isa<UndefValue>(Address)) {
34267a6dacacSDimitry Andric     LLVM_DEBUG(dbgs() << "Dropping debug info for " << *Variable << "\n");
34277a6dacacSDimitry Andric     return;
34287a6dacacSDimitry Andric   }
34297a6dacacSDimitry Andric 
34307a6dacacSDimitry Andric   assert(Variable->isValidLocationForIntrinsic(DL) &&
34317a6dacacSDimitry Andric          "Expected inlined-at fields to agree");
34327a6dacacSDimitry Andric   auto AI = dyn_cast<AllocaInst>(Address);
34337a6dacacSDimitry Andric   if (AI && AI->isStaticAlloca()) {
34347a6dacacSDimitry Andric     // Static allocas are tracked at the MF level, no need for DBG_VALUE
34357a6dacacSDimitry Andric     // instructions (in fact, they get ignored if they *do* exist).
34367a6dacacSDimitry Andric     MF->setVariableDbgInfo(Variable, Expression,
34377a6dacacSDimitry Andric                            getOrCreateFrameIndex(*AI), DL);
34387a6dacacSDimitry Andric     return;
34397a6dacacSDimitry Andric   }
34407a6dacacSDimitry Andric 
34417a6dacacSDimitry Andric   if (translateIfEntryValueArgument(true, Address, Variable,
34427a6dacacSDimitry Andric                                     Expression, DL,
34437a6dacacSDimitry Andric                                     MIRBuilder))
34447a6dacacSDimitry Andric     return;
34457a6dacacSDimitry Andric 
34467a6dacacSDimitry Andric   // A dbg.declare describes the address of a source variable, so lower it
34477a6dacacSDimitry Andric   // into an indirect DBG_VALUE.
34487a6dacacSDimitry Andric   MIRBuilder.setDebugLoc(DL);
34497a6dacacSDimitry Andric   MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address),
34507a6dacacSDimitry Andric                                    Variable, Expression);
34517a6dacacSDimitry Andric   return;
34527a6dacacSDimitry Andric }
34537a6dacacSDimitry Andric 
translateDbgInfo(const Instruction & Inst,MachineIRBuilder & MIRBuilder)34547a6dacacSDimitry Andric void IRTranslator::translateDbgInfo(const Instruction &Inst,
34557a6dacacSDimitry Andric                                       MachineIRBuilder &MIRBuilder) {
34560fca6ea1SDimitry Andric   for (DbgRecord &DR : Inst.getDbgRecordRange()) {
34570fca6ea1SDimitry Andric     if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) {
34580fca6ea1SDimitry Andric       MIRBuilder.setDebugLoc(DLR->getDebugLoc());
34590fca6ea1SDimitry Andric       assert(DLR->getLabel() && "Missing label");
34600fca6ea1SDimitry Andric       assert(DLR->getLabel()->isValidLocationForIntrinsic(
34610fca6ea1SDimitry Andric                  MIRBuilder.getDebugLoc()) &&
34620fca6ea1SDimitry Andric              "Expected inlined-at fields to agree");
34630fca6ea1SDimitry Andric       MIRBuilder.buildDbgLabel(DLR->getLabel());
34640fca6ea1SDimitry Andric       continue;
34650fca6ea1SDimitry Andric     }
34660fca6ea1SDimitry Andric     DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR);
34670fca6ea1SDimitry Andric     const DILocalVariable *Variable = DVR.getVariable();
34680fca6ea1SDimitry Andric     const DIExpression *Expression = DVR.getExpression();
34690fca6ea1SDimitry Andric     Value *V = DVR.getVariableLocationOp(0);
34700fca6ea1SDimitry Andric     if (DVR.isDbgDeclare())
34710fca6ea1SDimitry Andric       translateDbgDeclareRecord(V, DVR.hasArgList(), Variable, Expression,
34720fca6ea1SDimitry Andric                                 DVR.getDebugLoc(), MIRBuilder);
34737a6dacacSDimitry Andric     else
34740fca6ea1SDimitry Andric       translateDbgValueRecord(V, DVR.hasArgList(), Variable, Expression,
34750fca6ea1SDimitry Andric                               DVR.getDebugLoc(), MIRBuilder);
34767a6dacacSDimitry Andric   }
34777a6dacacSDimitry Andric }
34787a6dacacSDimitry Andric 
translate(const Instruction & Inst)34790b57cec5SDimitry Andric bool IRTranslator::translate(const Instruction &Inst) {
34800b57cec5SDimitry Andric   CurBuilder->setDebugLoc(Inst.getDebugLoc());
3481bdd1243dSDimitry Andric   CurBuilder->setPCSections(Inst.getMetadata(LLVMContext::MD_pcsections));
34820fca6ea1SDimitry Andric   CurBuilder->setMMRAMetadata(Inst.getMetadata(LLVMContext::MD_mmra));
34830b57cec5SDimitry Andric 
34840fca6ea1SDimitry Andric   if (TLI->fallBackToDAGISel(Inst))
34855ffd83dbSDimitry Andric     return false;
34865ffd83dbSDimitry Andric 
34870b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
34880b57cec5SDimitry Andric #define HANDLE_INST(NUM, OPCODE, CLASS)                                        \
34890b57cec5SDimitry Andric   case Instruction::OPCODE:                                                    \
34900b57cec5SDimitry Andric     return translate##OPCODE(Inst, *CurBuilder.get());
34910b57cec5SDimitry Andric #include "llvm/IR/Instruction.def"
34920b57cec5SDimitry Andric   default:
34930b57cec5SDimitry Andric     return false;
34940b57cec5SDimitry Andric   }
34950b57cec5SDimitry Andric }
34960b57cec5SDimitry Andric 
translate(const Constant & C,Register Reg)34970b57cec5SDimitry Andric bool IRTranslator::translate(const Constant &C, Register Reg) {
3498fe6060f1SDimitry Andric   // We only emit constants into the entry block from here. To prevent jumpy
3499972a253aSDimitry Andric   // debug behaviour remove debug line.
3500fe6060f1SDimitry Andric   if (auto CurrInstDL = CurBuilder->getDL())
3501972a253aSDimitry Andric     EntryBuilder->setDebugLoc(DebugLoc());
3502fe6060f1SDimitry Andric 
35030b57cec5SDimitry Andric   if (auto CI = dyn_cast<ConstantInt>(&C))
35040b57cec5SDimitry Andric     EntryBuilder->buildConstant(Reg, *CI);
35050b57cec5SDimitry Andric   else if (auto CF = dyn_cast<ConstantFP>(&C))
35060b57cec5SDimitry Andric     EntryBuilder->buildFConstant(Reg, *CF);
35070b57cec5SDimitry Andric   else if (isa<UndefValue>(C))
35080b57cec5SDimitry Andric     EntryBuilder->buildUndef(Reg);
35095ffd83dbSDimitry Andric   else if (isa<ConstantPointerNull>(C))
35105ffd83dbSDimitry Andric     EntryBuilder->buildConstant(Reg, 0);
35115ffd83dbSDimitry Andric   else if (auto GV = dyn_cast<GlobalValue>(&C))
35120b57cec5SDimitry Andric     EntryBuilder->buildGlobalValue(Reg, GV);
35130fca6ea1SDimitry Andric   else if (auto CPA = dyn_cast<ConstantPtrAuth>(&C)) {
35140fca6ea1SDimitry Andric     Register Addr = getOrCreateVReg(*CPA->getPointer());
35150fca6ea1SDimitry Andric     Register AddrDisc = getOrCreateVReg(*CPA->getAddrDiscriminator());
35160fca6ea1SDimitry Andric     EntryBuilder->buildConstantPtrAuth(Reg, CPA, Addr, AddrDisc);
35170fca6ea1SDimitry Andric   } else if (auto CAZ = dyn_cast<ConstantAggregateZero>(&C)) {
3518fe6060f1SDimitry Andric     if (!isa<FixedVectorType>(CAZ->getType()))
35190b57cec5SDimitry Andric       return false;
35200b57cec5SDimitry Andric     // Return the scalar if it is a <1 x Ty> vector.
3521fe6060f1SDimitry Andric     unsigned NumElts = CAZ->getElementCount().getFixedValue();
3522fe6060f1SDimitry Andric     if (NumElts == 1)
352381ad6265SDimitry Andric       return translateCopy(C, *CAZ->getElementValue(0u), *EntryBuilder);
35240b57cec5SDimitry Andric     SmallVector<Register, 4> Ops;
3525fe6060f1SDimitry Andric     for (unsigned I = 0; I < NumElts; ++I) {
3526fe6060f1SDimitry Andric       Constant &Elt = *CAZ->getElementValue(I);
35270b57cec5SDimitry Andric       Ops.push_back(getOrCreateVReg(Elt));
35280b57cec5SDimitry Andric     }
35290b57cec5SDimitry Andric     EntryBuilder->buildBuildVector(Reg, Ops);
35300b57cec5SDimitry Andric   } else if (auto CV = dyn_cast<ConstantDataVector>(&C)) {
35310b57cec5SDimitry Andric     // Return the scalar if it is a <1 x Ty> vector.
35320b57cec5SDimitry Andric     if (CV->getNumElements() == 1)
353381ad6265SDimitry Andric       return translateCopy(C, *CV->getElementAsConstant(0), *EntryBuilder);
35340b57cec5SDimitry Andric     SmallVector<Register, 4> Ops;
35350b57cec5SDimitry Andric     for (unsigned i = 0; i < CV->getNumElements(); ++i) {
35360b57cec5SDimitry Andric       Constant &Elt = *CV->getElementAsConstant(i);
35370b57cec5SDimitry Andric       Ops.push_back(getOrCreateVReg(Elt));
35380b57cec5SDimitry Andric     }
35390b57cec5SDimitry Andric     EntryBuilder->buildBuildVector(Reg, Ops);
35400b57cec5SDimitry Andric   } else if (auto CE = dyn_cast<ConstantExpr>(&C)) {
35410b57cec5SDimitry Andric     switch(CE->getOpcode()) {
35420b57cec5SDimitry Andric #define HANDLE_INST(NUM, OPCODE, CLASS)                                        \
35430b57cec5SDimitry Andric   case Instruction::OPCODE:                                                    \
35440b57cec5SDimitry Andric     return translate##OPCODE(*CE, *EntryBuilder.get());
35450b57cec5SDimitry Andric #include "llvm/IR/Instruction.def"
35460b57cec5SDimitry Andric     default:
35470b57cec5SDimitry Andric       return false;
35480b57cec5SDimitry Andric     }
35490b57cec5SDimitry Andric   } else if (auto CV = dyn_cast<ConstantVector>(&C)) {
35500b57cec5SDimitry Andric     if (CV->getNumOperands() == 1)
355181ad6265SDimitry Andric       return translateCopy(C, *CV->getOperand(0), *EntryBuilder);
35520b57cec5SDimitry Andric     SmallVector<Register, 4> Ops;
35530b57cec5SDimitry Andric     for (unsigned i = 0; i < CV->getNumOperands(); ++i) {
35540b57cec5SDimitry Andric       Ops.push_back(getOrCreateVReg(*CV->getOperand(i)));
35550b57cec5SDimitry Andric     }
35560b57cec5SDimitry Andric     EntryBuilder->buildBuildVector(Reg, Ops);
35570b57cec5SDimitry Andric   } else if (auto *BA = dyn_cast<BlockAddress>(&C)) {
35580b57cec5SDimitry Andric     EntryBuilder->buildBlockAddress(Reg, BA);
35590b57cec5SDimitry Andric   } else
35600b57cec5SDimitry Andric     return false;
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric   return true;
35630b57cec5SDimitry Andric }
35640b57cec5SDimitry Andric 
finalizeBasicBlock(const BasicBlock & BB,MachineBasicBlock & MBB)3565349cc55cSDimitry Andric bool IRTranslator::finalizeBasicBlock(const BasicBlock &BB,
3566349cc55cSDimitry Andric                                       MachineBasicBlock &MBB) {
3567e8d8bef9SDimitry Andric   for (auto &BTB : SL->BitTestCases) {
3568e8d8bef9SDimitry Andric     // Emit header first, if it wasn't already emitted.
3569e8d8bef9SDimitry Andric     if (!BTB.Emitted)
3570e8d8bef9SDimitry Andric       emitBitTestHeader(BTB, BTB.Parent);
3571e8d8bef9SDimitry Andric 
3572e8d8bef9SDimitry Andric     BranchProbability UnhandledProb = BTB.Prob;
3573e8d8bef9SDimitry Andric     for (unsigned j = 0, ej = BTB.Cases.size(); j != ej; ++j) {
3574e8d8bef9SDimitry Andric       UnhandledProb -= BTB.Cases[j].ExtraProb;
3575e8d8bef9SDimitry Andric       // Set the current basic block to the mbb we wish to insert the code into
3576e8d8bef9SDimitry Andric       MachineBasicBlock *MBB = BTB.Cases[j].ThisBB;
3577e8d8bef9SDimitry Andric       // If all cases cover a contiguous range, it is not necessary to jump to
3578e8d8bef9SDimitry Andric       // the default block after the last bit test fails. This is because the
3579e8d8bef9SDimitry Andric       // range check during bit test header creation has guaranteed that every
3580e8d8bef9SDimitry Andric       // case here doesn't go outside the range. In this case, there is no need
3581e8d8bef9SDimitry Andric       // to perform the last bit test, as it will always be true. Instead, make
3582e8d8bef9SDimitry Andric       // the second-to-last bit-test fall through to the target of the last bit
3583e8d8bef9SDimitry Andric       // test, and delete the last bit test.
3584e8d8bef9SDimitry Andric 
3585e8d8bef9SDimitry Andric       MachineBasicBlock *NextMBB;
3586349cc55cSDimitry Andric       if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
3587e8d8bef9SDimitry Andric         // Second-to-last bit-test with contiguous range: fall through to the
3588e8d8bef9SDimitry Andric         // target of the final bit test.
3589e8d8bef9SDimitry Andric         NextMBB = BTB.Cases[j + 1].TargetBB;
3590e8d8bef9SDimitry Andric       } else if (j + 1 == ej) {
3591e8d8bef9SDimitry Andric         // For the last bit test, fall through to Default.
3592e8d8bef9SDimitry Andric         NextMBB = BTB.Default;
3593e8d8bef9SDimitry Andric       } else {
3594e8d8bef9SDimitry Andric         // Otherwise, fall through to the next bit test.
3595e8d8bef9SDimitry Andric         NextMBB = BTB.Cases[j + 1].ThisBB;
3596e8d8bef9SDimitry Andric       }
3597e8d8bef9SDimitry Andric 
3598e8d8bef9SDimitry Andric       emitBitTestCase(BTB, NextMBB, UnhandledProb, BTB.Reg, BTB.Cases[j], MBB);
3599e8d8bef9SDimitry Andric 
3600349cc55cSDimitry Andric       if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
3601fe6060f1SDimitry Andric         // We need to record the replacement phi edge here that normally
3602fe6060f1SDimitry Andric         // happens in emitBitTestCase before we delete the case, otherwise the
3603fe6060f1SDimitry Andric         // phi edge will be lost.
3604fe6060f1SDimitry Andric         addMachineCFGPred({BTB.Parent->getBasicBlock(),
3605fe6060f1SDimitry Andric                            BTB.Cases[ej - 1].TargetBB->getBasicBlock()},
3606fe6060f1SDimitry Andric                           MBB);
3607e8d8bef9SDimitry Andric         // Since we're not going to use the final bit test, remove it.
3608e8d8bef9SDimitry Andric         BTB.Cases.pop_back();
3609e8d8bef9SDimitry Andric         break;
3610e8d8bef9SDimitry Andric       }
3611e8d8bef9SDimitry Andric     }
3612e8d8bef9SDimitry Andric     // This is "default" BB. We have two jumps to it. From "header" BB and from
3613e8d8bef9SDimitry Andric     // last "case" BB, unless the latter was skipped.
3614e8d8bef9SDimitry Andric     CFGEdge HeaderToDefaultEdge = {BTB.Parent->getBasicBlock(),
3615e8d8bef9SDimitry Andric                                    BTB.Default->getBasicBlock()};
3616e8d8bef9SDimitry Andric     addMachineCFGPred(HeaderToDefaultEdge, BTB.Parent);
3617e8d8bef9SDimitry Andric     if (!BTB.ContiguousRange) {
3618e8d8bef9SDimitry Andric       addMachineCFGPred(HeaderToDefaultEdge, BTB.Cases.back().ThisBB);
3619e8d8bef9SDimitry Andric     }
3620e8d8bef9SDimitry Andric   }
3621e8d8bef9SDimitry Andric   SL->BitTestCases.clear();
3622e8d8bef9SDimitry Andric 
36230b57cec5SDimitry Andric   for (auto &JTCase : SL->JTCases) {
36240b57cec5SDimitry Andric     // Emit header first, if it wasn't already emitted.
36250b57cec5SDimitry Andric     if (!JTCase.first.Emitted)
36260b57cec5SDimitry Andric       emitJumpTableHeader(JTCase.second, JTCase.first, JTCase.first.HeaderBB);
36270b57cec5SDimitry Andric 
36280b57cec5SDimitry Andric     emitJumpTable(JTCase.second, JTCase.second.MBB);
36290b57cec5SDimitry Andric   }
36300b57cec5SDimitry Andric   SL->JTCases.clear();
3631e8d8bef9SDimitry Andric 
3632e8d8bef9SDimitry Andric   for (auto &SwCase : SL->SwitchCases)
3633e8d8bef9SDimitry Andric     emitSwitchCase(SwCase, &CurBuilder->getMBB(), *CurBuilder);
3634e8d8bef9SDimitry Andric   SL->SwitchCases.clear();
3635349cc55cSDimitry Andric 
3636349cc55cSDimitry Andric   // Check if we need to generate stack-protector guard checks.
3637349cc55cSDimitry Andric   StackProtector &SP = getAnalysis<StackProtector>();
3638349cc55cSDimitry Andric   if (SP.shouldEmitSDCheck(BB)) {
3639349cc55cSDimitry Andric     bool FunctionBasedInstrumentation =
36400fca6ea1SDimitry Andric         TLI->getSSPStackGuardCheck(*MF->getFunction().getParent());
3641349cc55cSDimitry Andric     SPDescriptor.initialize(&BB, &MBB, FunctionBasedInstrumentation);
3642349cc55cSDimitry Andric   }
3643349cc55cSDimitry Andric   // Handle stack protector.
3644349cc55cSDimitry Andric   if (SPDescriptor.shouldEmitFunctionBasedCheckStackProtector()) {
3645349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Unimplemented stack protector case\n");
3646349cc55cSDimitry Andric     return false;
3647349cc55cSDimitry Andric   } else if (SPDescriptor.shouldEmitStackProtector()) {
3648349cc55cSDimitry Andric     MachineBasicBlock *ParentMBB = SPDescriptor.getParentMBB();
3649349cc55cSDimitry Andric     MachineBasicBlock *SuccessMBB = SPDescriptor.getSuccessMBB();
3650349cc55cSDimitry Andric 
3651349cc55cSDimitry Andric     // Find the split point to split the parent mbb. At the same time copy all
3652349cc55cSDimitry Andric     // physical registers used in the tail of parent mbb into virtual registers
3653349cc55cSDimitry Andric     // before the split point and back into physical registers after the split
3654349cc55cSDimitry Andric     // point. This prevents us needing to deal with Live-ins and many other
3655349cc55cSDimitry Andric     // register allocation issues caused by us splitting the parent mbb. The
3656349cc55cSDimitry Andric     // register allocator will clean up said virtual copies later on.
3657349cc55cSDimitry Andric     MachineBasicBlock::iterator SplitPoint = findSplitPointForStackProtector(
3658349cc55cSDimitry Andric         ParentMBB, *MF->getSubtarget().getInstrInfo());
3659349cc55cSDimitry Andric 
3660349cc55cSDimitry Andric     // Splice the terminator of ParentMBB into SuccessMBB.
3661349cc55cSDimitry Andric     SuccessMBB->splice(SuccessMBB->end(), ParentMBB, SplitPoint,
3662349cc55cSDimitry Andric                        ParentMBB->end());
3663349cc55cSDimitry Andric 
3664349cc55cSDimitry Andric     // Add compare/jump on neq/jump to the parent BB.
3665349cc55cSDimitry Andric     if (!emitSPDescriptorParent(SPDescriptor, ParentMBB))
3666349cc55cSDimitry Andric       return false;
3667349cc55cSDimitry Andric 
3668349cc55cSDimitry Andric     // CodeGen Failure MBB if we have not codegened it yet.
3669349cc55cSDimitry Andric     MachineBasicBlock *FailureMBB = SPDescriptor.getFailureMBB();
3670349cc55cSDimitry Andric     if (FailureMBB->empty()) {
3671349cc55cSDimitry Andric       if (!emitSPDescriptorFailure(SPDescriptor, FailureMBB))
3672349cc55cSDimitry Andric         return false;
3673349cc55cSDimitry Andric     }
3674349cc55cSDimitry Andric 
3675349cc55cSDimitry Andric     // Clear the Per-BB State.
3676349cc55cSDimitry Andric     SPDescriptor.resetPerBBState();
3677349cc55cSDimitry Andric   }
3678349cc55cSDimitry Andric   return true;
3679349cc55cSDimitry Andric }
3680349cc55cSDimitry Andric 
emitSPDescriptorParent(StackProtectorDescriptor & SPD,MachineBasicBlock * ParentBB)3681349cc55cSDimitry Andric bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
3682349cc55cSDimitry Andric                                           MachineBasicBlock *ParentBB) {
3683349cc55cSDimitry Andric   CurBuilder->setInsertPt(*ParentBB, ParentBB->end());
3684349cc55cSDimitry Andric   // First create the loads to the guard/stack slot for the comparison.
36855f757f3fSDimitry Andric   Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
3686349cc55cSDimitry Andric   const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
36870fca6ea1SDimitry Andric   LLT PtrMemTy = getLLTForMVT(TLI->getPointerMemTy(*DL));
3688349cc55cSDimitry Andric 
3689349cc55cSDimitry Andric   MachineFrameInfo &MFI = ParentBB->getParent()->getFrameInfo();
3690349cc55cSDimitry Andric   int FI = MFI.getStackProtectorIndex();
3691349cc55cSDimitry Andric 
3692349cc55cSDimitry Andric   Register Guard;
3693349cc55cSDimitry Andric   Register StackSlotPtr = CurBuilder->buildFrameIndex(PtrTy, FI).getReg(0);
3694349cc55cSDimitry Andric   const Module &M = *ParentBB->getParent()->getFunction().getParent();
36955f757f3fSDimitry Andric   Align Align = DL->getPrefTypeAlign(PointerType::getUnqual(M.getContext()));
3696349cc55cSDimitry Andric 
3697349cc55cSDimitry Andric   // Generate code to load the content of the guard slot.
3698349cc55cSDimitry Andric   Register GuardVal =
3699349cc55cSDimitry Andric       CurBuilder
3700349cc55cSDimitry Andric           ->buildLoad(PtrMemTy, StackSlotPtr,
3701349cc55cSDimitry Andric                       MachinePointerInfo::getFixedStack(*MF, FI), Align,
3702349cc55cSDimitry Andric                       MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile)
3703349cc55cSDimitry Andric           .getReg(0);
3704349cc55cSDimitry Andric 
37050fca6ea1SDimitry Andric   if (TLI->useStackGuardXorFP()) {
3706349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Stack protector xor'ing with FP not yet implemented");
3707349cc55cSDimitry Andric     return false;
3708349cc55cSDimitry Andric   }
3709349cc55cSDimitry Andric 
3710349cc55cSDimitry Andric   // Retrieve guard check function, nullptr if instrumentation is inlined.
37110fca6ea1SDimitry Andric   if (const Function *GuardCheckFn = TLI->getSSPStackGuardCheck(M)) {
3712349cc55cSDimitry Andric     // This path is currently untestable on GlobalISel, since the only platform
3713349cc55cSDimitry Andric     // that needs this seems to be Windows, and we fall back on that currently.
3714349cc55cSDimitry Andric     // The code still lives here in case that changes.
3715349cc55cSDimitry Andric     // Silence warning about unused variable until the code below that uses
3716349cc55cSDimitry Andric     // 'GuardCheckFn' is enabled.
3717349cc55cSDimitry Andric     (void)GuardCheckFn;
3718349cc55cSDimitry Andric     return false;
3719349cc55cSDimitry Andric #if 0
3720349cc55cSDimitry Andric     // The target provides a guard check function to validate the guard value.
3721349cc55cSDimitry Andric     // Generate a call to that function with the content of the guard slot as
3722349cc55cSDimitry Andric     // argument.
3723349cc55cSDimitry Andric     FunctionType *FnTy = GuardCheckFn->getFunctionType();
3724349cc55cSDimitry Andric     assert(FnTy->getNumParams() == 1 && "Invalid function signature");
3725349cc55cSDimitry Andric     ISD::ArgFlagsTy Flags;
3726349cc55cSDimitry Andric     if (GuardCheckFn->hasAttribute(1, Attribute::AttrKind::InReg))
3727349cc55cSDimitry Andric       Flags.setInReg();
3728349cc55cSDimitry Andric     CallLowering::ArgInfo GuardArgInfo(
3729349cc55cSDimitry Andric         {GuardVal, FnTy->getParamType(0), {Flags}});
3730349cc55cSDimitry Andric 
3731349cc55cSDimitry Andric     CallLowering::CallLoweringInfo Info;
3732349cc55cSDimitry Andric     Info.OrigArgs.push_back(GuardArgInfo);
3733349cc55cSDimitry Andric     Info.CallConv = GuardCheckFn->getCallingConv();
3734349cc55cSDimitry Andric     Info.Callee = MachineOperand::CreateGA(GuardCheckFn, 0);
3735349cc55cSDimitry Andric     Info.OrigRet = {Register(), FnTy->getReturnType()};
3736349cc55cSDimitry Andric     if (!CLI->lowerCall(MIRBuilder, Info)) {
3737349cc55cSDimitry Andric       LLVM_DEBUG(dbgs() << "Failed to lower call to stack protector check\n");
3738349cc55cSDimitry Andric       return false;
3739349cc55cSDimitry Andric     }
3740349cc55cSDimitry Andric     return true;
3741349cc55cSDimitry Andric #endif
3742349cc55cSDimitry Andric   }
3743349cc55cSDimitry Andric 
3744349cc55cSDimitry Andric   // If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
3745349cc55cSDimitry Andric   // Otherwise, emit a volatile load to retrieve the stack guard value.
37460fca6ea1SDimitry Andric   if (TLI->useLoadStackGuardNode()) {
3747349cc55cSDimitry Andric     Guard =
3748349cc55cSDimitry Andric         MRI->createGenericVirtualRegister(LLT::scalar(PtrTy.getSizeInBits()));
3749349cc55cSDimitry Andric     getStackGuard(Guard, *CurBuilder);
3750349cc55cSDimitry Andric   } else {
3751349cc55cSDimitry Andric     // TODO: test using android subtarget when we support @llvm.thread.pointer.
37520fca6ea1SDimitry Andric     const Value *IRGuard = TLI->getSDagStackGuard(M);
3753349cc55cSDimitry Andric     Register GuardPtr = getOrCreateVReg(*IRGuard);
3754349cc55cSDimitry Andric 
3755349cc55cSDimitry Andric     Guard = CurBuilder
3756349cc55cSDimitry Andric                 ->buildLoad(PtrMemTy, GuardPtr,
3757349cc55cSDimitry Andric                             MachinePointerInfo::getFixedStack(*MF, FI), Align,
3758349cc55cSDimitry Andric                             MachineMemOperand::MOLoad |
3759349cc55cSDimitry Andric                                 MachineMemOperand::MOVolatile)
3760349cc55cSDimitry Andric                 .getReg(0);
3761349cc55cSDimitry Andric   }
3762349cc55cSDimitry Andric 
3763349cc55cSDimitry Andric   // Perform the comparison.
3764349cc55cSDimitry Andric   auto Cmp =
3765349cc55cSDimitry Andric       CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Guard, GuardVal);
3766349cc55cSDimitry Andric   // If the guard/stackslot do not equal, branch to failure MBB.
3767349cc55cSDimitry Andric   CurBuilder->buildBrCond(Cmp, *SPD.getFailureMBB());
3768349cc55cSDimitry Andric   // Otherwise branch to success MBB.
3769349cc55cSDimitry Andric   CurBuilder->buildBr(*SPD.getSuccessMBB());
3770349cc55cSDimitry Andric   return true;
3771349cc55cSDimitry Andric }
3772349cc55cSDimitry Andric 
emitSPDescriptorFailure(StackProtectorDescriptor & SPD,MachineBasicBlock * FailureBB)3773349cc55cSDimitry Andric bool IRTranslator::emitSPDescriptorFailure(StackProtectorDescriptor &SPD,
3774349cc55cSDimitry Andric                                            MachineBasicBlock *FailureBB) {
3775349cc55cSDimitry Andric   CurBuilder->setInsertPt(*FailureBB, FailureBB->end());
3776349cc55cSDimitry Andric 
3777349cc55cSDimitry Andric   const RTLIB::Libcall Libcall = RTLIB::STACKPROTECTOR_CHECK_FAIL;
37780fca6ea1SDimitry Andric   const char *Name = TLI->getLibcallName(Libcall);
3779349cc55cSDimitry Andric 
3780349cc55cSDimitry Andric   CallLowering::CallLoweringInfo Info;
37810fca6ea1SDimitry Andric   Info.CallConv = TLI->getLibcallCallingConv(Libcall);
3782349cc55cSDimitry Andric   Info.Callee = MachineOperand::CreateES(Name);
3783349cc55cSDimitry Andric   Info.OrigRet = {Register(), Type::getVoidTy(MF->getFunction().getContext()),
3784349cc55cSDimitry Andric                   0};
3785349cc55cSDimitry Andric   if (!CLI->lowerCall(*CurBuilder, Info)) {
3786349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Failed to lower call to stack protector fail\n");
3787349cc55cSDimitry Andric     return false;
3788349cc55cSDimitry Andric   }
3789349cc55cSDimitry Andric 
379081ad6265SDimitry Andric   // On PS4/PS5, the "return address" must still be within the calling
379181ad6265SDimitry Andric   // function, even if it's at the very end, so emit an explicit TRAP here.
3792349cc55cSDimitry Andric   // WebAssembly needs an unreachable instruction after a non-returning call,
3793349cc55cSDimitry Andric   // because the function return type can be different from __stack_chk_fail's
3794349cc55cSDimitry Andric   // return type (void).
3795349cc55cSDimitry Andric   const TargetMachine &TM = MF->getTarget();
379681ad6265SDimitry Andric   if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) {
3797349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Unhandled trap emission for stack protector fail\n");
3798349cc55cSDimitry Andric     return false;
3799349cc55cSDimitry Andric   }
3800349cc55cSDimitry Andric   return true;
38010b57cec5SDimitry Andric }
38020b57cec5SDimitry Andric 
finalizeFunction()38030b57cec5SDimitry Andric void IRTranslator::finalizeFunction() {
38040b57cec5SDimitry Andric   // Release the memory used by the different maps we
38050b57cec5SDimitry Andric   // needed during the translation.
38060b57cec5SDimitry Andric   PendingPHIs.clear();
38070b57cec5SDimitry Andric   VMap.reset();
38080b57cec5SDimitry Andric   FrameIndices.clear();
38090b57cec5SDimitry Andric   MachinePreds.clear();
38100b57cec5SDimitry Andric   // MachineIRBuilder::DebugLoc can outlive the DILocation it holds. Clear it
38110b57cec5SDimitry Andric   // to avoid accessing free’d memory (in runOnMachineFunction) and to avoid
38120b57cec5SDimitry Andric   // destroying it twice (in ~IRTranslator() and ~LLVMContext())
38130b57cec5SDimitry Andric   EntryBuilder.reset();
38140b57cec5SDimitry Andric   CurBuilder.reset();
38150b57cec5SDimitry Andric   FuncInfo.clear();
3816349cc55cSDimitry Andric   SPDescriptor.resetPerFunctionState();
38170b57cec5SDimitry Andric }
38180b57cec5SDimitry Andric 
38198bcb0991SDimitry Andric /// Returns true if a BasicBlock \p BB within a variadic function contains a
38208bcb0991SDimitry Andric /// variadic musttail call.
checkForMustTailInVarArgFn(bool IsVarArg,const BasicBlock & BB)38218bcb0991SDimitry Andric static bool checkForMustTailInVarArgFn(bool IsVarArg, const BasicBlock &BB) {
38228bcb0991SDimitry Andric   if (!IsVarArg)
38238bcb0991SDimitry Andric     return false;
38248bcb0991SDimitry Andric 
38258bcb0991SDimitry Andric   // Walk the block backwards, because tail calls usually only appear at the end
38268bcb0991SDimitry Andric   // of a block.
3827349cc55cSDimitry Andric   return llvm::any_of(llvm::reverse(BB), [](const Instruction &I) {
38288bcb0991SDimitry Andric     const auto *CI = dyn_cast<CallInst>(&I);
38298bcb0991SDimitry Andric     return CI && CI->isMustTailCall();
38308bcb0991SDimitry Andric   });
38318bcb0991SDimitry Andric }
38328bcb0991SDimitry Andric 
runOnMachineFunction(MachineFunction & CurMF)38330b57cec5SDimitry Andric bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
38340b57cec5SDimitry Andric   MF = &CurMF;
38350b57cec5SDimitry Andric   const Function &F = MF->getFunction();
38360b57cec5SDimitry Andric   GISelCSEAnalysisWrapper &Wrapper =
38370b57cec5SDimitry Andric       getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
38380b57cec5SDimitry Andric   // Set the CSEConfig and run the analysis.
38390b57cec5SDimitry Andric   GISelCSEInfo *CSEInfo = nullptr;
38400b57cec5SDimitry Andric   TPC = &getAnalysis<TargetPassConfig>();
38410b57cec5SDimitry Andric   bool EnableCSE = EnableCSEInIRTranslator.getNumOccurrences()
38420b57cec5SDimitry Andric                        ? EnableCSEInIRTranslator
38430b57cec5SDimitry Andric                        : TPC->isGISelCSEEnabled();
38440fca6ea1SDimitry Andric   TLI = MF->getSubtarget().getTargetLowering();
38450b57cec5SDimitry Andric 
38460b57cec5SDimitry Andric   if (EnableCSE) {
38478bcb0991SDimitry Andric     EntryBuilder = std::make_unique<CSEMIRBuilder>(CurMF);
38480b57cec5SDimitry Andric     CSEInfo = &Wrapper.get(TPC->getCSEConfig());
38490b57cec5SDimitry Andric     EntryBuilder->setCSEInfo(CSEInfo);
38508bcb0991SDimitry Andric     CurBuilder = std::make_unique<CSEMIRBuilder>(CurMF);
38510b57cec5SDimitry Andric     CurBuilder->setCSEInfo(CSEInfo);
38520b57cec5SDimitry Andric   } else {
38538bcb0991SDimitry Andric     EntryBuilder = std::make_unique<MachineIRBuilder>();
38548bcb0991SDimitry Andric     CurBuilder = std::make_unique<MachineIRBuilder>();
38550b57cec5SDimitry Andric   }
38560b57cec5SDimitry Andric   CLI = MF->getSubtarget().getCallLowering();
38570b57cec5SDimitry Andric   CurBuilder->setMF(*MF);
38580b57cec5SDimitry Andric   EntryBuilder->setMF(*MF);
38590b57cec5SDimitry Andric   MRI = &MF->getRegInfo();
38600fca6ea1SDimitry Andric   DL = &F.getDataLayout();
38618bcb0991SDimitry Andric   ORE = std::make_unique<OptimizationRemarkEmitter>(&F);
38620b57cec5SDimitry Andric   const TargetMachine &TM = MF->getTarget();
3863e8d8bef9SDimitry Andric   TM.resetTargetOptions(F);
38645f757f3fSDimitry Andric   EnableOpts = OptLevel != CodeGenOptLevel::None && !skipFunction(F);
3865e8d8bef9SDimitry Andric   FuncInfo.MF = MF;
3866fcaf7f86SDimitry Andric   if (EnableOpts) {
3867fcaf7f86SDimitry Andric     AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
3868e8d8bef9SDimitry Andric     FuncInfo.BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
3869fcaf7f86SDimitry Andric   } else {
3870fcaf7f86SDimitry Andric     AA = nullptr;
3871e8d8bef9SDimitry Andric     FuncInfo.BPI = nullptr;
3872fcaf7f86SDimitry Andric   }
3873e8d8bef9SDimitry Andric 
3874bdd1243dSDimitry Andric   AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
3875bdd1243dSDimitry Andric       MF->getFunction());
3876bdd1243dSDimitry Andric   LibInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
3877e8d8bef9SDimitry Andric   FuncInfo.CanLowerReturn = CLI->checkReturnTypeForCallConv(*MF);
3878e8d8bef9SDimitry Andric 
38798bcb0991SDimitry Andric   SL = std::make_unique<GISelSwitchLowering>(this, FuncInfo);
38800fca6ea1SDimitry Andric   SL->init(*TLI, TM, *DL);
38810b57cec5SDimitry Andric 
38820b57cec5SDimitry Andric   assert(PendingPHIs.empty() && "stale PHIs");
38830b57cec5SDimitry Andric 
3884fe6060f1SDimitry Andric   // Targets which want to use big endian can enable it using
3885fe6060f1SDimitry Andric   // enableBigEndian()
3886fe6060f1SDimitry Andric   if (!DL->isLittleEndian() && !CLI->enableBigEndian()) {
38870b57cec5SDimitry Andric     // Currently we don't properly handle big endian code.
38880b57cec5SDimitry Andric     OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
38890b57cec5SDimitry Andric                                F.getSubprogram(), &F.getEntryBlock());
38900b57cec5SDimitry Andric     R << "unable to translate in big endian mode";
38910b57cec5SDimitry Andric     reportTranslationError(*MF, *TPC, *ORE, R);
3892*62987288SDimitry Andric     return false;
38930b57cec5SDimitry Andric   }
38940b57cec5SDimitry Andric 
38950b57cec5SDimitry Andric   // Release the per-function state when we return, whether we succeeded or not.
38960b57cec5SDimitry Andric   auto FinalizeOnReturn = make_scope_exit([this]() { finalizeFunction(); });
38970b57cec5SDimitry Andric 
38980b57cec5SDimitry Andric   // Setup a separate basic-block for the arguments and constants
38990b57cec5SDimitry Andric   MachineBasicBlock *EntryBB = MF->CreateMachineBasicBlock();
39000b57cec5SDimitry Andric   MF->push_back(EntryBB);
39010b57cec5SDimitry Andric   EntryBuilder->setMBB(*EntryBB);
39020b57cec5SDimitry Andric 
39030b57cec5SDimitry Andric   DebugLoc DbgLoc = F.getEntryBlock().getFirstNonPHI()->getDebugLoc();
39040b57cec5SDimitry Andric   SwiftError.setFunction(CurMF);
39050b57cec5SDimitry Andric   SwiftError.createEntriesInEntryBlock(DbgLoc);
39060b57cec5SDimitry Andric 
39078bcb0991SDimitry Andric   bool IsVarArg = F.isVarArg();
39088bcb0991SDimitry Andric   bool HasMustTailInVarArgFn = false;
39098bcb0991SDimitry Andric 
39100b57cec5SDimitry Andric   // Create all blocks, in IR order, to preserve the layout.
39110b57cec5SDimitry Andric   for (const BasicBlock &BB: F) {
39120b57cec5SDimitry Andric     auto *&MBB = BBToMBB[&BB];
39130b57cec5SDimitry Andric 
39140b57cec5SDimitry Andric     MBB = MF->CreateMachineBasicBlock(&BB);
39150b57cec5SDimitry Andric     MF->push_back(MBB);
39160b57cec5SDimitry Andric 
39170b57cec5SDimitry Andric     if (BB.hasAddressTaken())
3918bdd1243dSDimitry Andric       MBB->setAddressTakenIRBlock(const_cast<BasicBlock *>(&BB));
39198bcb0991SDimitry Andric 
39208bcb0991SDimitry Andric     if (!HasMustTailInVarArgFn)
39218bcb0991SDimitry Andric       HasMustTailInVarArgFn = checkForMustTailInVarArgFn(IsVarArg, BB);
39220b57cec5SDimitry Andric   }
39230b57cec5SDimitry Andric 
39248bcb0991SDimitry Andric   MF->getFrameInfo().setHasMustTailInVarArgFunc(HasMustTailInVarArgFn);
39258bcb0991SDimitry Andric 
39260b57cec5SDimitry Andric   // Make our arguments/constants entry block fallthrough to the IR entry block.
39270b57cec5SDimitry Andric   EntryBB->addSuccessor(&getMBB(F.front()));
39280b57cec5SDimitry Andric 
3929fe6060f1SDimitry Andric   if (CLI->fallBackToDAGISel(*MF)) {
39305ffd83dbSDimitry Andric     OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
39315ffd83dbSDimitry Andric                                F.getSubprogram(), &F.getEntryBlock());
39325ffd83dbSDimitry Andric     R << "unable to lower function: " << ore::NV("Prototype", F.getType());
39335ffd83dbSDimitry Andric     reportTranslationError(*MF, *TPC, *ORE, R);
39345ffd83dbSDimitry Andric     return false;
39355ffd83dbSDimitry Andric   }
39365ffd83dbSDimitry Andric 
39370b57cec5SDimitry Andric   // Lower the actual args into this basic block.
39380b57cec5SDimitry Andric   SmallVector<ArrayRef<Register>, 8> VRegArgs;
39390b57cec5SDimitry Andric   for (const Argument &Arg: F.args()) {
39405ffd83dbSDimitry Andric     if (DL->getTypeStoreSize(Arg.getType()).isZero())
39410b57cec5SDimitry Andric       continue; // Don't handle zero sized types.
39420b57cec5SDimitry Andric     ArrayRef<Register> VRegs = getOrCreateVRegs(Arg);
39430b57cec5SDimitry Andric     VRegArgs.push_back(VRegs);
39440b57cec5SDimitry Andric 
39450b57cec5SDimitry Andric     if (Arg.hasSwiftErrorAttr()) {
39460b57cec5SDimitry Andric       assert(VRegs.size() == 1 && "Too many vregs for Swift error");
39470b57cec5SDimitry Andric       SwiftError.setCurrentVReg(EntryBB, SwiftError.getFunctionArg(), VRegs[0]);
39480b57cec5SDimitry Andric     }
39490b57cec5SDimitry Andric   }
39500b57cec5SDimitry Andric 
395181ad6265SDimitry Andric   if (!CLI->lowerFormalArguments(*EntryBuilder, F, VRegArgs, FuncInfo)) {
39520b57cec5SDimitry Andric     OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
39530b57cec5SDimitry Andric                                F.getSubprogram(), &F.getEntryBlock());
39540b57cec5SDimitry Andric     R << "unable to lower arguments: " << ore::NV("Prototype", F.getType());
39550b57cec5SDimitry Andric     reportTranslationError(*MF, *TPC, *ORE, R);
39560b57cec5SDimitry Andric     return false;
39570b57cec5SDimitry Andric   }
39580b57cec5SDimitry Andric 
39590b57cec5SDimitry Andric   // Need to visit defs before uses when translating instructions.
39600b57cec5SDimitry Andric   GISelObserverWrapper WrapperObserver;
39610b57cec5SDimitry Andric   if (EnableCSE && CSEInfo)
39620b57cec5SDimitry Andric     WrapperObserver.addObserver(CSEInfo);
39630b57cec5SDimitry Andric   {
39640b57cec5SDimitry Andric     ReversePostOrderTraversal<const Function *> RPOT(&F);
39650b57cec5SDimitry Andric #ifndef NDEBUG
39660b57cec5SDimitry Andric     DILocationVerifier Verifier;
39670b57cec5SDimitry Andric     WrapperObserver.addObserver(&Verifier);
39680b57cec5SDimitry Andric #endif // ifndef NDEBUG
39690b57cec5SDimitry Andric     RAIIDelegateInstaller DelInstall(*MF, &WrapperObserver);
39705ffd83dbSDimitry Andric     RAIIMFObserverInstaller ObsInstall(*MF, WrapperObserver);
39710b57cec5SDimitry Andric     for (const BasicBlock *BB : RPOT) {
39720b57cec5SDimitry Andric       MachineBasicBlock &MBB = getMBB(*BB);
39730b57cec5SDimitry Andric       // Set the insertion point of all the following translations to
39740b57cec5SDimitry Andric       // the end of this basic block.
39750b57cec5SDimitry Andric       CurBuilder->setMBB(MBB);
39768bcb0991SDimitry Andric       HasTailCall = false;
39770b57cec5SDimitry Andric       for (const Instruction &Inst : *BB) {
39788bcb0991SDimitry Andric         // If we translated a tail call in the last step, then we know
39798bcb0991SDimitry Andric         // everything after the call is either a return, or something that is
39808bcb0991SDimitry Andric         // handled by the call itself. (E.g. a lifetime marker or assume
39818bcb0991SDimitry Andric         // intrinsic.) In this case, we should stop translating the block and
39828bcb0991SDimitry Andric         // move on.
39838bcb0991SDimitry Andric         if (HasTailCall)
39848bcb0991SDimitry Andric           break;
39850b57cec5SDimitry Andric #ifndef NDEBUG
39860b57cec5SDimitry Andric         Verifier.setCurrentInst(&Inst);
39870b57cec5SDimitry Andric #endif // ifndef NDEBUG
39887a6dacacSDimitry Andric 
39897a6dacacSDimitry Andric         // Translate any debug-info attached to the instruction.
39900fca6ea1SDimitry Andric         translateDbgInfo(Inst, *CurBuilder);
39917a6dacacSDimitry Andric 
39920b57cec5SDimitry Andric         if (translate(Inst))
39930b57cec5SDimitry Andric           continue;
39940b57cec5SDimitry Andric 
39950b57cec5SDimitry Andric         OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
39960b57cec5SDimitry Andric                                    Inst.getDebugLoc(), BB);
39970b57cec5SDimitry Andric         R << "unable to translate instruction: " << ore::NV("Opcode", &Inst);
39980b57cec5SDimitry Andric 
39990b57cec5SDimitry Andric         if (ORE->allowExtraAnalysis("gisel-irtranslator")) {
40000b57cec5SDimitry Andric           std::string InstStrStorage;
40010b57cec5SDimitry Andric           raw_string_ostream InstStr(InstStrStorage);
40020b57cec5SDimitry Andric           InstStr << Inst;
40030b57cec5SDimitry Andric 
40040fca6ea1SDimitry Andric           R << ": '" << InstStrStorage << "'";
40050b57cec5SDimitry Andric         }
40060b57cec5SDimitry Andric 
40070b57cec5SDimitry Andric         reportTranslationError(*MF, *TPC, *ORE, R);
40080b57cec5SDimitry Andric         return false;
40090b57cec5SDimitry Andric       }
40100b57cec5SDimitry Andric 
40112a66634dSDimitry Andric       if (!finalizeBasicBlock(*BB, MBB)) {
40122a66634dSDimitry Andric         OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
40132a66634dSDimitry Andric                                    BB->getTerminator()->getDebugLoc(), BB);
40142a66634dSDimitry Andric         R << "unable to translate basic block";
40152a66634dSDimitry Andric         reportTranslationError(*MF, *TPC, *ORE, R);
4016349cc55cSDimitry Andric         return false;
40170b57cec5SDimitry Andric       }
40182a66634dSDimitry Andric     }
40190b57cec5SDimitry Andric #ifndef NDEBUG
40200b57cec5SDimitry Andric     WrapperObserver.removeObserver(&Verifier);
40210b57cec5SDimitry Andric #endif
40220b57cec5SDimitry Andric   }
40230b57cec5SDimitry Andric 
40240b57cec5SDimitry Andric   finishPendingPhis();
40250b57cec5SDimitry Andric 
40260b57cec5SDimitry Andric   SwiftError.propagateVRegs();
40270b57cec5SDimitry Andric 
40280b57cec5SDimitry Andric   // Merge the argument lowering and constants block with its single
40290b57cec5SDimitry Andric   // successor, the LLVM-IR entry block.  We want the basic block to
40300b57cec5SDimitry Andric   // be maximal.
40310b57cec5SDimitry Andric   assert(EntryBB->succ_size() == 1 &&
40320b57cec5SDimitry Andric          "Custom BB used for lowering should have only one successor");
40330b57cec5SDimitry Andric   // Get the successor of the current entry block.
40340b57cec5SDimitry Andric   MachineBasicBlock &NewEntryBB = **EntryBB->succ_begin();
40350b57cec5SDimitry Andric   assert(NewEntryBB.pred_size() == 1 &&
40360b57cec5SDimitry Andric          "LLVM-IR entry block has a predecessor!?");
40370b57cec5SDimitry Andric   // Move all the instruction from the current entry block to the
40380b57cec5SDimitry Andric   // new entry block.
40390b57cec5SDimitry Andric   NewEntryBB.splice(NewEntryBB.begin(), EntryBB, EntryBB->begin(),
40400b57cec5SDimitry Andric                     EntryBB->end());
40410b57cec5SDimitry Andric 
40420b57cec5SDimitry Andric   // Update the live-in information for the new entry block.
40430b57cec5SDimitry Andric   for (const MachineBasicBlock::RegisterMaskPair &LiveIn : EntryBB->liveins())
40440b57cec5SDimitry Andric     NewEntryBB.addLiveIn(LiveIn);
40450b57cec5SDimitry Andric   NewEntryBB.sortUniqueLiveIns();
40460b57cec5SDimitry Andric 
40470b57cec5SDimitry Andric   // Get rid of the now empty basic block.
40480b57cec5SDimitry Andric   EntryBB->removeSuccessor(&NewEntryBB);
40490b57cec5SDimitry Andric   MF->remove(EntryBB);
40500eae32dcSDimitry Andric   MF->deleteMachineBasicBlock(EntryBB);
40510b57cec5SDimitry Andric 
40520b57cec5SDimitry Andric   assert(&MF->front() == &NewEntryBB &&
40530b57cec5SDimitry Andric          "New entry wasn't next in the list of basic block!");
40540b57cec5SDimitry Andric 
40550b57cec5SDimitry Andric   // Initialize stack protector information.
40560b57cec5SDimitry Andric   StackProtector &SP = getAnalysis<StackProtector>();
40570b57cec5SDimitry Andric   SP.copyToMachineFrameInfo(MF->getFrameInfo());
40580b57cec5SDimitry Andric 
40590b57cec5SDimitry Andric   return false;
40600b57cec5SDimitry Andric }
4061