1 //===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.cpp - MIBuilder--*- C++ -*-==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// This file implements the MachineIRBuidler class. 11 //===----------------------------------------------------------------------===// 12 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 13 14 #include "llvm/CodeGen/MachineFunction.h" 15 #include "llvm/CodeGen/MachineInstr.h" 16 #include "llvm/CodeGen/MachineInstrBuilder.h" 17 #include "llvm/CodeGen/MachineRegisterInfo.h" 18 #include "llvm/Target/TargetInstrInfo.h" 19 #include "llvm/Target/TargetOpcodes.h" 20 #include "llvm/Target/TargetSubtargetInfo.h" 21 22 using namespace llvm; 23 24 void MachineIRBuilder::setMF(MachineFunction &MF) { 25 this->MF = &MF; 26 this->MBB = nullptr; 27 this->MRI = &MF.getRegInfo(); 28 this->TII = MF.getSubtarget().getInstrInfo(); 29 this->DL = DebugLoc(); 30 this->MI = nullptr; 31 this->InsertedInstr = nullptr; 32 } 33 34 void MachineIRBuilder::setMBB(MachineBasicBlock &MBB, bool Beginning) { 35 this->MBB = &MBB; 36 this->MI = nullptr; 37 Before = Beginning; 38 assert(&getMF() == MBB.getParent() && 39 "Basic block is in a different function"); 40 } 41 42 void MachineIRBuilder::setInstr(MachineInstr &MI, bool Before) { 43 assert(MI.getParent() && "Instruction is not part of a basic block"); 44 setMBB(*MI.getParent()); 45 this->MI = &MI; 46 this->Before = Before; 47 } 48 49 MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() { 50 if (MI) { 51 if (Before) 52 return MI; 53 if (!MI->getNextNode()) 54 return getMBB().end(); 55 return MI->getNextNode(); 56 } 57 return Before ? getMBB().begin() : getMBB().end(); 58 } 59 60 void MachineIRBuilder::recordInsertions( 61 std::function<void(MachineInstr *)> Inserted) { 62 InsertedInstr = Inserted; 63 } 64 65 void MachineIRBuilder::stopRecordingInsertions() { 66 InsertedInstr = nullptr; 67 } 68 69 //------------------------------------------------------------------------------ 70 // Build instruction variants. 71 //------------------------------------------------------------------------------ 72 73 MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode) { 74 MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode)); 75 getMBB().insert(getInsertPt(), MIB); 76 if (InsertedInstr) 77 InsertedInstr(MIB); 78 return MIB; 79 } 80 81 MachineInstrBuilder MachineIRBuilder::buildFrameIndex(unsigned Res, int Idx) { 82 assert(MRI->getType(Res).isPointer() && "invalid operand type"); 83 return buildInstr(TargetOpcode::G_FRAME_INDEX) 84 .addDef(Res) 85 .addFrameIndex(Idx); 86 } 87 88 MachineInstrBuilder MachineIRBuilder::buildGlobalValue(unsigned Res, 89 const GlobalValue *GV) { 90 assert(MRI->getType(Res).isPointer() && "invalid operand type"); 91 assert(MRI->getType(Res).getAddressSpace() == 92 GV->getType()->getAddressSpace() && 93 "address space mismatch"); 94 95 return buildInstr(TargetOpcode::G_GLOBAL_VALUE) 96 .addDef(Res) 97 .addGlobalAddress(GV); 98 } 99 100 MachineInstrBuilder MachineIRBuilder::buildAdd(unsigned Res, unsigned Op0, 101 unsigned Op1) { 102 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 103 "invalid operand type"); 104 assert(MRI->getType(Res) == MRI->getType(Op0) && 105 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 106 107 return buildInstr(TargetOpcode::G_ADD) 108 .addDef(Res) 109 .addUse(Op0) 110 .addUse(Op1); 111 } 112 113 MachineInstrBuilder MachineIRBuilder::buildGEP(unsigned Res, unsigned Op0, 114 unsigned Op1) { 115 assert(MRI->getType(Res).isPointer() && 116 MRI->getType(Res) == MRI->getType(Op0) && "type mismatch"); 117 assert(MRI->getType(Op1).isScalar() && "invalid offset type"); 118 119 return buildInstr(TargetOpcode::G_GEP) 120 .addDef(Res) 121 .addUse(Op0) 122 .addUse(Op1); 123 } 124 125 MachineInstrBuilder MachineIRBuilder::buildSub(unsigned Res, unsigned Op0, 126 unsigned Op1) { 127 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 128 "invalid operand type"); 129 assert(MRI->getType(Res) == MRI->getType(Op0) && 130 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 131 132 return buildInstr(TargetOpcode::G_SUB) 133 .addDef(Res) 134 .addUse(Op0) 135 .addUse(Op1); 136 } 137 138 MachineInstrBuilder MachineIRBuilder::buildMul(unsigned Res, unsigned Op0, 139 unsigned Op1) { 140 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 141 "invalid operand type"); 142 assert(MRI->getType(Res) == MRI->getType(Op0) && 143 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 144 145 return buildInstr(TargetOpcode::G_MUL) 146 .addDef(Res) 147 .addUse(Op0) 148 .addUse(Op1); 149 } 150 151 MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) { 152 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest); 153 } 154 155 MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) { 156 return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op); 157 } 158 159 MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res, int64_t Val) { 160 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 161 162 return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addImm(Val); 163 } 164 165 MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res, 166 const ConstantFP &Val) { 167 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 168 169 return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val); 170 } 171 172 MachineInstrBuilder MachineIRBuilder::buildBrCond(unsigned Tst, 173 MachineBasicBlock &Dest) { 174 assert(MRI->getType(Tst).isScalar() && "invalid operand type"); 175 176 return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest); 177 } 178 179 MachineInstrBuilder MachineIRBuilder::buildLoad(unsigned Res, unsigned Addr, 180 MachineMemOperand &MMO) { 181 assert(MRI->getType(Res).isValid() && "invalid operand type"); 182 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 183 184 return buildInstr(TargetOpcode::G_LOAD) 185 .addDef(Res) 186 .addUse(Addr) 187 .addMemOperand(&MMO); 188 } 189 190 MachineInstrBuilder MachineIRBuilder::buildStore(unsigned Val, unsigned Addr, 191 MachineMemOperand &MMO) { 192 assert(MRI->getType(Val).isValid() && "invalid operand type"); 193 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 194 195 return buildInstr(TargetOpcode::G_STORE) 196 .addUse(Val) 197 .addUse(Addr) 198 .addMemOperand(&MMO); 199 } 200 201 MachineInstrBuilder MachineIRBuilder::buildUAdde(unsigned Res, 202 unsigned CarryOut, 203 unsigned Op0, unsigned Op1, 204 unsigned CarryIn) { 205 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 206 assert(MRI->getType(Res) == MRI->getType(Op0) && 207 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 208 assert(MRI->getType(CarryOut).isScalar() && "invalid operand type"); 209 assert(MRI->getType(CarryOut) == MRI->getType(CarryIn) && "type mismatch"); 210 211 return buildInstr(TargetOpcode::G_UADDE) 212 .addDef(Res) 213 .addDef(CarryOut) 214 .addUse(Op0) 215 .addUse(Op1) 216 .addUse(CarryIn); 217 } 218 219 MachineInstrBuilder MachineIRBuilder::buildAnyExt(unsigned Res, unsigned Op) { 220 validateTruncExt(Res, Op, true); 221 return buildInstr(TargetOpcode::G_ANYEXT).addDef(Res).addUse(Op); 222 } 223 224 MachineInstrBuilder MachineIRBuilder::buildSExt(unsigned Res, unsigned Op) { 225 validateTruncExt(Res, Op, true); 226 return buildInstr(TargetOpcode::G_SEXT).addDef(Res).addUse(Op); 227 } 228 229 MachineInstrBuilder MachineIRBuilder::buildZExt(unsigned Res, unsigned Op) { 230 validateTruncExt(Res, Op, true); 231 return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op); 232 } 233 234 MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res, 235 unsigned Op) { 236 unsigned Opcode = TargetOpcode::COPY; 237 if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits()) 238 Opcode = TargetOpcode::G_SEXT; 239 else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits()) 240 Opcode = TargetOpcode::G_TRUNC; 241 242 return buildInstr(Opcode).addDef(Res).addUse(Op); 243 } 244 245 MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<unsigned> Results, 246 ArrayRef<uint64_t> Indices, 247 unsigned Src) { 248 #ifndef NDEBUG 249 assert(Results.size() == Indices.size() && "inconsistent number of regs"); 250 assert(!Results.empty() && "invalid trivial extract"); 251 assert(std::is_sorted(Indices.begin(), Indices.end()) && 252 "extract offsets must be in ascending order"); 253 254 assert(MRI->getType(Src).isValid() && "invalid operand type"); 255 for (auto Res : Results) 256 assert(MRI->getType(Res).isValid() && "invalid operand type"); 257 #endif 258 259 auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT)); 260 for (auto Res : Results) 261 MIB.addDef(Res); 262 263 MIB.addUse(Src); 264 265 for (auto Idx : Indices) 266 MIB.addImm(Idx); 267 268 getMBB().insert(getInsertPt(), MIB); 269 if (InsertedInstr) 270 InsertedInstr(MIB); 271 272 return MIB; 273 } 274 275 MachineInstrBuilder 276 MachineIRBuilder::buildSequence(unsigned Res, 277 ArrayRef<unsigned> Ops, 278 ArrayRef<uint64_t> Indices) { 279 #ifndef NDEBUG 280 assert(Ops.size() == Indices.size() && "incompatible args"); 281 assert(!Ops.empty() && "invalid trivial sequence"); 282 assert(std::is_sorted(Indices.begin(), Indices.end()) && 283 "sequence offsets must be in ascending order"); 284 285 assert(MRI->getType(Res).isValid() && "invalid operand type"); 286 for (auto Op : Ops) 287 assert(MRI->getType(Op).isValid() && "invalid operand type"); 288 #endif 289 290 MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE); 291 MIB.addDef(Res); 292 for (unsigned i = 0; i < Ops.size(); ++i) { 293 MIB.addUse(Ops[i]); 294 MIB.addImm(Indices[i]); 295 } 296 return MIB; 297 } 298 299 MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID, 300 unsigned Res, 301 bool HasSideEffects) { 302 auto MIB = 303 buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS 304 : TargetOpcode::G_INTRINSIC); 305 if (Res) 306 MIB.addDef(Res); 307 MIB.addIntrinsicID(ID); 308 return MIB; 309 } 310 311 MachineInstrBuilder MachineIRBuilder::buildTrunc(unsigned Res, unsigned Op) { 312 validateTruncExt(Res, Op, false); 313 return buildInstr(TargetOpcode::G_TRUNC).addDef(Res).addUse(Op); 314 } 315 316 MachineInstrBuilder MachineIRBuilder::buildFPTrunc(unsigned Res, unsigned Op) { 317 validateTruncExt(Res, Op, false); 318 return buildInstr(TargetOpcode::G_FPTRUNC).addDef(Res).addUse(Op); 319 } 320 321 MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred, 322 unsigned Res, unsigned Op0, 323 unsigned Op1) { 324 #ifndef NDEBUG 325 assert(MRI->getType(Op0) == MRI->getType(Op0) && "type mismatch"); 326 assert(CmpInst::isIntPredicate(Pred) && "invalid predicate"); 327 if (MRI->getType(Op0).isScalar() || MRI->getType(Op0).isPointer()) 328 assert(MRI->getType(Res).isScalar() && "type mismatch"); 329 else 330 assert(MRI->getType(Res).isVector() && 331 MRI->getType(Res).getNumElements() == 332 MRI->getType(Op0).getNumElements() && 333 "type mismatch"); 334 #endif 335 336 return buildInstr(TargetOpcode::G_ICMP) 337 .addDef(Res) 338 .addPredicate(Pred) 339 .addUse(Op0) 340 .addUse(Op1); 341 } 342 343 MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred, 344 unsigned Res, unsigned Op0, 345 unsigned Op1) { 346 #ifndef NDEBUG 347 assert((MRI->getType(Op0).isScalar() || MRI->getType(Op0).isVector()) && 348 "invalid operand type"); 349 assert(MRI->getType(Op0) == MRI->getType(Op1) && "type mismatch"); 350 assert(CmpInst::isFPPredicate(Pred) && "invalid predicate"); 351 if (MRI->getType(Op0).isScalar()) 352 assert(MRI->getType(Res).isScalar() && "type mismatch"); 353 else 354 assert(MRI->getType(Res).isVector() && 355 MRI->getType(Res).getNumElements() == 356 MRI->getType(Op0).getNumElements() && 357 "type mismatch"); 358 #endif 359 360 return buildInstr(TargetOpcode::G_FCMP) 361 .addDef(Res) 362 .addPredicate(Pred) 363 .addUse(Op0) 364 .addUse(Op1); 365 } 366 367 MachineInstrBuilder MachineIRBuilder::buildSelect(unsigned Res, unsigned Tst, 368 unsigned Op0, unsigned Op1) { 369 #ifndef NDEBUG 370 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 371 "invalid operand type"); 372 assert(MRI->getType(Res) == MRI->getType(Op0) && 373 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 374 if (MRI->getType(Res).isScalar()) 375 assert(MRI->getType(Tst).isScalar() && "type mismatch"); 376 else 377 assert(MRI->getType(Tst).isVector() && 378 MRI->getType(Tst).getNumElements() == 379 MRI->getType(Op0).getNumElements() && 380 "type mismatch"); 381 #endif 382 383 return buildInstr(TargetOpcode::G_SELECT) 384 .addDef(Res) 385 .addUse(Tst) 386 .addUse(Op0) 387 .addUse(Op1); 388 } 389 390 void MachineIRBuilder::validateTruncExt(unsigned Dst, unsigned Src, 391 bool IsExtend) { 392 #ifndef NDEBUG 393 LLT SrcTy = MRI->getType(Src); 394 LLT DstTy = MRI->getType(Dst); 395 396 if (DstTy.isVector()) { 397 assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector"); 398 assert(SrcTy.getNumElements() == DstTy.getNumElements() && 399 "different number of elements in a trunc/ext"); 400 } else 401 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc"); 402 403 if (IsExtend) 404 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() && 405 "invalid narrowing extend"); 406 else 407 assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() && 408 "invalid widening trunc"); 409 #endif 410 } 411