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