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::buildAdd(unsigned Res, unsigned Op0, 88 unsigned Op1) { 89 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 90 "invalid operand type"); 91 assert(MRI->getType(Res) == MRI->getType(Op0) && 92 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 93 94 return buildInstr(TargetOpcode::G_ADD) 95 .addDef(Res) 96 .addUse(Op0) 97 .addUse(Op1); 98 } 99 100 MachineInstrBuilder MachineIRBuilder::buildSub(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_SUB) 108 .addDef(Res) 109 .addUse(Op0) 110 .addUse(Op1); 111 } 112 113 MachineInstrBuilder MachineIRBuilder::buildMul(unsigned Res, unsigned Op0, 114 unsigned Op1) { 115 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 116 "invalid operand type"); 117 assert(MRI->getType(Res) == MRI->getType(Op0) && 118 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 119 120 return buildInstr(TargetOpcode::G_MUL) 121 .addDef(Res) 122 .addUse(Op0) 123 .addUse(Op1); 124 } 125 126 MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) { 127 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest); 128 } 129 130 MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) { 131 return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op); 132 } 133 134 MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res, int64_t Val) { 135 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 136 137 return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addImm(Val); 138 } 139 140 MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res, 141 const ConstantFP &Val) { 142 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 143 144 return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val); 145 } 146 147 MachineInstrBuilder MachineIRBuilder::buildBrCond(unsigned Tst, 148 MachineBasicBlock &Dest) { 149 assert(MRI->getType(Tst).isScalar() && "invalid operand type"); 150 151 return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest); 152 } 153 154 MachineInstrBuilder MachineIRBuilder::buildLoad(unsigned Res, unsigned Addr, 155 MachineMemOperand &MMO) { 156 assert(MRI->getType(Res).isValid() && "invalid operand type"); 157 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 158 159 return buildInstr(TargetOpcode::G_LOAD) 160 .addDef(Res) 161 .addUse(Addr) 162 .addMemOperand(&MMO); 163 } 164 165 MachineInstrBuilder MachineIRBuilder::buildStore(unsigned Val, unsigned Addr, 166 MachineMemOperand &MMO) { 167 assert(MRI->getType(Val).isValid() && "invalid operand type"); 168 assert(MRI->getType(Addr).isPointer() && "invalid operand type"); 169 170 return buildInstr(TargetOpcode::G_STORE) 171 .addUse(Val) 172 .addUse(Addr) 173 .addMemOperand(&MMO); 174 } 175 176 MachineInstrBuilder MachineIRBuilder::buildUAdde(unsigned Res, 177 unsigned CarryOut, 178 unsigned Op0, unsigned Op1, 179 unsigned CarryIn) { 180 assert(MRI->getType(Res).isScalar() && "invalid operand type"); 181 assert(MRI->getType(Res) == MRI->getType(Op0) && 182 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 183 assert(MRI->getType(CarryOut).isScalar() && "invalid operand type"); 184 assert(MRI->getType(CarryOut) == MRI->getType(CarryIn) && "type mismatch"); 185 186 return buildInstr(TargetOpcode::G_UADDE) 187 .addDef(Res) 188 .addDef(CarryOut) 189 .addUse(Op0) 190 .addUse(Op1) 191 .addUse(CarryIn); 192 } 193 194 MachineInstrBuilder MachineIRBuilder::buildAnyExt(unsigned Res, unsigned Op) { 195 validateTruncExt(Res, Op, true); 196 return buildInstr(TargetOpcode::G_ANYEXT).addDef(Res).addUse(Op); 197 } 198 199 MachineInstrBuilder MachineIRBuilder::buildSExt(unsigned Res, unsigned Op) { 200 validateTruncExt(Res, Op, true); 201 return buildInstr(TargetOpcode::G_SEXT).addDef(Res).addUse(Op); 202 } 203 204 MachineInstrBuilder MachineIRBuilder::buildZExt(unsigned Res, unsigned Op) { 205 validateTruncExt(Res, Op, true); 206 return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op); 207 } 208 209 MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<unsigned> Results, 210 ArrayRef<uint64_t> Indices, 211 unsigned Src) { 212 #ifndef NDEBUG 213 assert(Results.size() == Indices.size() && "inconsistent number of regs"); 214 assert(!Results.empty() && "invalid trivial extract"); 215 assert(std::is_sorted(Indices.begin(), Indices.end()) && 216 "extract offsets must be in ascending order"); 217 218 assert(MRI->getType(Src).isValid() && "invalid operand type"); 219 for (auto Res : Results) 220 assert(MRI->getType(Res).isValid() && "invalid operand type"); 221 #endif 222 223 auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT)); 224 for (auto Res : Results) 225 MIB.addDef(Res); 226 227 MIB.addUse(Src); 228 229 for (auto Idx : Indices) 230 MIB.addImm(Idx); 231 232 getMBB().insert(getInsertPt(), MIB); 233 if (InsertedInstr) 234 InsertedInstr(MIB); 235 236 return MIB; 237 } 238 239 MachineInstrBuilder 240 MachineIRBuilder::buildSequence(unsigned Res, 241 ArrayRef<unsigned> Ops, 242 ArrayRef<unsigned> Indices) { 243 #ifndef NDEBUG 244 assert(Ops.size() == Indices.size() && "incompatible args"); 245 assert(!Ops.empty() && "invalid trivial sequence"); 246 assert(std::is_sorted(Indices.begin(), Indices.end()) && 247 "sequence offsets must be in ascending order"); 248 249 assert(MRI->getType(Res).isValid() && "invalid operand type"); 250 for (auto Op : Ops) 251 assert(MRI->getType(Op).isValid() && "invalid operand type"); 252 #endif 253 254 MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE); 255 MIB.addDef(Res); 256 for (unsigned i = 0; i < Ops.size(); ++i) { 257 MIB.addUse(Ops[i]); 258 MIB.addImm(Indices[i]); 259 } 260 return MIB; 261 } 262 263 MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID, 264 unsigned Res, 265 bool HasSideEffects) { 266 auto MIB = 267 buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS 268 : TargetOpcode::G_INTRINSIC); 269 if (Res) 270 MIB.addDef(Res); 271 MIB.addIntrinsicID(ID); 272 return MIB; 273 } 274 275 MachineInstrBuilder MachineIRBuilder::buildTrunc(unsigned Res, unsigned Op) { 276 validateTruncExt(Res, Op, false); 277 return buildInstr(TargetOpcode::G_TRUNC).addDef(Res).addUse(Op); 278 } 279 280 MachineInstrBuilder MachineIRBuilder::buildFPTrunc(unsigned Res, unsigned Op) { 281 validateTruncExt(Res, Op, false); 282 return buildInstr(TargetOpcode::G_FPTRUNC).addDef(Res).addUse(Op); 283 } 284 285 MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred, 286 unsigned Res, unsigned Op0, 287 unsigned Op1) { 288 #ifndef NDEBUG 289 assert((MRI->getType(Op0).isScalar() || MRI->getType(Op0).isVector()) && 290 "invalid operand type"); 291 assert(MRI->getType(Op0) == MRI->getType(Op0) && "type mismatch"); 292 assert(CmpInst::isIntPredicate(Pred) && "invalid predicate"); 293 if (MRI->getType(Op0).isScalar()) 294 assert(MRI->getType(Res).isScalar() && "type mismatch"); 295 else 296 assert(MRI->getType(Res).isVector() && 297 MRI->getType(Res).getNumElements() == 298 MRI->getType(Op0).getNumElements() && 299 "type mismatch"); 300 #endif 301 302 return buildInstr(TargetOpcode::G_ICMP) 303 .addDef(Res) 304 .addPredicate(Pred) 305 .addUse(Op0) 306 .addUse(Op1); 307 } 308 309 MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred, 310 unsigned Res, unsigned Op0, 311 unsigned Op1) { 312 #ifndef NDEBUG 313 assert((MRI->getType(Op0).isScalar() || MRI->getType(Op0).isVector()) && 314 "invalid operand type"); 315 assert(MRI->getType(Op0) == MRI->getType(Op1) && "type mismatch"); 316 assert(CmpInst::isFPPredicate(Pred) && "invalid predicate"); 317 if (MRI->getType(Op0).isScalar()) 318 assert(MRI->getType(Res).isScalar() && "type mismatch"); 319 else 320 assert(MRI->getType(Res).isVector() && 321 MRI->getType(Res).getNumElements() == 322 MRI->getType(Op0).getNumElements() && 323 "type mismatch"); 324 #endif 325 326 return buildInstr(TargetOpcode::G_FCMP) 327 .addDef(Res) 328 .addPredicate(Pred) 329 .addUse(Op0) 330 .addUse(Op1); 331 } 332 333 MachineInstrBuilder MachineIRBuilder::buildSelect(unsigned Res, unsigned Tst, 334 unsigned Op0, unsigned Op1) { 335 #ifndef NDEBUG 336 assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) && 337 "invalid operand type"); 338 assert(MRI->getType(Res) == MRI->getType(Op0) && 339 MRI->getType(Res) == MRI->getType(Op1) && "type mismatch"); 340 if (MRI->getType(Res).isScalar()) 341 assert(MRI->getType(Tst).isScalar() && "type mismatch"); 342 else 343 assert(MRI->getType(Tst).isVector() && 344 MRI->getType(Tst).getNumElements() == 345 MRI->getType(Op0).getNumElements() && 346 "type mismatch"); 347 #endif 348 349 return buildInstr(TargetOpcode::G_SELECT) 350 .addDef(Res) 351 .addUse(Tst) 352 .addUse(Op0) 353 .addUse(Op1); 354 } 355 356 void MachineIRBuilder::validateTruncExt(unsigned Dst, unsigned Src, 357 bool IsExtend) { 358 #ifndef NDEBUG 359 LLT SrcTy = MRI->getType(Src); 360 LLT DstTy = MRI->getType(Dst); 361 362 if (DstTy.isVector()) { 363 assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector"); 364 assert(SrcTy.getNumElements() == DstTy.getNumElements() && 365 "different number of elements in a trunc/ext"); 366 } else 367 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc"); 368 369 if (IsExtend) 370 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() && 371 "invalid narrowing extend"); 372 else 373 assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() && 374 "invalid widening trunc"); 375 #endif 376 } 377