xref: /llvm-project/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp (revision d0104eaae8ada01ffbbafe4ec54378f16fb4d294)
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