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