1 //===- X86InstructionSelector.cpp ----------------------------*- 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 targeting of the InstructionSelector class for 11 /// X86. 12 /// \todo This should be generated by TableGen. 13 //===----------------------------------------------------------------------===// 14 15 #include "X86InstructionSelector.h" 16 #include "X86InstrInfo.h" 17 #include "X86RegisterBankInfo.h" 18 #include "X86RegisterInfo.h" 19 #include "X86Subtarget.h" 20 #include "X86TargetMachine.h" 21 #include "llvm/CodeGen/MachineBasicBlock.h" 22 #include "llvm/CodeGen/MachineFunction.h" 23 #include "llvm/CodeGen/MachineInstr.h" 24 #include "llvm/CodeGen/MachineInstrBuilder.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/IR/Type.h" 27 #include "llvm/Support/Debug.h" 28 #include "llvm/Support/raw_ostream.h" 29 30 #define DEBUG_TYPE "X86-isel" 31 32 using namespace llvm; 33 34 #ifndef LLVM_BUILD_GLOBAL_ISEL 35 #error "You shouldn't build this" 36 #endif 37 38 #include "X86GenGlobalISel.inc" 39 40 X86InstructionSelector::X86InstructionSelector(const X86Subtarget &STI, 41 const X86RegisterBankInfo &RBI) 42 : InstructionSelector(), STI(STI), TII(*STI.getInstrInfo()), 43 TRI(*STI.getRegisterInfo()), RBI(RBI) {} 44 45 // FIXME: This should be target-independent, inferred from the types declared 46 // for each class in the bank. 47 static const TargetRegisterClass * 48 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) { 49 if (RB.getID() == X86::GPRRegBankID) { 50 if (Ty.getSizeInBits() == 32) 51 return &X86::GR32RegClass; 52 if (Ty.getSizeInBits() == 64) 53 return &X86::GR64RegClass; 54 } 55 if (RB.getID() == X86::VECRRegBankID) { 56 if (Ty.getSizeInBits() == 32) 57 return &X86::FR32XRegClass; 58 if (Ty.getSizeInBits() == 64) 59 return &X86::FR64XRegClass; 60 if (Ty.getSizeInBits() == 128) 61 return &X86::VR128XRegClass; 62 if (Ty.getSizeInBits() == 256) 63 return &X86::VR256XRegClass; 64 if (Ty.getSizeInBits() == 512) 65 return &X86::VR512RegClass; 66 } 67 68 llvm_unreachable("Unknown RegBank!"); 69 } 70 71 // Set X86 Opcode and constrain DestReg. 72 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 73 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 74 const RegisterBankInfo &RBI) { 75 76 unsigned DstReg = I.getOperand(0).getReg(); 77 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { 78 assert(I.isCopy() && "Generic operators do not allow physical registers"); 79 return true; 80 } 81 82 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI); 83 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); 84 (void)DstSize; 85 unsigned SrcReg = I.getOperand(1).getReg(); 86 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI); 87 (void)SrcSize; 88 assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) && 89 "No phys reg on generic operators"); 90 assert((DstSize == SrcSize || 91 // Copies are a mean to setup initial types, the number of 92 // bits may not exactly match. 93 (TargetRegisterInfo::isPhysicalRegister(SrcReg) && 94 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) && 95 "Copy with different width?!"); 96 97 const TargetRegisterClass *RC = nullptr; 98 99 switch (RegBank.getID()) { 100 case X86::GPRRegBankID: 101 assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values."); 102 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank); 103 break; 104 case X86::VECRRegBankID: 105 RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank); 106 break; 107 default: 108 llvm_unreachable("Unknown RegBank!"); 109 } 110 111 // No need to constrain SrcReg. It will get constrained when 112 // we hit another of its use or its defs. 113 // Copies do not have constraints. 114 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg); 115 if (!OldRC || !RC->hasSubClassEq(OldRC)) { 116 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 117 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 118 << " operand\n"); 119 return false; 120 } 121 } 122 I.setDesc(TII.get(X86::COPY)); 123 return true; 124 } 125 126 bool X86InstructionSelector::select(MachineInstr &I) const { 127 assert(I.getParent() && "Instruction should be in a basic block!"); 128 assert(I.getParent()->getParent() && "Instruction should be in a function!"); 129 130 MachineBasicBlock &MBB = *I.getParent(); 131 MachineFunction &MF = *MBB.getParent(); 132 MachineRegisterInfo &MRI = MF.getRegInfo(); 133 134 unsigned Opcode = I.getOpcode(); 135 if (!isPreISelGenericOpcode(Opcode)) { 136 // Certain non-generic instructions also need some special handling. 137 138 if (I.isCopy()) 139 return selectCopy(I, TII, MRI, TRI, RBI); 140 141 // TODO: handle more cases - LOAD_STACK_GUARD, PHI 142 return true; 143 } 144 145 assert(I.getNumOperands() == I.getNumExplicitOperands() && 146 "Generic instruction has unexpected implicit operands\n"); 147 148 // TODO: This should be implemented by tblgen, pattern with predicate not supported yet. 149 if (selectBinaryOp(I, MRI)) 150 return true; 151 152 return selectImpl(I); 153 } 154 155 unsigned X86InstructionSelector::getFAddOp(LLT &Ty, 156 const RegisterBank &RB) const { 157 158 if (X86::VECRRegBankID != RB.getID()) 159 return TargetOpcode::G_FADD; 160 161 if (Ty == LLT::scalar(32)) { 162 if (STI.hasAVX512()) { 163 return X86::VADDSSZrr; 164 } else if (STI.hasAVX()) { 165 return X86::VADDSSrr; 166 } else if (STI.hasSSE1()) { 167 return X86::ADDSSrr; 168 } 169 } else if (Ty == LLT::scalar(64)) { 170 if (STI.hasAVX512()) { 171 return X86::VADDSDZrr; 172 } else if (STI.hasAVX()) { 173 return X86::VADDSDrr; 174 } else if (STI.hasSSE2()) { 175 return X86::ADDSDrr; 176 } 177 } else if (Ty == LLT::vector(4, 32)) { 178 if ((STI.hasAVX512()) && (STI.hasVLX())) { 179 return X86::VADDPSZ128rr; 180 } else if (STI.hasAVX()) { 181 return X86::VADDPSrr; 182 } else if (STI.hasSSE1()) { 183 return X86::ADDPSrr; 184 } 185 } 186 187 return TargetOpcode::G_FADD; 188 } 189 190 unsigned X86InstructionSelector::getFSubOp(LLT &Ty, 191 const RegisterBank &RB) const { 192 193 if (X86::VECRRegBankID != RB.getID()) 194 return TargetOpcode::G_FSUB; 195 196 if (Ty == LLT::scalar(32)) { 197 if (STI.hasAVX512()) { 198 return X86::VSUBSSZrr; 199 } else if (STI.hasAVX()) { 200 return X86::VSUBSSrr; 201 } else if (STI.hasSSE1()) { 202 return X86::SUBSSrr; 203 } 204 } else if (Ty == LLT::scalar(64)) { 205 if (STI.hasAVX512()) { 206 return X86::VSUBSDZrr; 207 } else if (STI.hasAVX()) { 208 return X86::VSUBSDrr; 209 } else if (STI.hasSSE2()) { 210 return X86::SUBSDrr; 211 } 212 } else if (Ty == LLT::vector(4, 32)) { 213 if ((STI.hasAVX512()) && (STI.hasVLX())) { 214 return X86::VSUBPSZ128rr; 215 } else if (STI.hasAVX()) { 216 return X86::VSUBPSrr; 217 } else if (STI.hasSSE1()) { 218 return X86::SUBPSrr; 219 } 220 } 221 222 return TargetOpcode::G_FSUB; 223 } 224 225 unsigned X86InstructionSelector::getAddOp(LLT &Ty, 226 const RegisterBank &RB) const { 227 228 if (X86::VECRRegBankID != RB.getID()) 229 return TargetOpcode::G_ADD; 230 231 if (Ty == LLT::vector(4, 32)) { 232 if (STI.hasAVX512() && STI.hasVLX()) { 233 return X86::VPADDDZ128rr; 234 } else if (STI.hasAVX()) { 235 return X86::VPADDDrr; 236 } else if (STI.hasSSE2()) { 237 return X86::PADDDrr; 238 } 239 } 240 241 return TargetOpcode::G_ADD; 242 } 243 244 unsigned X86InstructionSelector::getSubOp(LLT &Ty, 245 const RegisterBank &RB) const { 246 247 if (X86::VECRRegBankID != RB.getID()) 248 return TargetOpcode::G_SUB; 249 250 if (Ty == LLT::vector(4, 32)) { 251 if (STI.hasAVX512() && STI.hasVLX()) { 252 return X86::VPSUBDZ128rr; 253 } else if (STI.hasAVX()) { 254 return X86::VPSUBDrr; 255 } else if (STI.hasSSE2()) { 256 return X86::PSUBDrr; 257 } 258 } 259 260 return TargetOpcode::G_SUB; 261 } 262 263 bool X86InstructionSelector::selectBinaryOp(MachineInstr &I, 264 MachineRegisterInfo &MRI) const { 265 266 LLT Ty = MRI.getType(I.getOperand(0).getReg()); 267 const unsigned DefReg = I.getOperand(0).getReg(); 268 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI); 269 270 unsigned NewOpc = I.getOpcode(); 271 272 switch (I.getOpcode()) { 273 case TargetOpcode::G_FADD: 274 NewOpc = getFAddOp(Ty, RB); 275 break; 276 case TargetOpcode::G_FSUB: 277 NewOpc = getFSubOp(Ty, RB); 278 break; 279 case TargetOpcode::G_ADD: 280 NewOpc = getAddOp(Ty, RB); 281 break; 282 case TargetOpcode::G_SUB: 283 NewOpc = getSubOp(Ty, RB); 284 break; 285 default: 286 break; 287 } 288 289 if (NewOpc == I.getOpcode()) 290 return false; 291 292 I.setDesc(TII.get(NewOpc)); 293 294 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 295 } 296 297