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 static bool AEABI(const ARMSubtarget &ST) { 32 return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI(); 33 } 34 35 ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { 36 using namespace TargetOpcode; 37 38 const LLT p0 = LLT::pointer(0, 32); 39 40 const LLT s1 = LLT::scalar(1); 41 const LLT s8 = LLT::scalar(8); 42 const LLT s16 = LLT::scalar(16); 43 const LLT s32 = LLT::scalar(32); 44 const LLT s64 = LLT::scalar(64); 45 46 setAction({G_FRAME_INDEX, p0}, Legal); 47 48 for (unsigned Op : {G_LOAD, G_STORE}) { 49 for (auto Ty : {s1, s8, s16, s32, p0}) 50 setAction({Op, Ty}, Legal); 51 setAction({Op, 1, p0}, Legal); 52 } 53 54 for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) { 55 for (auto Ty : {s1, s8, s16}) 56 setAction({Op, Ty}, WidenScalar); 57 setAction({Op, s32}, Legal); 58 } 59 60 for (unsigned Op : {G_SDIV, G_UDIV}) { 61 for (auto Ty : {s8, s16}) 62 setAction({Op, Ty}, WidenScalar); 63 if (ST.hasDivideInARMMode()) 64 setAction({Op, s32}, Legal); 65 else 66 setAction({Op, s32}, Libcall); 67 } 68 69 // FIXME: Support s8 and s16 as well 70 for (unsigned Op : {G_SREM, G_UREM}) 71 if (ST.hasDivideInARMMode()) 72 setAction({Op, s32}, Lower); 73 else if (AEABI(ST)) 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 for (auto Ty : {s1, s8, s16}) 93 setAction({G_CONSTANT, Ty}, WidenScalar); 94 95 setAction({G_ICMP, s1}, Legal); 96 for (auto Ty : {s8, s16}) 97 setAction({G_ICMP, 1, Ty}, WidenScalar); 98 for (auto Ty : {s32, p0}) 99 setAction({G_ICMP, 1, Ty}, Legal); 100 101 if (!ST.useSoftFloat() && ST.hasVFP2()) { 102 setAction({G_FADD, s32}, Legal); 103 setAction({G_FADD, s64}, Legal); 104 105 setAction({G_LOAD, s64}, Legal); 106 setAction({G_STORE, s64}, Legal); 107 108 setAction({G_FCMP, s1}, Legal); 109 setAction({G_FCMP, 1, s32}, Legal); 110 } else { 111 for (auto Ty : {s32, s64}) 112 setAction({G_FADD, Ty}, Libcall); 113 114 setAction({G_FCMP, s1}, Legal); 115 setAction({G_FCMP, 1, s32}, Custom); 116 117 if (AEABI(ST)) 118 setFCmpLibcallsAEABI(); 119 else 120 setFCmpLibcallsGNU(); 121 } 122 123 for (unsigned Op : {G_FREM, G_FPOW}) 124 for (auto Ty : {s32, s64}) 125 setAction({Op, Ty}, Libcall); 126 127 computeTables(); 128 } 129 130 void ARMLegalizerInfo::setFCmpLibcallsAEABI() { 131 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be 132 // default-initialized. 133 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1); 134 FCmp32Libcalls[CmpInst::FCMP_OEQ] = { 135 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}}; 136 FCmp32Libcalls[CmpInst::FCMP_OGE] = { 137 {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}}; 138 FCmp32Libcalls[CmpInst::FCMP_OGT] = { 139 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}}; 140 FCmp32Libcalls[CmpInst::FCMP_OLE] = { 141 {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}}; 142 FCmp32Libcalls[CmpInst::FCMP_OLT] = { 143 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}}; 144 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}}; 145 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}}; 146 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}}; 147 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}}; 148 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}}; 149 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}}; 150 FCmp32Libcalls[CmpInst::FCMP_UNO] = { 151 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}}; 152 FCmp32Libcalls[CmpInst::FCMP_ONE] = { 153 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}, 154 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}}; 155 FCmp32Libcalls[CmpInst::FCMP_UEQ] = { 156 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}, 157 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}}; 158 } 159 160 void ARMLegalizerInfo::setFCmpLibcallsGNU() { 161 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be 162 // default-initialized. 163 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1); 164 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}}; 165 FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}}; 166 FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}}; 167 FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}}; 168 FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}}; 169 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}}; 170 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}}; 171 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}}; 172 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}}; 173 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}}; 174 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}}; 175 FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}}; 176 FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}, 177 {RTLIB::OLT_F32, CmpInst::ICMP_SLT}}; 178 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}, 179 {RTLIB::UO_F32, CmpInst::ICMP_NE}}; 180 } 181 182 ARMLegalizerInfo::FCmpLibcallsList 183 ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate) const { 184 assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate"); 185 return FCmp32Libcalls[Predicate]; 186 } 187 188 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI, 189 MachineRegisterInfo &MRI, 190 MachineIRBuilder &MIRBuilder) const { 191 using namespace TargetOpcode; 192 193 MIRBuilder.setInstr(MI); 194 195 switch (MI.getOpcode()) { 196 default: 197 return false; 198 case G_SREM: 199 case G_UREM: { 200 unsigned OriginalResult = MI.getOperand(0).getReg(); 201 auto Size = MRI.getType(OriginalResult).getSizeInBits(); 202 if (Size != 32) 203 return false; 204 205 auto Libcall = 206 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; 207 208 // Our divmod libcalls return a struct containing the quotient and the 209 // remainder. We need to create a virtual register for it. 210 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 211 Type *ArgTy = Type::getInt32Ty(Ctx); 212 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true); 213 auto RetVal = MRI.createGenericVirtualRegister( 214 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout())); 215 216 auto Status = createLibcall(MIRBuilder, Libcall, {RetVal, RetTy}, 217 {{MI.getOperand(1).getReg(), ArgTy}, 218 {MI.getOperand(2).getReg(), ArgTy}}); 219 if (Status != LegalizerHelper::Legalized) 220 return false; 221 222 // The remainder is the second result of divmod. Split the return value into 223 // a new, unused register for the quotient and the destination of the 224 // original instruction for the remainder. 225 MIRBuilder.buildUnmerge( 226 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult}, 227 RetVal); 228 break; 229 } 230 case G_FCMP: { 231 assert(MRI.getType(MI.getOperand(2).getReg()).getSizeInBits() == 32 && 232 "Unsupported size for FCMP"); 233 assert(MRI.getType(MI.getOperand(3).getReg()).getSizeInBits() == 32 && 234 "Unsupported size for FCMP"); 235 236 auto OriginalResult = MI.getOperand(0).getReg(); 237 auto Predicate = 238 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()); 239 auto Libcalls = getFCmpLibcalls(Predicate); 240 241 if (Libcalls.empty()) { 242 assert((Predicate == CmpInst::FCMP_TRUE || 243 Predicate == CmpInst::FCMP_FALSE) && 244 "Predicate needs libcalls, but none specified"); 245 MIRBuilder.buildConstant(OriginalResult, 246 Predicate == CmpInst::FCMP_TRUE ? 1 : 0); 247 return true; 248 } 249 250 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 251 auto *ArgTy = Type::getFloatTy(Ctx); 252 auto *RetTy = Type::getInt32Ty(Ctx); 253 254 SmallVector<unsigned, 2> Results; 255 for (auto Libcall : Libcalls) { 256 auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32)); 257 auto Status = 258 createLibcall(MIRBuilder, Libcall.LibcallID, {LibcallResult, RetTy}, 259 {{MI.getOperand(2).getReg(), ArgTy}, 260 {MI.getOperand(3).getReg(), ArgTy}}); 261 262 if (Status != LegalizerHelper::Legalized) 263 return false; 264 265 auto ProcessedResult = 266 Libcalls.size() == 1 267 ? OriginalResult 268 : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult)); 269 270 // We have a result, but we need to transform it into a proper 1-bit 0 or 271 // 1, taking into account the different peculiarities of the values 272 // returned by the comparison functions. 273 CmpInst::Predicate ResultPred = Libcall.Predicate; 274 if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) { 275 // We have a nice 0 or 1, and we just need to truncate it back to 1 bit 276 // to keep the types consistent. 277 MIRBuilder.buildTrunc(ProcessedResult, LibcallResult); 278 } else { 279 // We need to compare against 0. 280 assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate"); 281 auto Zero = MRI.createGenericVirtualRegister(LLT::scalar(32)); 282 MIRBuilder.buildConstant(Zero, 0); 283 MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero); 284 } 285 Results.push_back(ProcessedResult); 286 } 287 288 if (Results.size() != 1) { 289 assert(Results.size() == 2 && "Unexpected number of results"); 290 MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]); 291 } 292 break; 293 } 294 } 295 296 MI.eraseFromParent(); 297 return true; 298 } 299