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 && "Unsupported reg bank"); 58 const TargetRegisterClass *RC = &ARM::GPRRegClass; 59 60 // No need to constrain SrcReg. It will get constrained when 61 // we hit another of its uses or its defs. 62 // Copies do not have constraints. 63 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 64 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 65 << " operand\n"); 66 return false; 67 } 68 return true; 69 } 70 71 /// Select the opcode for simple extensions (that translate to a single SXT/UXT 72 /// instruction). Extension operations more complicated than that should not 73 /// invoke this. 74 static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) { 75 using namespace TargetOpcode; 76 77 assert((Size == 8 || Size == 16) && "Unsupported size"); 78 79 if (Opc == G_SEXT) 80 return Size == 8 ? ARM::SXTB : ARM::SXTH; 81 82 if (Opc == G_ZEXT) 83 return Size == 8 ? ARM::UXTB : ARM::UXTH; 84 85 llvm_unreachable("Unsupported opcode"); 86 } 87 88 /// Select the opcode for simple loads. For types smaller than 32 bits, the 89 /// value will be zero extended. 90 static unsigned selectLoadOpCode(unsigned Size) { 91 switch (Size) { 92 case 1: 93 case 8: 94 return ARM::LDRBi12; 95 case 16: 96 return ARM::LDRH; 97 case 32: 98 return ARM::LDRi12; 99 } 100 101 llvm_unreachable("Unsupported size"); 102 } 103 104 bool ARMInstructionSelector::select(MachineInstr &I) const { 105 assert(I.getParent() && "Instruction should be in a basic block!"); 106 assert(I.getParent()->getParent() && "Instruction should be in a function!"); 107 108 auto &MBB = *I.getParent(); 109 auto &MF = *MBB.getParent(); 110 auto &MRI = MF.getRegInfo(); 111 112 if (!isPreISelGenericOpcode(I.getOpcode())) { 113 if (I.isCopy()) 114 return selectCopy(I, TII, MRI, TRI, RBI); 115 116 return true; 117 } 118 119 MachineInstrBuilder MIB{MF, I}; 120 bool isSExt = false; 121 122 using namespace TargetOpcode; 123 switch (I.getOpcode()) { 124 case G_SEXT: 125 isSExt = true; 126 LLVM_FALLTHROUGH; 127 case G_ZEXT: { 128 LLT DstTy = MRI.getType(I.getOperand(0).getReg()); 129 // FIXME: Smaller destination sizes coming soon! 130 if (DstTy.getSizeInBits() != 32) { 131 DEBUG(dbgs() << "Unsupported destination size for extension"); 132 return false; 133 } 134 135 LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); 136 unsigned SrcSize = SrcTy.getSizeInBits(); 137 switch (SrcSize) { 138 case 1: { 139 // ZExt boils down to & 0x1; for SExt we also subtract that from 0 140 I.setDesc(TII.get(ARM::ANDri)); 141 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp()); 142 143 if (isSExt) { 144 unsigned SExtResult = I.getOperand(0).getReg(); 145 146 // Use a new virtual register for the result of the AND 147 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass); 148 I.getOperand(0).setReg(AndResult); 149 150 auto InsertBefore = std::next(I.getIterator()); 151 auto SubI = 152 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri)) 153 .addDef(SExtResult) 154 .addUse(AndResult) 155 .addImm(0) 156 .add(predOps(ARMCC::AL)) 157 .add(condCodeOp()); 158 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI)) 159 return false; 160 } 161 break; 162 } 163 case 8: 164 case 16: { 165 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize); 166 I.setDesc(TII.get(NewOpc)); 167 MIB.addImm(0).add(predOps(ARMCC::AL)); 168 break; 169 } 170 default: 171 DEBUG(dbgs() << "Unsupported source size for extension"); 172 return false; 173 } 174 break; 175 } 176 case G_ADD: 177 I.setDesc(TII.get(ARM::ADDrr)); 178 MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); 179 break; 180 case G_FRAME_INDEX: 181 // Add 0 to the given frame index and hope it will eventually be folded into 182 // the user(s). 183 I.setDesc(TII.get(ARM::ADDri)); 184 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp()); 185 break; 186 case G_LOAD: { 187 LLT ValTy = MRI.getType(I.getOperand(0).getReg()); 188 const auto ValSize = ValTy.getSizeInBits(); 189 190 if (ValSize != 32 && ValSize != 16 && ValSize != 8 && ValSize != 1) 191 return false; 192 193 const auto NewOpc = selectLoadOpCode(ValSize); 194 I.setDesc(TII.get(NewOpc)); 195 196 if (NewOpc == ARM::LDRH) 197 // LDRH has a funny addressing mode (there's already a FIXME for it). 198 MIB.addReg(0); 199 MIB.addImm(0).add(predOps(ARMCC::AL)); 200 break; 201 } 202 default: 203 return false; 204 } 205 206 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 207 } 208