1 //===- ARMLegalizerInfo.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 Machinelegalizer class for ARM. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMLegalizerInfo.h" 15 #include "ARMCallLowering.h" 16 #include "ARMSubtarget.h" 17 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 18 #include "llvm/CodeGen/LowLevelType.h" 19 #include "llvm/CodeGen/MachineRegisterInfo.h" 20 #include "llvm/CodeGen/ValueTypes.h" 21 #include "llvm/IR/DerivedTypes.h" 22 #include "llvm/IR/Type.h" 23 #include "llvm/Target/TargetOpcodes.h" 24 25 using namespace llvm; 26 27 #ifndef LLVM_BUILD_GLOBAL_ISEL 28 #error "You shouldn't build this" 29 #endif 30 31 ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { 32 using namespace TargetOpcode; 33 34 const LLT p0 = LLT::pointer(0, 32); 35 36 const LLT s1 = LLT::scalar(1); 37 const LLT s8 = LLT::scalar(8); 38 const LLT s16 = LLT::scalar(16); 39 const LLT s32 = LLT::scalar(32); 40 const LLT s64 = LLT::scalar(64); 41 42 setAction({G_FRAME_INDEX, p0}, Legal); 43 44 for (unsigned Op : {G_LOAD, G_STORE}) { 45 for (auto Ty : {s1, s8, s16, s32, p0}) 46 setAction({Op, Ty}, Legal); 47 setAction({Op, 1, p0}, Legal); 48 } 49 50 for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) { 51 for (auto Ty : {s1, s8, s16}) 52 setAction({Op, Ty}, WidenScalar); 53 setAction({Op, s32}, Legal); 54 } 55 56 for (unsigned Op : {G_SDIV, G_UDIV}) { 57 for (auto Ty : {s8, s16}) 58 // FIXME: We need WidenScalar here, but in the case of targets with 59 // software division we'll also need Libcall afterwards. Treat as Custom 60 // until we have better support for chaining legalization actions. 61 setAction({Op, Ty}, Custom); 62 if (ST.hasDivideInARMMode()) 63 setAction({Op, s32}, Legal); 64 else 65 setAction({Op, s32}, Libcall); 66 } 67 68 // FIXME: Support s8 and s16 as well 69 for (unsigned Op : {G_SREM, G_UREM}) 70 if (ST.hasDivideInARMMode()) 71 setAction({Op, s32}, Lower); 72 else if (ST.isTargetAEABI() || ST.isTargetGNUAEABI() || 73 ST.isTargetMuslAEABI()) 74 setAction({Op, s32}, Custom); 75 else 76 setAction({Op, s32}, Libcall); 77 78 for (unsigned Op : {G_SEXT, G_ZEXT}) { 79 setAction({Op, s32}, Legal); 80 for (auto Ty : {s1, s8, s16}) 81 setAction({Op, 1, Ty}, Legal); 82 } 83 84 setAction({G_GEP, p0}, Legal); 85 setAction({G_GEP, 1, s32}, Legal); 86 87 setAction({G_SELECT, s32}, Legal); 88 setAction({G_SELECT, p0}, Legal); 89 setAction({G_SELECT, 1, s1}, Legal); 90 91 setAction({G_CONSTANT, s32}, Legal); 92 93 setAction({G_ICMP, s1}, Legal); 94 for (auto Ty : {s8, s16}) 95 setAction({G_ICMP, 1, Ty}, WidenScalar); 96 for (auto Ty : {s32, p0}) 97 setAction({G_ICMP, 1, Ty}, Legal); 98 99 if (!ST.useSoftFloat() && ST.hasVFP2()) { 100 setAction({G_FADD, s32}, Legal); 101 setAction({G_FADD, s64}, Legal); 102 103 setAction({G_LOAD, s64}, Legal); 104 setAction({G_STORE, s64}, Legal); 105 } else { 106 for (auto Ty : {s32, s64}) 107 setAction({G_FADD, Ty}, Libcall); 108 } 109 110 for (unsigned Op : {G_FREM, G_FPOW}) 111 for (auto Ty : {s32, s64}) 112 setAction({Op, Ty}, Libcall); 113 114 computeTables(); 115 } 116 117 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI, 118 MachineRegisterInfo &MRI, 119 MachineIRBuilder &MIRBuilder) const { 120 using namespace TargetOpcode; 121 122 switch (MI.getOpcode()) { 123 default: 124 return false; 125 case G_SDIV: 126 case G_UDIV: { 127 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 128 if (Ty != LLT::scalar(16) && Ty != LLT::scalar(8)) 129 return false; 130 131 // We need to widen to 32 bits and then maybe, if the target requires, 132 // transform into a libcall. 133 LegalizerHelper Helper(MIRBuilder.getMF()); 134 135 MachineInstr *NewMI = nullptr; 136 Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) { 137 // Store the new, 32-bit div instruction. 138 if (MI->getOpcode() == G_SDIV || MI->getOpcode() == G_UDIV) 139 NewMI = MI; 140 }); 141 142 auto Result = Helper.widenScalar(MI, 0, LLT::scalar(32)); 143 Helper.MIRBuilder.stopRecordingInsertions(); 144 if (Result == LegalizerHelper::UnableToLegalize) { 145 return false; 146 } 147 assert(NewMI && "Couldn't find widened instruction"); 148 assert((NewMI->getOpcode() == G_SDIV || NewMI->getOpcode() == G_UDIV) && 149 "Unexpected widened instruction"); 150 assert(MRI.getType(NewMI->getOperand(0).getReg()).getSizeInBits() == 32 && 151 "Unexpected type for the widened instruction"); 152 153 Result = Helper.legalizeInstrStep(*NewMI); 154 if (Result == LegalizerHelper::UnableToLegalize) { 155 return false; 156 } 157 return true; 158 } 159 case G_SREM: 160 case G_UREM: { 161 unsigned OriginalResult = MI.getOperand(0).getReg(); 162 auto Size = MRI.getType(OriginalResult).getSizeInBits(); 163 if (Size != 32) 164 return false; 165 166 auto Libcall = 167 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; 168 169 // Our divmod libcalls return a struct containing the quotient and the 170 // remainder. We need to create a virtual register for it. 171 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 172 Type *ArgTy = Type::getInt32Ty(Ctx); 173 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true); 174 auto RetVal = MRI.createGenericVirtualRegister( 175 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout())); 176 177 auto Status = replaceWithLibcall(MI, MIRBuilder, Libcall, {RetVal, RetTy}, 178 {{MI.getOperand(1).getReg(), ArgTy}, 179 {MI.getOperand(2).getReg(), ArgTy}}); 180 if (Status != LegalizerHelper::Legalized) 181 return false; 182 183 // The remainder is the second result of divmod. Split the return value into 184 // a new, unused register for the quotient and the destination of the 185 // original instruction for the remainder. 186 MIRBuilder.buildUnmerge( 187 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult}, 188 RetVal); 189 190 return LegalizerHelper::Legalized; 191 } 192 } 193 } 194