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