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/Target/TargetInstrInfo.h" 18 #include "llvm/Target/TargetOpcodes.h" 19 #include "llvm/Target/TargetSubtargetInfo.h" 20 21 using namespace llvm; 22 23 void MachineIRBuilder::setMF(MachineFunction &MF) { 24 this->MF = &MF; 25 this->MBB = nullptr; 26 this->TII = MF.getSubtarget().getInstrInfo(); 27 this->DL = DebugLoc(); 28 this->MI = nullptr; 29 this->InsertedInstr = nullptr; 30 } 31 32 void MachineIRBuilder::setMBB(MachineBasicBlock &MBB, bool Beginning) { 33 this->MBB = &MBB; 34 Before = Beginning; 35 assert(&getMF() == MBB.getParent() && 36 "Basic block is in a different function"); 37 } 38 39 void MachineIRBuilder::setInstr(MachineInstr &MI, bool Before) { 40 assert(MI.getParent() && "Instruction is not part of a basic block"); 41 setMBB(*MI.getParent()); 42 this->MI = &MI; 43 this->Before = Before; 44 } 45 46 MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() { 47 if (MI) { 48 if (Before) 49 return MI; 50 if (!MI->getNextNode()) 51 return getMBB().end(); 52 return MI->getNextNode(); 53 } 54 return Before ? getMBB().begin() : getMBB().end(); 55 } 56 57 void MachineIRBuilder::recordInsertions( 58 std::function<void(MachineInstr *)> Inserted) { 59 InsertedInstr = Inserted; 60 } 61 62 void MachineIRBuilder::stopRecordingInsertions() { 63 InsertedInstr = nullptr; 64 } 65 66 //------------------------------------------------------------------------------ 67 // Build instruction variants. 68 //------------------------------------------------------------------------------ 69 70 MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode, 71 ArrayRef<LLT> Tys) { 72 MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode)); 73 if (Tys.size() > 0) { 74 assert(isPreISelGenericOpcode(Opcode) && 75 "Only generic instruction can have a type"); 76 for (unsigned i = 0; i < Tys.size(); ++i) 77 MIB->setType(Tys[i], i); 78 } else 79 assert(!isPreISelGenericOpcode(Opcode) && 80 "Generic instruction must have a type"); 81 getMBB().insert(getInsertPt(), MIB); 82 if (InsertedInstr) 83 InsertedInstr(MIB); 84 return MIB; 85 } 86 87 MachineInstrBuilder MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res, 88 int Idx) { 89 return buildInstr(TargetOpcode::G_FRAME_INDEX, Ty) 90 .addDef(Res) 91 .addFrameIndex(Idx); 92 } 93 94 MachineInstrBuilder MachineIRBuilder::buildAdd(LLT Ty, unsigned Res, 95 unsigned Op0, unsigned Op1) { 96 return buildInstr(TargetOpcode::G_ADD, Ty) 97 .addDef(Res) 98 .addUse(Op0) 99 .addUse(Op1); 100 } 101 102 MachineInstrBuilder MachineIRBuilder::buildSub(LLT Ty, unsigned Res, 103 unsigned Op0, unsigned Op1) { 104 return buildInstr(TargetOpcode::G_SUB, Ty) 105 .addDef(Res) 106 .addUse(Op0) 107 .addUse(Op1); 108 } 109 110 MachineInstrBuilder MachineIRBuilder::buildMul(LLT Ty, unsigned Res, 111 unsigned Op0, unsigned Op1) { 112 return buildInstr(TargetOpcode::G_MUL, Ty) 113 .addDef(Res) 114 .addUse(Op0) 115 .addUse(Op1); 116 } 117 118 MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) { 119 return buildInstr(TargetOpcode::G_BR, LLT::unsized()).addMBB(&Dest); 120 } 121 122 MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) { 123 return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op); 124 } 125 126 MachineInstrBuilder MachineIRBuilder::buildConstant(LLT Ty, unsigned Res, 127 int64_t Val) { 128 return buildInstr(TargetOpcode::G_CONSTANT, Ty).addDef(Res).addImm(Val); 129 } 130 131 MachineInstrBuilder MachineIRBuilder::buildFConstant(LLT Ty, unsigned Res, 132 const ConstantFP &Val) { 133 return buildInstr(TargetOpcode::G_FCONSTANT, Ty).addDef(Res).addFPImm(&Val); 134 } 135 136 MachineInstrBuilder MachineIRBuilder::buildBrCond(LLT Ty, unsigned Tst, 137 MachineBasicBlock &Dest) { 138 return buildInstr(TargetOpcode::G_BRCOND, Ty).addUse(Tst).addMBB(&Dest); 139 } 140 141 142 MachineInstrBuilder MachineIRBuilder::buildLoad(LLT VTy, LLT PTy, unsigned Res, 143 unsigned Addr, 144 MachineMemOperand &MMO) { 145 return buildInstr(TargetOpcode::G_LOAD, {VTy, PTy}) 146 .addDef(Res) 147 .addUse(Addr) 148 .addMemOperand(&MMO); 149 } 150 151 MachineInstrBuilder MachineIRBuilder::buildStore(LLT VTy, LLT PTy, 152 unsigned Val, unsigned Addr, 153 MachineMemOperand &MMO) { 154 return buildInstr(TargetOpcode::G_STORE, {VTy, PTy}) 155 .addUse(Val) 156 .addUse(Addr) 157 .addMemOperand(&MMO); 158 } 159 160 MachineInstrBuilder 161 MachineIRBuilder::buildUAdde(ArrayRef<LLT> Tys, unsigned Res, unsigned CarryOut, 162 unsigned Op0, unsigned Op1, unsigned CarryIn) { 163 return buildInstr(TargetOpcode::G_UADDE, Tys) 164 .addDef(Res) 165 .addDef(CarryOut) 166 .addUse(Op0) 167 .addUse(Op1) 168 .addUse(CarryIn); 169 } 170 171 MachineInstrBuilder MachineIRBuilder::buildType(LLT Ty, 172 unsigned Res, unsigned Op) { 173 return buildInstr(TargetOpcode::G_TYPE, Ty).addDef(Res).addUse(Op); 174 } 175 176 MachineInstrBuilder MachineIRBuilder::buildAnyExt(ArrayRef<LLT> Tys, 177 unsigned Res, unsigned Op) { 178 validateTruncExt(Tys, true); 179 return buildInstr(TargetOpcode::G_ANYEXT, Tys).addDef(Res).addUse(Op); 180 } 181 182 MachineInstrBuilder MachineIRBuilder::buildSExt(ArrayRef<LLT> Tys, unsigned Res, 183 unsigned Op) { 184 validateTruncExt(Tys, true); 185 return buildInstr(TargetOpcode::G_SEXT, Tys).addDef(Res).addUse(Op); 186 } 187 188 MachineInstrBuilder MachineIRBuilder::buildZExt(ArrayRef<LLT> Tys, unsigned Res, 189 unsigned Op) { 190 validateTruncExt(Tys, true); 191 return buildInstr(TargetOpcode::G_ZEXT, Tys).addDef(Res).addUse(Op); 192 } 193 194 MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<LLT> ResTys, 195 ArrayRef<unsigned> Results, 196 ArrayRef<uint64_t> Indices, 197 LLT SrcTy, unsigned Src) { 198 assert(ResTys.size() == Results.size() && Results.size() == Indices.size() && 199 "inconsistent number of regs"); 200 assert(!Results.empty() && "invalid trivial extract"); 201 assert(std::is_sorted(Indices.begin(), Indices.end()) && 202 "extract offsets must be in ascending order"); 203 204 auto MIB = BuildMI(getMF(), DL, getTII().get(TargetOpcode::G_EXTRACT)); 205 for (unsigned i = 0; i < ResTys.size(); ++i) 206 MIB->setType(LLT::scalar(ResTys[i].getSizeInBits()), i); 207 MIB->setType(LLT::scalar(SrcTy.getSizeInBits()), ResTys.size()); 208 209 for (auto Res : Results) 210 MIB.addDef(Res); 211 212 MIB.addUse(Src); 213 214 for (auto Idx : Indices) 215 MIB.addImm(Idx); 216 217 getMBB().insert(getInsertPt(), MIB); 218 if (InsertedInstr) 219 InsertedInstr(MIB); 220 221 return MIB; 222 } 223 224 MachineInstrBuilder 225 MachineIRBuilder::buildSequence(LLT ResTy, unsigned Res, 226 ArrayRef<LLT> OpTys, 227 ArrayRef<unsigned> Ops, 228 ArrayRef<unsigned> Indices) { 229 assert(OpTys.size() == Ops.size() && Ops.size() == Indices.size() && 230 "incompatible args"); 231 assert(!Ops.empty() && "invalid trivial sequence"); 232 assert(std::is_sorted(Indices.begin(), Indices.end()) && 233 "sequence offsets must be in ascending order"); 234 235 MachineInstrBuilder MIB = 236 buildInstr(TargetOpcode::G_SEQUENCE, LLT::scalar(ResTy.getSizeInBits())); 237 MIB.addDef(Res); 238 for (unsigned i = 0; i < Ops.size(); ++i) { 239 MIB.addUse(Ops[i]); 240 MIB.addImm(Indices[i]); 241 MIB->setType(LLT::scalar(OpTys[i].getSizeInBits()), MIB->getNumTypes()); 242 } 243 return MIB; 244 } 245 246 MachineInstrBuilder MachineIRBuilder::buildIntrinsic(ArrayRef<LLT> Tys, 247 Intrinsic::ID ID, 248 unsigned Res, 249 bool HasSideEffects) { 250 auto MIB = 251 buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS 252 : TargetOpcode::G_INTRINSIC, 253 Tys); 254 if (Res) 255 MIB.addDef(Res); 256 MIB.addIntrinsicID(ID); 257 return MIB; 258 } 259 260 MachineInstrBuilder MachineIRBuilder::buildTrunc(ArrayRef<LLT> Tys, 261 unsigned Res, unsigned Op) { 262 validateTruncExt(Tys, false); 263 return buildInstr(TargetOpcode::G_TRUNC, Tys).addDef(Res).addUse(Op); 264 } 265 266 MachineInstrBuilder MachineIRBuilder::buildFPTrunc(ArrayRef<LLT> Tys, 267 unsigned Res, unsigned Op) { 268 validateTruncExt(Tys, false); 269 return buildInstr(TargetOpcode::G_FPTRUNC, Tys).addDef(Res).addUse(Op); 270 } 271 272 MachineInstrBuilder MachineIRBuilder::buildICmp(ArrayRef<LLT> Tys, 273 CmpInst::Predicate Pred, 274 unsigned Res, unsigned Op0, 275 unsigned Op1) { 276 return buildInstr(TargetOpcode::G_ICMP, Tys) 277 .addDef(Res) 278 .addPredicate(Pred) 279 .addUse(Op0) 280 .addUse(Op1); 281 } 282 283 MachineInstrBuilder MachineIRBuilder::buildFCmp(ArrayRef<LLT> Tys, 284 CmpInst::Predicate Pred, 285 unsigned Res, unsigned Op0, 286 unsigned Op1) { 287 return buildInstr(TargetOpcode::G_FCMP, Tys) 288 .addDef(Res) 289 .addPredicate(Pred) 290 .addUse(Op0) 291 .addUse(Op1); 292 } 293 294 MachineInstrBuilder MachineIRBuilder::buildSelect(LLT Ty, unsigned Res, 295 unsigned Tst, 296 unsigned Op0, unsigned Op1) { 297 return buildInstr(TargetOpcode::G_SELECT, {Ty, LLT::scalar(1)}) 298 .addDef(Res) 299 .addUse(Tst) 300 .addUse(Op0) 301 .addUse(Op1); 302 } 303 304 void MachineIRBuilder::validateTruncExt(ArrayRef<LLT> Tys, bool IsExtend) { 305 #ifndef NDEBUG 306 assert(Tys.size() == 2 && "cast should have a source and a dest type"); 307 LLT DstTy{Tys[0]}, SrcTy{Tys[1]}; 308 309 if (DstTy.isVector()) { 310 assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector"); 311 assert(SrcTy.getNumElements() == DstTy.getNumElements() && 312 "different number of elements in a trunc/ext"); 313 } else 314 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc"); 315 316 if (IsExtend) 317 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() && 318 "invalid narrowing extend"); 319 else 320 assert(DstTy.getSizeInBits() < SrcTy.getSizeInBits() && 321 "invalid widening trunc"); 322 #endif 323 } 324