1 //===- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file declares the IRTranslator pass. 10 /// This pass is responsible for translating LLVM IR into MachineInstr. 11 /// It uses target hooks to lower the ABI but aside from that, the pass 12 /// generated code is generic. This is the default translator used for 13 /// GlobalISel. 14 /// 15 /// \todo Replace the comments with actual doxygen comments. 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H 19 #define LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H 20 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" 24 #include "llvm/CodeGen/GlobalISel/Types.h" 25 #include "llvm/CodeGen/SwiftErrorValueTracking.h" 26 #include "llvm/CodeGen/MachineFunctionPass.h" 27 #include "llvm/CodeGen/SwitchLoweringUtils.h" 28 #include "llvm/IR/Intrinsics.h" 29 #include "llvm/Support/Allocator.h" 30 #include <memory> 31 #include <utility> 32 33 namespace llvm { 34 35 class AllocaInst; 36 class BasicBlock; 37 class CallInst; 38 class CallLowering; 39 class Constant; 40 class DataLayout; 41 class FunctionLoweringInfo; 42 class Instruction; 43 class MachineBasicBlock; 44 class MachineFunction; 45 class MachineInstr; 46 class MachineRegisterInfo; 47 class OptimizationRemarkEmitter; 48 class PHINode; 49 class TargetPassConfig; 50 class User; 51 class Value; 52 53 // Technically the pass should run on an hypothetical MachineModule, 54 // since it should translate Global into some sort of MachineGlobal. 55 // The MachineGlobal should ultimately just be a transfer of ownership of 56 // the interesting bits that are relevant to represent a global value. 57 // That being said, we could investigate what would it cost to just duplicate 58 // the information from the LLVM IR. 59 // The idea is that ultimately we would be able to free up the memory used 60 // by the LLVM IR as soon as the translation is over. 61 class IRTranslator : public MachineFunctionPass { 62 public: 63 static char ID; 64 65 private: 66 /// Interface used to lower the everything related to calls. 67 const CallLowering *CLI; 68 69 /// This class contains the mapping between the Values to vreg related data. 70 class ValueToVRegInfo { 71 public: 72 ValueToVRegInfo() = default; 73 74 using VRegListT = SmallVector<Register, 1>; 75 using OffsetListT = SmallVector<uint64_t, 1>; 76 77 using const_vreg_iterator = 78 DenseMap<const Value *, VRegListT *>::const_iterator; 79 using const_offset_iterator = 80 DenseMap<const Value *, OffsetListT *>::const_iterator; 81 vregs_end()82 inline const_vreg_iterator vregs_end() const { return ValToVRegs.end(); } 83 getVRegs(const Value & V)84 VRegListT *getVRegs(const Value &V) { 85 auto It = ValToVRegs.find(&V); 86 if (It != ValToVRegs.end()) 87 return It->second; 88 89 return insertVRegs(V); 90 } 91 getOffsets(const Value & V)92 OffsetListT *getOffsets(const Value &V) { 93 auto It = TypeToOffsets.find(V.getType()); 94 if (It != TypeToOffsets.end()) 95 return It->second; 96 97 return insertOffsets(V); 98 } 99 findVRegs(const Value & V)100 const_vreg_iterator findVRegs(const Value &V) const { 101 return ValToVRegs.find(&V); 102 } 103 contains(const Value & V)104 bool contains(const Value &V) const { 105 return ValToVRegs.find(&V) != ValToVRegs.end(); 106 } 107 reset()108 void reset() { 109 ValToVRegs.clear(); 110 TypeToOffsets.clear(); 111 VRegAlloc.DestroyAll(); 112 OffsetAlloc.DestroyAll(); 113 } 114 115 private: insertVRegs(const Value & V)116 VRegListT *insertVRegs(const Value &V) { 117 assert(ValToVRegs.find(&V) == ValToVRegs.end() && "Value already exists"); 118 119 // We placement new using our fast allocator since we never try to free 120 // the vectors until translation is finished. 121 auto *VRegList = new (VRegAlloc.Allocate()) VRegListT(); 122 ValToVRegs[&V] = VRegList; 123 return VRegList; 124 } 125 insertOffsets(const Value & V)126 OffsetListT *insertOffsets(const Value &V) { 127 assert(TypeToOffsets.find(V.getType()) == TypeToOffsets.end() && 128 "Type already exists"); 129 130 auto *OffsetList = new (OffsetAlloc.Allocate()) OffsetListT(); 131 TypeToOffsets[V.getType()] = OffsetList; 132 return OffsetList; 133 } 134 SpecificBumpPtrAllocator<VRegListT> VRegAlloc; 135 SpecificBumpPtrAllocator<OffsetListT> OffsetAlloc; 136 137 // We store pointers to vectors here since references may be invalidated 138 // while we hold them if we stored the vectors directly. 139 DenseMap<const Value *, VRegListT*> ValToVRegs; 140 DenseMap<const Type *, OffsetListT*> TypeToOffsets; 141 }; 142 143 /// Mapping of the values of the current LLVM IR function to the related 144 /// virtual registers and offsets. 145 ValueToVRegInfo VMap; 146 147 // N.b. it's not completely obvious that this will be sufficient for every 148 // LLVM IR construct (with "invoke" being the obvious candidate to mess up our 149 // lives. 150 DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB; 151 152 // One BasicBlock can be translated to multiple MachineBasicBlocks. For such 153 // BasicBlocks translated to multiple MachineBasicBlocks, MachinePreds retains 154 // a mapping between the edges arriving at the BasicBlock to the corresponding 155 // created MachineBasicBlocks. Some BasicBlocks that get translated to a 156 // single MachineBasicBlock may also end up in this Map. 157 using CFGEdge = std::pair<const BasicBlock *, const BasicBlock *>; 158 DenseMap<CFGEdge, SmallVector<MachineBasicBlock *, 1>> MachinePreds; 159 160 // List of stubbed PHI instructions, for values and basic blocks to be filled 161 // in once all MachineBasicBlocks have been created. 162 SmallVector<std::pair<const PHINode *, SmallVector<MachineInstr *, 1>>, 4> 163 PendingPHIs; 164 165 /// Record of what frame index has been allocated to specified allocas for 166 /// this function. 167 DenseMap<const AllocaInst *, int> FrameIndices; 168 169 SwiftErrorValueTracking SwiftError; 170 171 /// \name Methods for translating form LLVM IR to MachineInstr. 172 /// \see ::translate for general information on the translate methods. 173 /// @{ 174 175 /// Translate \p Inst into its corresponding MachineInstr instruction(s). 176 /// Insert the newly translated instruction(s) right where the CurBuilder 177 /// is set. 178 /// 179 /// The general algorithm is: 180 /// 1. Look for a virtual register for each operand or 181 /// create one. 182 /// 2 Update the VMap accordingly. 183 /// 2.alt. For constant arguments, if they are compile time constants, 184 /// produce an immediate in the right operand and do not touch 185 /// ValToReg. Actually we will go with a virtual register for each 186 /// constants because it may be expensive to actually materialize the 187 /// constant. Moreover, if the constant spans on several instructions, 188 /// CSE may not catch them. 189 /// => Update ValToVReg and remember that we saw a constant in Constants. 190 /// We will materialize all the constants in finalize. 191 /// Note: we would need to do something so that we can recognize such operand 192 /// as constants. 193 /// 3. Create the generic instruction. 194 /// 195 /// \return true if the translation succeeded. 196 bool translate(const Instruction &Inst); 197 198 /// Materialize \p C into virtual-register \p Reg. The generic instructions 199 /// performing this materialization will be inserted into the entry block of 200 /// the function. 201 /// 202 /// \return true if the materialization succeeded. 203 bool translate(const Constant &C, Register Reg); 204 205 /// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is 206 /// emitted. 207 bool translateBitCast(const User &U, MachineIRBuilder &MIRBuilder); 208 209 /// Translate an LLVM load instruction into generic IR. 210 bool translateLoad(const User &U, MachineIRBuilder &MIRBuilder); 211 212 /// Translate an LLVM store instruction into generic IR. 213 bool translateStore(const User &U, MachineIRBuilder &MIRBuilder); 214 215 /// Translate an LLVM string intrinsic (memcpy, memset, ...). 216 bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, 217 Intrinsic::ID ID); 218 219 void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder); 220 221 bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op, 222 MachineIRBuilder &MIRBuilder); 223 224 /// Helper function for translateSimpleIntrinsic. 225 /// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a 226 /// simple intrinsic (ceil, fabs, etc.). Otherwise, returns 227 /// Intrinsic::not_intrinsic. 228 unsigned getSimpleIntrinsicOpcode(Intrinsic::ID ID); 229 230 /// Translates the intrinsics defined in getSimpleIntrinsicOpcode. 231 /// \return true if the translation succeeded. 232 bool translateSimpleIntrinsic(const CallInst &CI, Intrinsic::ID ID, 233 MachineIRBuilder &MIRBuilder); 234 235 bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, 236 MachineIRBuilder &MIRBuilder); 237 238 bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder); 239 240 /// Returns true if the value should be split into multiple LLTs. 241 /// If \p Offsets is given then the split type's offsets will be stored in it. 242 /// If \p Offsets is not empty it will be cleared first. 243 bool valueIsSplit(const Value &V, 244 SmallVectorImpl<uint64_t> *Offsets = nullptr); 245 246 /// Common code for translating normal calls or invokes. 247 bool translateCallSite(const ImmutableCallSite &CS, 248 MachineIRBuilder &MIRBuilder); 249 250 /// Translate call instruction. 251 /// \pre \p U is a call instruction. 252 bool translateCall(const User &U, MachineIRBuilder &MIRBuilder); 253 254 bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder); 255 256 bool translateCallBr(const User &U, MachineIRBuilder &MIRBuilder); 257 258 bool translateLandingPad(const User &U, MachineIRBuilder &MIRBuilder); 259 260 /// Translate one of LLVM's cast instructions into MachineInstrs, with the 261 /// given generic Opcode. 262 bool translateCast(unsigned Opcode, const User &U, 263 MachineIRBuilder &MIRBuilder); 264 265 /// Translate a phi instruction. 266 bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder); 267 268 /// Translate a comparison (icmp or fcmp) instruction or constant. 269 bool translateCompare(const User &U, MachineIRBuilder &MIRBuilder); 270 271 /// Translate an integer compare instruction (or constant). translateICmp(const User & U,MachineIRBuilder & MIRBuilder)272 bool translateICmp(const User &U, MachineIRBuilder &MIRBuilder) { 273 return translateCompare(U, MIRBuilder); 274 } 275 276 /// Translate a floating-point compare instruction (or constant). translateFCmp(const User & U,MachineIRBuilder & MIRBuilder)277 bool translateFCmp(const User &U, MachineIRBuilder &MIRBuilder) { 278 return translateCompare(U, MIRBuilder); 279 } 280 281 /// Add remaining operands onto phis we've translated. Executed after all 282 /// MachineBasicBlocks for the function have been created. 283 void finishPendingPhis(); 284 285 /// Translate \p Inst into a binary operation \p Opcode. 286 /// \pre \p U is a binary operation. 287 bool translateBinaryOp(unsigned Opcode, const User &U, 288 MachineIRBuilder &MIRBuilder); 289 290 /// Translate branch (br) instruction. 291 /// \pre \p U is a branch instruction. 292 bool translateBr(const User &U, MachineIRBuilder &MIRBuilder); 293 294 // Begin switch lowering functions. 295 bool emitJumpTableHeader(SwitchCG::JumpTable &JT, 296 SwitchCG::JumpTableHeader &JTH, 297 MachineBasicBlock *HeaderBB); 298 void emitJumpTable(SwitchCG::JumpTable &JT, MachineBasicBlock *MBB); 299 300 void emitSwitchCase(SwitchCG::CaseBlock &CB, MachineBasicBlock *SwitchBB, 301 MachineIRBuilder &MIB); 302 303 bool lowerJumpTableWorkItem(SwitchCG::SwitchWorkListItem W, 304 MachineBasicBlock *SwitchMBB, 305 MachineBasicBlock *CurMBB, 306 MachineBasicBlock *DefaultMBB, 307 MachineIRBuilder &MIB, 308 MachineFunction::iterator BBI, 309 BranchProbability UnhandledProbs, 310 SwitchCG::CaseClusterIt I, 311 MachineBasicBlock *Fallthrough, 312 bool FallthroughUnreachable); 313 314 bool lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I, 315 Value *Cond, 316 MachineBasicBlock *Fallthrough, 317 bool FallthroughUnreachable, 318 BranchProbability UnhandledProbs, 319 MachineBasicBlock *CurMBB, 320 MachineIRBuilder &MIB, 321 MachineBasicBlock *SwitchMBB); 322 323 bool lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W, Value *Cond, 324 MachineBasicBlock *SwitchMBB, 325 MachineBasicBlock *DefaultMBB, 326 MachineIRBuilder &MIB); 327 328 bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); 329 // End switch lowering section. 330 331 bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder); 332 333 bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder); 334 335 bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder); 336 337 bool translateSelect(const User &U, MachineIRBuilder &MIRBuilder); 338 339 bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder); 340 341 bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder); 342 343 /// Translate return (ret) instruction. 344 /// The target needs to implement CallLowering::lowerReturn for 345 /// this to succeed. 346 /// \pre \p U is a return instruction. 347 bool translateRet(const User &U, MachineIRBuilder &MIRBuilder); 348 349 bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder); 350 351 bool translateFNeg(const User &U, MachineIRBuilder &MIRBuilder); 352 translateAdd(const User & U,MachineIRBuilder & MIRBuilder)353 bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) { 354 return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder); 355 } translateSub(const User & U,MachineIRBuilder & MIRBuilder)356 bool translateSub(const User &U, MachineIRBuilder &MIRBuilder) { 357 return translateBinaryOp(TargetOpcode::G_SUB, U, MIRBuilder); 358 } translateAnd(const User & U,MachineIRBuilder & MIRBuilder)359 bool translateAnd(const User &U, MachineIRBuilder &MIRBuilder) { 360 return translateBinaryOp(TargetOpcode::G_AND, U, MIRBuilder); 361 } translateMul(const User & U,MachineIRBuilder & MIRBuilder)362 bool translateMul(const User &U, MachineIRBuilder &MIRBuilder) { 363 return translateBinaryOp(TargetOpcode::G_MUL, U, MIRBuilder); 364 } translateOr(const User & U,MachineIRBuilder & MIRBuilder)365 bool translateOr(const User &U, MachineIRBuilder &MIRBuilder) { 366 return translateBinaryOp(TargetOpcode::G_OR, U, MIRBuilder); 367 } translateXor(const User & U,MachineIRBuilder & MIRBuilder)368 bool translateXor(const User &U, MachineIRBuilder &MIRBuilder) { 369 return translateBinaryOp(TargetOpcode::G_XOR, U, MIRBuilder); 370 } 371 translateUDiv(const User & U,MachineIRBuilder & MIRBuilder)372 bool translateUDiv(const User &U, MachineIRBuilder &MIRBuilder) { 373 return translateBinaryOp(TargetOpcode::G_UDIV, U, MIRBuilder); 374 } translateSDiv(const User & U,MachineIRBuilder & MIRBuilder)375 bool translateSDiv(const User &U, MachineIRBuilder &MIRBuilder) { 376 return translateBinaryOp(TargetOpcode::G_SDIV, U, MIRBuilder); 377 } translateURem(const User & U,MachineIRBuilder & MIRBuilder)378 bool translateURem(const User &U, MachineIRBuilder &MIRBuilder) { 379 return translateBinaryOp(TargetOpcode::G_UREM, U, MIRBuilder); 380 } translateSRem(const User & U,MachineIRBuilder & MIRBuilder)381 bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) { 382 return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder); 383 } translateIntToPtr(const User & U,MachineIRBuilder & MIRBuilder)384 bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) { 385 return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder); 386 } translatePtrToInt(const User & U,MachineIRBuilder & MIRBuilder)387 bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) { 388 return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder); 389 } translateTrunc(const User & U,MachineIRBuilder & MIRBuilder)390 bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) { 391 return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder); 392 } translateFPTrunc(const User & U,MachineIRBuilder & MIRBuilder)393 bool translateFPTrunc(const User &U, MachineIRBuilder &MIRBuilder) { 394 return translateCast(TargetOpcode::G_FPTRUNC, U, MIRBuilder); 395 } translateFPExt(const User & U,MachineIRBuilder & MIRBuilder)396 bool translateFPExt(const User &U, MachineIRBuilder &MIRBuilder) { 397 return translateCast(TargetOpcode::G_FPEXT, U, MIRBuilder); 398 } translateFPToUI(const User & U,MachineIRBuilder & MIRBuilder)399 bool translateFPToUI(const User &U, MachineIRBuilder &MIRBuilder) { 400 return translateCast(TargetOpcode::G_FPTOUI, U, MIRBuilder); 401 } translateFPToSI(const User & U,MachineIRBuilder & MIRBuilder)402 bool translateFPToSI(const User &U, MachineIRBuilder &MIRBuilder) { 403 return translateCast(TargetOpcode::G_FPTOSI, U, MIRBuilder); 404 } translateUIToFP(const User & U,MachineIRBuilder & MIRBuilder)405 bool translateUIToFP(const User &U, MachineIRBuilder &MIRBuilder) { 406 return translateCast(TargetOpcode::G_UITOFP, U, MIRBuilder); 407 } translateSIToFP(const User & U,MachineIRBuilder & MIRBuilder)408 bool translateSIToFP(const User &U, MachineIRBuilder &MIRBuilder) { 409 return translateCast(TargetOpcode::G_SITOFP, U, MIRBuilder); 410 } translateUnreachable(const User & U,MachineIRBuilder & MIRBuilder)411 bool translateUnreachable(const User &U, MachineIRBuilder &MIRBuilder) { 412 return true; 413 } translateSExt(const User & U,MachineIRBuilder & MIRBuilder)414 bool translateSExt(const User &U, MachineIRBuilder &MIRBuilder) { 415 return translateCast(TargetOpcode::G_SEXT, U, MIRBuilder); 416 } 417 translateZExt(const User & U,MachineIRBuilder & MIRBuilder)418 bool translateZExt(const User &U, MachineIRBuilder &MIRBuilder) { 419 return translateCast(TargetOpcode::G_ZEXT, U, MIRBuilder); 420 } 421 translateShl(const User & U,MachineIRBuilder & MIRBuilder)422 bool translateShl(const User &U, MachineIRBuilder &MIRBuilder) { 423 return translateBinaryOp(TargetOpcode::G_SHL, U, MIRBuilder); 424 } translateLShr(const User & U,MachineIRBuilder & MIRBuilder)425 bool translateLShr(const User &U, MachineIRBuilder &MIRBuilder) { 426 return translateBinaryOp(TargetOpcode::G_LSHR, U, MIRBuilder); 427 } translateAShr(const User & U,MachineIRBuilder & MIRBuilder)428 bool translateAShr(const User &U, MachineIRBuilder &MIRBuilder) { 429 return translateBinaryOp(TargetOpcode::G_ASHR, U, MIRBuilder); 430 } 431 translateFAdd(const User & U,MachineIRBuilder & MIRBuilder)432 bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) { 433 return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder); 434 } translateFMul(const User & U,MachineIRBuilder & MIRBuilder)435 bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) { 436 return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder); 437 } translateFDiv(const User & U,MachineIRBuilder & MIRBuilder)438 bool translateFDiv(const User &U, MachineIRBuilder &MIRBuilder) { 439 return translateBinaryOp(TargetOpcode::G_FDIV, U, MIRBuilder); 440 } translateFRem(const User & U,MachineIRBuilder & MIRBuilder)441 bool translateFRem(const User &U, MachineIRBuilder &MIRBuilder) { 442 return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder); 443 } 444 445 bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder); 446 447 bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder); 448 449 bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder); 450 451 bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder); 452 453 bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder); 454 bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder); 455 bool translateFence(const User &U, MachineIRBuilder &MIRBuilder); 456 457 // Stubs to keep the compiler happy while we implement the rest of the 458 // translation. translateResume(const User & U,MachineIRBuilder & MIRBuilder)459 bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { 460 return false; 461 } translateCleanupRet(const User & U,MachineIRBuilder & MIRBuilder)462 bool translateCleanupRet(const User &U, MachineIRBuilder &MIRBuilder) { 463 return false; 464 } translateCatchRet(const User & U,MachineIRBuilder & MIRBuilder)465 bool translateCatchRet(const User &U, MachineIRBuilder &MIRBuilder) { 466 return false; 467 } translateCatchSwitch(const User & U,MachineIRBuilder & MIRBuilder)468 bool translateCatchSwitch(const User &U, MachineIRBuilder &MIRBuilder) { 469 return false; 470 } translateAddrSpaceCast(const User & U,MachineIRBuilder & MIRBuilder)471 bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) { 472 return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder); 473 } translateCleanupPad(const User & U,MachineIRBuilder & MIRBuilder)474 bool translateCleanupPad(const User &U, MachineIRBuilder &MIRBuilder) { 475 return false; 476 } translateCatchPad(const User & U,MachineIRBuilder & MIRBuilder)477 bool translateCatchPad(const User &U, MachineIRBuilder &MIRBuilder) { 478 return false; 479 } translateUserOp1(const User & U,MachineIRBuilder & MIRBuilder)480 bool translateUserOp1(const User &U, MachineIRBuilder &MIRBuilder) { 481 return false; 482 } translateUserOp2(const User & U,MachineIRBuilder & MIRBuilder)483 bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) { 484 return false; 485 } translateFreeze(const User & U,MachineIRBuilder & MIRBuilder)486 bool translateFreeze(const User &U, MachineIRBuilder &MIRBuilder) { 487 return false; 488 } 489 490 /// @} 491 492 // Builder for machine instruction a la IRBuilder. 493 // I.e., compared to regular MIBuilder, this one also inserts the instruction 494 // in the current block, it can creates block, etc., basically a kind of 495 // IRBuilder, but for Machine IR. 496 // CSEMIRBuilder CurBuilder; 497 std::unique_ptr<MachineIRBuilder> CurBuilder; 498 499 // Builder set to the entry block (just after ABI lowering instructions). Used 500 // as a convenient location for Constants. 501 // CSEMIRBuilder EntryBuilder; 502 std::unique_ptr<MachineIRBuilder> EntryBuilder; 503 504 // The MachineFunction currently being translated. 505 MachineFunction *MF; 506 507 /// MachineRegisterInfo used to create virtual registers. 508 MachineRegisterInfo *MRI = nullptr; 509 510 const DataLayout *DL; 511 512 /// Current target configuration. Controls how the pass handles errors. 513 const TargetPassConfig *TPC; 514 515 /// Current optimization remark emitter. Used to report failures. 516 std::unique_ptr<OptimizationRemarkEmitter> ORE; 517 518 FunctionLoweringInfo FuncInfo; 519 520 // True when either the Target Machine specifies no optimizations or the 521 // function has the optnone attribute. 522 bool EnableOpts = false; 523 524 /// True when the block contains a tail call. This allows the IRTranslator to 525 /// stop translating such blocks early. 526 bool HasTailCall = false; 527 528 /// Switch analysis and optimization. 529 class GISelSwitchLowering : public SwitchCG::SwitchLowering { 530 public: GISelSwitchLowering(IRTranslator * irt,FunctionLoweringInfo & funcinfo)531 GISelSwitchLowering(IRTranslator *irt, FunctionLoweringInfo &funcinfo) 532 : SwitchLowering(funcinfo), IRT(irt) { 533 assert(irt && "irt is null!"); 534 } 535 536 virtual void addSuccessorWithProb( 537 MachineBasicBlock *Src, MachineBasicBlock *Dst, 538 BranchProbability Prob = BranchProbability::getUnknown()) override { 539 IRT->addSuccessorWithProb(Src, Dst, Prob); 540 } 541 542 virtual ~GISelSwitchLowering() = default; 543 544 private: 545 IRTranslator *IRT; 546 }; 547 548 std::unique_ptr<GISelSwitchLowering> SL; 549 550 // * Insert all the code needed to materialize the constants 551 // at the proper place. E.g., Entry block or dominator block 552 // of each constant depending on how fancy we want to be. 553 // * Clear the different maps. 554 void finalizeFunction(); 555 556 // Handle emitting jump tables for each basic block. 557 void finalizeBasicBlock(); 558 559 /// Get the VRegs that represent \p Val. 560 /// Non-aggregate types have just one corresponding VReg and the list can be 561 /// used as a single "unsigned". Aggregates get flattened. If such VRegs do 562 /// not exist, they are created. 563 ArrayRef<Register> getOrCreateVRegs(const Value &Val); 564 getOrCreateVReg(const Value & Val)565 Register getOrCreateVReg(const Value &Val) { 566 auto Regs = getOrCreateVRegs(Val); 567 if (Regs.empty()) 568 return 0; 569 assert(Regs.size() == 1 && 570 "attempt to get single VReg for aggregate or void"); 571 return Regs[0]; 572 } 573 574 /// Allocate some vregs and offsets in the VMap. Then populate just the 575 /// offsets while leaving the vregs empty. 576 ValueToVRegInfo::VRegListT &allocateVRegs(const Value &Val); 577 578 /// Get the frame index that represents \p Val. 579 /// If such VReg does not exist, it is created. 580 int getOrCreateFrameIndex(const AllocaInst &AI); 581 582 /// Get the alignment of the given memory operation instruction. This will 583 /// either be the explicitly specified value or the ABI-required alignment for 584 /// the type being accessed (according to the Module's DataLayout). 585 unsigned getMemOpAlignment(const Instruction &I); 586 587 /// Get the MachineBasicBlock that represents \p BB. Specifically, the block 588 /// returned will be the head of the translated block (suitable for branch 589 /// destinations). 590 MachineBasicBlock &getMBB(const BasicBlock &BB); 591 592 /// Record \p NewPred as a Machine predecessor to `Edge.second`, corresponding 593 /// to `Edge.first` at the IR level. This is used when IRTranslation creates 594 /// multiple MachineBasicBlocks for a given IR block and the CFG is no longer 595 /// represented simply by the IR-level CFG. 596 void addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred); 597 598 /// Returns the Machine IR predecessors for the given IR CFG edge. Usually 599 /// this is just the single MachineBasicBlock corresponding to the predecessor 600 /// in the IR. More complex lowering can result in multiple MachineBasicBlocks 601 /// preceding the original though (e.g. switch instructions). getMachinePredBBs(CFGEdge Edge)602 SmallVector<MachineBasicBlock *, 1> getMachinePredBBs(CFGEdge Edge) { 603 auto RemappedEdge = MachinePreds.find(Edge); 604 if (RemappedEdge != MachinePreds.end()) 605 return RemappedEdge->second; 606 return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first)); 607 } 608 609 /// Return branch probability calculated by BranchProbabilityInfo for IR 610 /// blocks. 611 BranchProbability getEdgeProbability(const MachineBasicBlock *Src, 612 const MachineBasicBlock *Dst) const; 613 614 void addSuccessorWithProb(MachineBasicBlock *Src, MachineBasicBlock *Dst, 615 BranchProbability Prob); 616 617 public: 618 // Ctor, nothing fancy. 619 IRTranslator(); 620 getPassName()621 StringRef getPassName() const override { return "IRTranslator"; } 622 623 void getAnalysisUsage(AnalysisUsage &AU) const override; 624 625 // Algo: 626 // CallLowering = MF.subtarget.getCallLowering() 627 // F = MF.getParent() 628 // MIRBuilder.reset(MF) 629 // getMBB(F.getEntryBB()) 630 // CallLowering->translateArguments(MIRBuilder, F, ValToVReg) 631 // for each bb in F 632 // getMBB(bb) 633 // for each inst in bb 634 // if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence)) 635 // report_fatal_error("Don't know how to translate input"); 636 // finalize() 637 bool runOnMachineFunction(MachineFunction &MF) override; 638 }; 639 640 } // end namespace llvm 641 642 #endif // LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H 643