1 //===- ARMInstructionSelector.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 ARM. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMInstructionSelector.h" 15 #include "ARMRegisterBankInfo.h" 16 #include "ARMSubtarget.h" 17 #include "ARMTargetMachine.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 #include "llvm/Support/Debug.h" 20 21 #define DEBUG_TYPE "arm-isel" 22 23 using namespace llvm; 24 25 #ifndef LLVM_BUILD_GLOBAL_ISEL 26 #error "You shouldn't build this" 27 #endif 28 29 ARMInstructionSelector::ARMInstructionSelector(const ARMSubtarget &STI, 30 const ARMRegisterBankInfo &RBI) 31 : InstructionSelector(), TII(*STI.getInstrInfo()), 32 TRI(*STI.getRegisterInfo()), RBI(RBI) {} 33 34 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 35 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 36 const RegisterBankInfo &RBI) { 37 unsigned DstReg = I.getOperand(0).getReg(); 38 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) 39 return true; 40 41 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); 42 (void)RegBank; 43 assert(RegBank && "Can't get reg bank for virtual register"); 44 45 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); 46 (void)DstSize; 47 unsigned SrcReg = I.getOperand(1).getReg(); 48 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI); 49 (void)SrcSize; 50 assert((DstSize == SrcSize || 51 // Copies are a means to setup initial types, the number of 52 // bits may not exactly match. 53 (TargetRegisterInfo::isPhysicalRegister(SrcReg) && 54 DstSize <= SrcSize)) && 55 "Copy with different width?!"); 56 57 assert((RegBank->getID() == ARM::GPRRegBankID || 58 RegBank->getID() == ARM::FPRRegBankID) && 59 "Unsupported reg bank"); 60 61 const TargetRegisterClass *RC = &ARM::GPRRegClass; 62 63 if (RegBank->getID() == ARM::FPRRegBankID) { 64 assert(DstSize == 32 && "Only 32-bit FP values are supported"); 65 RC = &ARM::SPRRegClass; 66 } 67 68 // No need to constrain SrcReg. It will get constrained when 69 // we hit another of its uses or its defs. 70 // Copies do not have constraints. 71 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 72 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 73 << " operand\n"); 74 return false; 75 } 76 return true; 77 } 78 79 /// Select the opcode for simple extensions (that translate to a single SXT/UXT 80 /// instruction). Extension operations more complicated than that should not 81 /// invoke this. 82 static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) { 83 using namespace TargetOpcode; 84 85 assert((Size == 8 || Size == 16) && "Unsupported size"); 86 87 if (Opc == G_SEXT) 88 return Size == 8 ? ARM::SXTB : ARM::SXTH; 89 90 if (Opc == G_ZEXT) 91 return Size == 8 ? ARM::UXTB : ARM::UXTH; 92 93 llvm_unreachable("Unsupported opcode"); 94 } 95 96 /// Select the opcode for simple loads. For types smaller than 32 bits, the 97 /// value will be zero extended. 98 static unsigned selectLoadOpCode(unsigned Size) { 99 switch (Size) { 100 case 1: 101 case 8: 102 return ARM::LDRBi12; 103 case 16: 104 return ARM::LDRH; 105 case 32: 106 return ARM::LDRi12; 107 } 108 109 llvm_unreachable("Unsupported size"); 110 } 111 112 bool ARMInstructionSelector::select(MachineInstr &I) const { 113 assert(I.getParent() && "Instruction should be in a basic block!"); 114 assert(I.getParent()->getParent() && "Instruction should be in a function!"); 115 116 auto &MBB = *I.getParent(); 117 auto &MF = *MBB.getParent(); 118 auto &MRI = MF.getRegInfo(); 119 120 if (!isPreISelGenericOpcode(I.getOpcode())) { 121 if (I.isCopy()) 122 return selectCopy(I, TII, MRI, TRI, RBI); 123 124 return true; 125 } 126 127 MachineInstrBuilder MIB{MF, I}; 128 bool isSExt = false; 129 130 using namespace TargetOpcode; 131 switch (I.getOpcode()) { 132 case G_SEXT: 133 isSExt = true; 134 LLVM_FALLTHROUGH; 135 case G_ZEXT: { 136 LLT DstTy = MRI.getType(I.getOperand(0).getReg()); 137 // FIXME: Smaller destination sizes coming soon! 138 if (DstTy.getSizeInBits() != 32) { 139 DEBUG(dbgs() << "Unsupported destination size for extension"); 140 return false; 141 } 142 143 LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); 144 unsigned SrcSize = SrcTy.getSizeInBits(); 145 switch (SrcSize) { 146 case 1: { 147 // ZExt boils down to & 0x1; for SExt we also subtract that from 0 148 I.setDesc(TII.get(ARM::ANDri)); 149 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp()); 150 151 if (isSExt) { 152 unsigned SExtResult = I.getOperand(0).getReg(); 153 154 // Use a new virtual register for the result of the AND 155 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass); 156 I.getOperand(0).setReg(AndResult); 157 158 auto InsertBefore = std::next(I.getIterator()); 159 auto SubI = 160 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri)) 161 .addDef(SExtResult) 162 .addUse(AndResult) 163 .addImm(0) 164 .add(predOps(ARMCC::AL)) 165 .add(condCodeOp()); 166 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI)) 167 return false; 168 } 169 break; 170 } 171 case 8: 172 case 16: { 173 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize); 174 I.setDesc(TII.get(NewOpc)); 175 MIB.addImm(0).add(predOps(ARMCC::AL)); 176 break; 177 } 178 default: 179 DEBUG(dbgs() << "Unsupported source size for extension"); 180 return false; 181 } 182 break; 183 } 184 case G_ADD: 185 I.setDesc(TII.get(ARM::ADDrr)); 186 MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); 187 break; 188 case G_FADD: 189 if (!TII.getSubtarget().hasVFP2() || 190 TII.getSubtarget().useNEONForSinglePrecisionFP()) 191 return false; 192 I.setDesc(TII.get(ARM::VADDS)); 193 MIB.add(predOps(ARMCC::AL)); 194 break; 195 case G_FRAME_INDEX: 196 // Add 0 to the given frame index and hope it will eventually be folded into 197 // the user(s). 198 I.setDesc(TII.get(ARM::ADDri)); 199 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp()); 200 break; 201 case G_LOAD: { 202 LLT ValTy = MRI.getType(I.getOperand(0).getReg()); 203 const auto ValSize = ValTy.getSizeInBits(); 204 205 if (ValSize != 32 && ValSize != 16 && ValSize != 8 && ValSize != 1) 206 return false; 207 208 const auto NewOpc = selectLoadOpCode(ValSize); 209 I.setDesc(TII.get(NewOpc)); 210 211 if (NewOpc == ARM::LDRH) 212 // LDRH has a funny addressing mode (there's already a FIXME for it). 213 MIB.addReg(0); 214 MIB.addImm(0).add(predOps(ARMCC::AL)); 215 break; 216 } 217 default: 218 return false; 219 } 220 221 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 222 } 223