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