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, 1, s1}, Legal); 89 90 setAction({G_CONSTANT, s32}, Legal); 91 92 setAction({G_ICMP, s1}, Legal); 93 for (auto Ty : {s8, s16}) 94 setAction({G_ICMP, 1, Ty}, WidenScalar); 95 for (auto Ty : {s32, p0}) 96 setAction({G_ICMP, 1, Ty}, Legal); 97 98 if (!ST.useSoftFloat() && ST.hasVFP2()) { 99 setAction({G_FADD, s32}, Legal); 100 setAction({G_FADD, s64}, Legal); 101 102 setAction({G_LOAD, s64}, Legal); 103 setAction({G_STORE, s64}, Legal); 104 } else { 105 for (auto Ty : {s32, s64}) 106 setAction({G_FADD, Ty}, Libcall); 107 } 108 109 for (unsigned Op : {G_FREM, G_FPOW}) 110 for (auto Ty : {s32, s64}) 111 setAction({Op, Ty}, Libcall); 112 113 computeTables(); 114 } 115 116 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI, 117 MachineRegisterInfo &MRI, 118 MachineIRBuilder &MIRBuilder) const { 119 using namespace TargetOpcode; 120 121 switch (MI.getOpcode()) { 122 default: 123 return false; 124 case G_SDIV: 125 case G_UDIV: { 126 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 127 if (Ty != LLT::scalar(16) && Ty != LLT::scalar(8)) 128 return false; 129 130 // We need to widen to 32 bits and then maybe, if the target requires, 131 // transform into a libcall. 132 LegalizerHelper Helper(MIRBuilder.getMF()); 133 134 MachineInstr *NewMI = nullptr; 135 Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) { 136 // Store the new, 32-bit div instruction. 137 if (MI->getOpcode() == G_SDIV || MI->getOpcode() == G_UDIV) 138 NewMI = MI; 139 }); 140 141 auto Result = Helper.widenScalar(MI, 0, LLT::scalar(32)); 142 Helper.MIRBuilder.stopRecordingInsertions(); 143 if (Result == LegalizerHelper::UnableToLegalize) { 144 return false; 145 } 146 assert(NewMI && "Couldn't find widened instruction"); 147 assert((NewMI->getOpcode() == G_SDIV || NewMI->getOpcode() == G_UDIV) && 148 "Unexpected widened instruction"); 149 assert(MRI.getType(NewMI->getOperand(0).getReg()).getSizeInBits() == 32 && 150 "Unexpected type for the widened instruction"); 151 152 Result = Helper.legalizeInstrStep(*NewMI); 153 if (Result == LegalizerHelper::UnableToLegalize) { 154 return false; 155 } 156 return true; 157 } 158 case G_SREM: 159 case G_UREM: { 160 unsigned OriginalResult = MI.getOperand(0).getReg(); 161 auto Size = MRI.getType(OriginalResult).getSizeInBits(); 162 if (Size != 32) 163 return false; 164 165 auto Libcall = 166 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; 167 168 // Our divmod libcalls return a struct containing the quotient and the 169 // remainder. We need to create a virtual register for it. 170 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 171 Type *ArgTy = Type::getInt32Ty(Ctx); 172 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true); 173 auto RetVal = MRI.createGenericVirtualRegister( 174 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout())); 175 176 auto Status = replaceWithLibcall(MI, MIRBuilder, Libcall, {RetVal, RetTy}, 177 {{MI.getOperand(1).getReg(), ArgTy}, 178 {MI.getOperand(2).getReg(), ArgTy}}); 179 if (Status != LegalizerHelper::Legalized) 180 return false; 181 182 // The remainder is the second result of divmod. Split the return value into 183 // a new, unused register for the quotient and the destination of the 184 // original instruction for the remainder. 185 MIRBuilder.buildUnmerge( 186 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult}, 187 RetVal); 188 189 return LegalizerHelper::Legalized; 190 } 191 } 192 } 193