1 //===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the Machinelegalizer class for ARM.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
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/TargetOpcodes.h"
21 #include "llvm/CodeGen/ValueTypes.h"
22 #include "llvm/IR/DerivedTypes.h"
23 #include "llvm/IR/Type.h"
27 /// FIXME: The following static functions are SizeChangeStrategy functions
28 /// that are meant to temporarily mimic the behaviour of the old legalization
29 /// based on doubling/halving non-legal types as closely as possible. This is
30 /// not entirly possible as only legalizing the types that are exactly a power
31 /// of 2 times the size of the legal types would require specifying all those
33 /// In practice, not specifying those isn't a problem, and the below functions
34 /// should disappear quickly as we add support for legalizing non-power-of-2
35 /// sized types further.
37 addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
38 const LegalizerInfo::SizeAndActionsVec &v) {
39 for (unsigned i = 0; i < v.size(); ++i) {
40 result.push_back(v[i]);
41 if (i + 1 < v[i].first && i + 1 < v.size() &&
42 v[i + 1].first != v[i].first + 1)
43 result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
47 static LegalizerInfo::SizeAndActionsVec
48 widen_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
49 assert(v.size() >= 1);
50 assert(v[0].first > 17);
51 LegalizerInfo::SizeAndActionsVec result = {
52 {1, LegalizerInfo::Unsupported},
53 {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},
54 {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};
55 addAndInterleaveWithUnsupported(result, v);
56 auto Largest = result.back().first;
57 result.push_back({Largest + 1, LegalizerInfo::Unsupported});
61 static LegalizerInfo::SizeAndActionsVec
62 widen_1_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
63 assert(v.size() >= 1);
64 assert(v[0].first > 17);
65 LegalizerInfo::SizeAndActionsVec result = {
66 {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},
67 {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},
68 {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};
69 addAndInterleaveWithUnsupported(result, v);
70 auto Largest = result.back().first;
71 result.push_back({Largest + 1, LegalizerInfo::Unsupported});
75 static bool AEABI(const ARMSubtarget &ST) {
76 return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
79 ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
80 using namespace TargetOpcode;
82 const LLT p0 = LLT::pointer(0, 32);
84 const LLT s1 = LLT::scalar(1);
85 const LLT s8 = LLT::scalar(8);
86 const LLT s16 = LLT::scalar(16);
87 const LLT s32 = LLT::scalar(32);
88 const LLT s64 = LLT::scalar(64);
90 setAction({G_GLOBAL_VALUE, p0}, Legal);
91 setAction({G_FRAME_INDEX, p0}, Legal);
93 for (unsigned Op : {G_LOAD, G_STORE}) {
94 for (auto Ty : {s1, s8, s16, s32, p0})
95 setAction({Op, Ty}, Legal);
96 setAction({Op, 1, p0}, Legal);
99 for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {
101 setLegalizeScalarToDifferentSizeStrategy(
102 Op, 0, widenToLargerTypesUnsupportedOtherwise);
103 setAction({Op, s32}, Legal);
106 for (unsigned Op : {G_SDIV, G_UDIV}) {
107 setLegalizeScalarToDifferentSizeStrategy(Op, 0,
108 widenToLargerTypesUnsupportedOtherwise);
109 if (ST.hasDivideInARMMode())
110 setAction({Op, s32}, Legal);
112 setAction({Op, s32}, Libcall);
115 for (unsigned Op : {G_SREM, G_UREM}) {
116 setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
117 if (ST.hasDivideInARMMode())
118 setAction({Op, s32}, Lower);
120 setAction({Op, s32}, Custom);
122 setAction({Op, s32}, Libcall);
125 for (unsigned Op : {G_SEXT, G_ZEXT, G_ANYEXT}) {
126 setAction({Op, s32}, Legal);
129 setAction({G_INTTOPTR, p0}, Legal);
130 setAction({G_INTTOPTR, 1, s32}, Legal);
132 setAction({G_PTRTOINT, s32}, Legal);
133 setAction({G_PTRTOINT, 1, p0}, Legal);
135 for (unsigned Op : {G_ASHR, G_LSHR, G_SHL})
136 setAction({Op, s32}, Legal);
138 setAction({G_GEP, p0}, Legal);
139 setAction({G_GEP, 1, s32}, Legal);
141 setAction({G_SELECT, s32}, Legal);
142 setAction({G_SELECT, p0}, Legal);
143 setAction({G_SELECT, 1, s1}, Legal);
145 setAction({G_BRCOND, s1}, Legal);
147 setAction({G_CONSTANT, s32}, Legal);
148 setAction({G_CONSTANT, p0}, Legal);
149 setLegalizeScalarToDifferentSizeStrategy(G_CONSTANT, 0, widen_1_8_16);
151 setAction({G_ICMP, s1}, Legal);
152 setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 1,
153 widenToLargerTypesUnsupportedOtherwise);
154 for (auto Ty : {s32, p0})
155 setAction({G_ICMP, 1, Ty}, Legal);
157 if (!ST.useSoftFloat() && ST.hasVFP2()) {
158 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
159 for (auto Ty : {s32, s64})
160 setAction({BinOp, Ty}, Legal);
162 setAction({G_LOAD, s64}, Legal);
163 setAction({G_STORE, s64}, Legal);
165 setAction({G_FCMP, s1}, Legal);
166 setAction({G_FCMP, 1, s32}, Legal);
167 setAction({G_FCMP, 1, s64}, Legal);
169 setAction({G_MERGE_VALUES, s64}, Legal);
170 setAction({G_MERGE_VALUES, 1, s32}, Legal);
171 setAction({G_UNMERGE_VALUES, s32}, Legal);
172 setAction({G_UNMERGE_VALUES, 1, s64}, Legal);
174 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
175 for (auto Ty : {s32, s64})
176 setAction({BinOp, Ty}, Libcall);
178 setAction({G_FCMP, s1}, Legal);
179 setAction({G_FCMP, 1, s32}, Custom);
180 setAction({G_FCMP, 1, s64}, Custom);
183 setFCmpLibcallsAEABI();
185 setFCmpLibcallsGNU();
188 for (unsigned Op : {G_FREM, G_FPOW})
189 for (auto Ty : {s32, s64})
190 setAction({Op, Ty}, Libcall);
195 void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
196 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
197 // default-initialized.
198 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
199 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {
200 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}};
201 FCmp32Libcalls[CmpInst::FCMP_OGE] = {
202 {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}};
203 FCmp32Libcalls[CmpInst::FCMP_OGT] = {
204 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}};
205 FCmp32Libcalls[CmpInst::FCMP_OLE] = {
206 {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}};
207 FCmp32Libcalls[CmpInst::FCMP_OLT] = {
208 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
209 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
210 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}};
211 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}};
212 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}};
213 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}};
214 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}};
215 FCmp32Libcalls[CmpInst::FCMP_UNO] = {
216 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
217 FCmp32Libcalls[CmpInst::FCMP_ONE] = {
218 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE},
219 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
220 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {
221 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE},
222 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
224 FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
225 FCmp64Libcalls[CmpInst::FCMP_OEQ] = {
226 {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE}};
227 FCmp64Libcalls[CmpInst::FCMP_OGE] = {
228 {RTLIB::OGE_F64, CmpInst::BAD_ICMP_PREDICATE}};
229 FCmp64Libcalls[CmpInst::FCMP_OGT] = {
230 {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE}};
231 FCmp64Libcalls[CmpInst::FCMP_OLE] = {
232 {RTLIB::OLE_F64, CmpInst::BAD_ICMP_PREDICATE}};
233 FCmp64Libcalls[CmpInst::FCMP_OLT] = {
234 {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
235 FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
236 FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_EQ}};
237 FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_EQ}};
238 FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_EQ}};
239 FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_EQ}};
240 FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_EQ}};
241 FCmp64Libcalls[CmpInst::FCMP_UNO] = {
242 {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
243 FCmp64Libcalls[CmpInst::FCMP_ONE] = {
244 {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE},
245 {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
246 FCmp64Libcalls[CmpInst::FCMP_UEQ] = {
247 {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE},
248 {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
251 void ARMLegalizerInfo::setFCmpLibcallsGNU() {
252 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
253 // default-initialized.
254 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
255 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}};
256 FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}};
257 FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}};
258 FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}};
259 FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
260 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
261 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}};
262 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}};
263 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}};
264 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}};
265 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}};
266 FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}};
267 FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT},
268 {RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
269 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ},
270 {RTLIB::UO_F32, CmpInst::ICMP_NE}};
272 FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
273 FCmp64Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ}};
274 FCmp64Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F64, CmpInst::ICMP_SGE}};
275 FCmp64Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT}};
276 FCmp64Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F64, CmpInst::ICMP_SLE}};
277 FCmp64Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
278 FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
279 FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_SGE}};
280 FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_SGT}};
281 FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SLE}};
282 FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_SLT}};
283 FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_NE}};
284 FCmp64Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F64, CmpInst::ICMP_NE}};
285 FCmp64Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT},
286 {RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
287 FCmp64Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ},
288 {RTLIB::UO_F64, CmpInst::ICMP_NE}};
291 ARMLegalizerInfo::FCmpLibcallsList
292 ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
293 unsigned Size) const {
294 assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");
296 return FCmp32Libcalls[Predicate];
298 return FCmp64Libcalls[Predicate];
299 llvm_unreachable("Unsupported size for FCmp predicate");
302 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
303 MachineRegisterInfo &MRI,
304 MachineIRBuilder &MIRBuilder) const {
305 using namespace TargetOpcode;
307 MIRBuilder.setInstr(MI);
309 switch (MI.getOpcode()) {
314 unsigned OriginalResult = MI.getOperand(0).getReg();
315 auto Size = MRI.getType(OriginalResult).getSizeInBits();
320 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
322 // Our divmod libcalls return a struct containing the quotient and the
323 // remainder. We need to create a virtual register for it.
324 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
325 Type *ArgTy = Type::getInt32Ty(Ctx);
326 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
327 auto RetVal = MRI.createGenericVirtualRegister(
328 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout()));
330 auto Status = createLibcall(MIRBuilder, Libcall, {RetVal, RetTy},
331 {{MI.getOperand(1).getReg(), ArgTy},
332 {MI.getOperand(2).getReg(), ArgTy}});
333 if (Status != LegalizerHelper::Legalized)
336 // The remainder is the second result of divmod. Split the return value into
337 // a new, unused register for the quotient and the destination of the
338 // original instruction for the remainder.
339 MIRBuilder.buildUnmerge(
340 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult},
345 assert(MRI.getType(MI.getOperand(2).getReg()) ==
346 MRI.getType(MI.getOperand(3).getReg()) &&
347 "Mismatched operands for G_FCMP");
348 auto OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
350 auto OriginalResult = MI.getOperand(0).getReg();
352 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
353 auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
355 if (Libcalls.empty()) {
356 assert((Predicate == CmpInst::FCMP_TRUE ||
357 Predicate == CmpInst::FCMP_FALSE) &&
358 "Predicate needs libcalls, but none specified");
359 MIRBuilder.buildConstant(OriginalResult,
360 Predicate == CmpInst::FCMP_TRUE ? 1 : 0);
361 MI.eraseFromParent();
365 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
366 assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");
367 auto *ArgTy = OpSize == 32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
368 auto *RetTy = Type::getInt32Ty(Ctx);
370 SmallVector<unsigned, 2> Results;
371 for (auto Libcall : Libcalls) {
372 auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
374 createLibcall(MIRBuilder, Libcall.LibcallID, {LibcallResult, RetTy},
375 {{MI.getOperand(2).getReg(), ArgTy},
376 {MI.getOperand(3).getReg(), ArgTy}});
378 if (Status != LegalizerHelper::Legalized)
381 auto ProcessedResult =
384 : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult));
386 // We have a result, but we need to transform it into a proper 1-bit 0 or
387 // 1, taking into account the different peculiarities of the values
388 // returned by the comparison functions.
389 CmpInst::Predicate ResultPred = Libcall.Predicate;
390 if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) {
391 // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
392 // to keep the types consistent.
393 MIRBuilder.buildTrunc(ProcessedResult, LibcallResult);
395 // We need to compare against 0.
396 assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate");
397 auto Zero = MRI.createGenericVirtualRegister(LLT::scalar(32));
398 MIRBuilder.buildConstant(Zero, 0);
399 MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);
401 Results.push_back(ProcessedResult);
404 if (Results.size() != 1) {
405 assert(Results.size() == 2 && "Unexpected number of results");
406 MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);
412 MI.eraseFromParent();