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 setAction({Op, Ty}, WidenScalar); 59 if (ST.hasDivideInARMMode()) 60 setAction({Op, s32}, Legal); 61 else 62 setAction({Op, s32}, Libcall); 63 } 64 65 // FIXME: Support s8 and s16 as well 66 for (unsigned Op : {G_SREM, G_UREM}) 67 if (ST.hasDivideInARMMode()) 68 setAction({Op, s32}, Lower); 69 else if (ST.isTargetAEABI() || ST.isTargetGNUAEABI() || 70 ST.isTargetMuslAEABI()) 71 setAction({Op, s32}, Custom); 72 else 73 setAction({Op, s32}, Libcall); 74 75 for (unsigned Op : {G_SEXT, G_ZEXT}) { 76 setAction({Op, s32}, Legal); 77 for (auto Ty : {s1, s8, s16}) 78 setAction({Op, 1, Ty}, Legal); 79 } 80 81 setAction({G_GEP, p0}, Legal); 82 setAction({G_GEP, 1, s32}, Legal); 83 84 setAction({G_SELECT, s32}, Legal); 85 setAction({G_SELECT, p0}, Legal); 86 setAction({G_SELECT, 1, s1}, Legal); 87 88 setAction({G_CONSTANT, s32}, Legal); 89 90 setAction({G_ICMP, s1}, Legal); 91 for (auto Ty : {s8, s16}) 92 setAction({G_ICMP, 1, Ty}, WidenScalar); 93 for (auto Ty : {s32, p0}) 94 setAction({G_ICMP, 1, Ty}, Legal); 95 96 if (!ST.useSoftFloat() && ST.hasVFP2()) { 97 setAction({G_FADD, s32}, Legal); 98 setAction({G_FADD, s64}, Legal); 99 100 setAction({G_LOAD, s64}, Legal); 101 setAction({G_STORE, s64}, Legal); 102 } else { 103 for (auto Ty : {s32, s64}) 104 setAction({G_FADD, Ty}, Libcall); 105 } 106 107 for (unsigned Op : {G_FREM, G_FPOW}) 108 for (auto Ty : {s32, s64}) 109 setAction({Op, Ty}, Libcall); 110 111 computeTables(); 112 } 113 114 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI, 115 MachineRegisterInfo &MRI, 116 MachineIRBuilder &MIRBuilder) const { 117 using namespace TargetOpcode; 118 119 switch (MI.getOpcode()) { 120 default: 121 return false; 122 case G_SREM: 123 case G_UREM: { 124 unsigned OriginalResult = MI.getOperand(0).getReg(); 125 auto Size = MRI.getType(OriginalResult).getSizeInBits(); 126 if (Size != 32) 127 return false; 128 129 auto Libcall = 130 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; 131 132 // Our divmod libcalls return a struct containing the quotient and the 133 // remainder. We need to create a virtual register for it. 134 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 135 Type *ArgTy = Type::getInt32Ty(Ctx); 136 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true); 137 auto RetVal = MRI.createGenericVirtualRegister( 138 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout())); 139 140 auto Status = replaceWithLibcall(MI, MIRBuilder, Libcall, {RetVal, RetTy}, 141 {{MI.getOperand(1).getReg(), ArgTy}, 142 {MI.getOperand(2).getReg(), ArgTy}}); 143 if (Status != LegalizerHelper::Legalized) 144 return false; 145 146 // The remainder is the second result of divmod. Split the return value into 147 // a new, unused register for the quotient and the destination of the 148 // original instruction for the remainder. 149 MIRBuilder.buildUnmerge( 150 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult}, 151 RetVal); 152 153 return LegalizerHelper::Legalized; 154 } 155 } 156 } 157