blob: a9c1af3b26fcd569036e0f8ea19485a165fafc32 [file] [log] [blame]
Diana Picus22274932016-11-11 08:27:37 +00001//===- 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"
Diana Picus02e11012017-06-15 10:53:31 +000015#include "ARMCallLowering.h"
Diana Picus7cab0782017-02-17 11:25:17 +000016#include "ARMSubtarget.h"
Diana Picusf53865d2017-04-24 09:12:19 +000017#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Diana Picus02e11012017-06-15 10:53:31 +000018#include "llvm/CodeGen/LowLevelType.h"
Diana Picusf53865d2017-04-24 09:12:19 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000020#include "llvm/CodeGen/TargetOpcodes.h"
Diana Picus22274932016-11-11 08:27:37 +000021#include "llvm/CodeGen/ValueTypes.h"
22#include "llvm/IR/DerivedTypes.h"
23#include "llvm/IR/Type.h"
Diana Picus22274932016-11-11 08:27:37 +000024
25using namespace llvm;
26
Kristof Beylsaf9814a2017-11-07 10:34:34 +000027/// 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
32/// sizes explicitly.
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.
36static void
37addAndInterleaveWithUnsupported(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});
44 }
45}
46
47static LegalizerInfo::SizeAndActionsVec
48widen_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});
58 return result;
59}
60
61static LegalizerInfo::SizeAndActionsVec
Diana Picus734a5e82018-01-10 09:32:01 +000062widen_1_8_16_narrowToLargest(const LegalizerInfo::SizeAndActionsVec &v) {
Kristof Beylsaf9814a2017-11-07 10:34:34 +000063 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;
Diana Picus734a5e82018-01-10 09:32:01 +000071 result.push_back({Largest + 1, LegalizerInfo::NarrowScalar});
Kristof Beylsaf9814a2017-11-07 10:34:34 +000072 return result;
73}
74
Diana Picus3e8851a2017-07-05 11:53:51 +000075static bool AEABI(const ARMSubtarget &ST) {
76 return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
77}
78
Diana Picus7cab0782017-02-17 11:25:17 +000079ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
Diana Picus812caee2016-12-16 12:54:46 +000080 using namespace TargetOpcode;
Diana Picus5a724452016-12-19 14:07:56 +000081
Diana Picus519807f2016-12-19 11:26:31 +000082 const LLT p0 = LLT::pointer(0, 32);
Diana Picus5a724452016-12-19 14:07:56 +000083
Diana Picusd83df5d2017-01-25 08:47:40 +000084 const LLT s1 = LLT::scalar(1);
Diana Picus5a724452016-12-19 14:07:56 +000085 const LLT s8 = LLT::scalar(8);
86 const LLT s16 = LLT::scalar(16);
Diana Picus812caee2016-12-16 12:54:46 +000087 const LLT s32 = LLT::scalar(32);
Diana Picus21c3d8e2017-02-16 09:09:49 +000088 const LLT s64 = LLT::scalar(64);
Diana Picus812caee2016-12-16 12:54:46 +000089
Diana Picusb1fd7842017-07-26 09:25:15 +000090 setAction({G_GLOBAL_VALUE, p0}, Legal);
Diana Picus519807f2016-12-19 11:26:31 +000091 setAction({G_FRAME_INDEX, p0}, Legal);
92
Diana Picusa2b632a2017-02-24 11:28:24 +000093 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);
97 }
Diana Picus519807f2016-12-19 11:26:31 +000098
Diana Picus01964272017-06-07 11:57:30 +000099 for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000100 if (Op != G_ADD)
101 setLegalizeScalarToDifferentSizeStrategy(
102 Op, 0, widenToLargerTypesUnsupportedOtherwise);
Diana Picus9cfbc6d2017-05-11 09:45:57 +0000103 setAction({Op, s32}, Legal);
104 }
Diana Picus812caee2016-12-16 12:54:46 +0000105
Diana Picusb70e88b2017-04-24 08:20:05 +0000106 for (unsigned Op : {G_SDIV, G_UDIV}) {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000107 setLegalizeScalarToDifferentSizeStrategy(Op, 0,
108 widenToLargerTypesUnsupportedOtherwise);
Diana Picusb70e88b2017-04-24 08:20:05 +0000109 if (ST.hasDivideInARMMode())
110 setAction({Op, s32}, Legal);
111 else
112 setAction({Op, s32}, Libcall);
113 }
114
Diana Picusda25d5b2017-07-18 10:07:01 +0000115 for (unsigned Op : {G_SREM, G_UREM}) {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000116 setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
Diana Picus02e11012017-06-15 10:53:31 +0000117 if (ST.hasDivideInARMMode())
118 setAction({Op, s32}, Lower);
Diana Picus3e8851a2017-07-05 11:53:51 +0000119 else if (AEABI(ST))
Diana Picus02e11012017-06-15 10:53:31 +0000120 setAction({Op, s32}, Custom);
121 else
122 setAction({Op, s32}, Libcall);
Diana Picusda25d5b2017-07-18 10:07:01 +0000123 }
Diana Picus02e11012017-06-15 10:53:31 +0000124
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000125 for (unsigned Op : {G_SEXT, G_ZEXT, G_ANYEXT}) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000126 setAction({Op, s32}, Legal);
Diana Picus8b6c6be2017-01-25 08:10:40 +0000127 }
128
Diana Picus28a6d0e2017-12-22 13:05:51 +0000129 setAction({G_INTTOPTR, p0}, Legal);
130 setAction({G_INTTOPTR, 1, s32}, Legal);
131
132 setAction({G_PTRTOINT, s32}, Legal);
133 setAction({G_PTRTOINT, 1, p0}, Legal);
134
Diana Picus2c957302017-10-06 14:30:05 +0000135 for (unsigned Op : {G_ASHR, G_LSHR, G_SHL})
136 setAction({Op, s32}, Legal);
137
Diana Picus8598b172017-02-28 09:02:42 +0000138 setAction({G_GEP, p0}, Legal);
139 setAction({G_GEP, 1, s32}, Legal);
140
Diana Picus7145d222017-06-27 09:19:51 +0000141 setAction({G_SELECT, s32}, Legal);
Diana Picus0e74a132017-06-27 10:29:50 +0000142 setAction({G_SELECT, p0}, Legal);
Diana Picus7145d222017-06-27 09:19:51 +0000143 setAction({G_SELECT, 1, s1}, Legal);
144
Diana Picus87a70672017-07-14 09:46:06 +0000145 setAction({G_BRCOND, s1}, Legal);
146
Diana Picusc768bbe2018-01-04 13:09:14 +0000147 for (auto Ty : {s32, p0})
148 setAction({G_PHI, Ty}, Legal);
149 setLegalizeScalarToDifferentSizeStrategy(
150 G_PHI, 0, widenToLargerTypesUnsupportedOtherwise);
151
Diana Picuse6beac62017-02-28 11:33:46 +0000152 setAction({G_CONSTANT, s32}, Legal);
Diana Picus68773852017-12-22 11:09:18 +0000153 setAction({G_CONSTANT, p0}, Legal);
Diana Picus734a5e82018-01-10 09:32:01 +0000154 setLegalizeScalarToDifferentSizeStrategy(G_CONSTANT, 0,
155 widen_1_8_16_narrowToLargest);
Diana Picuse6beac62017-02-28 11:33:46 +0000156
Diana Picus621894a2017-06-19 09:40:51 +0000157 setAction({G_ICMP, s1}, Legal);
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000158 setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 1,
159 widenToLargerTypesUnsupportedOtherwise);
Diana Picus621894a2017-06-19 09:40:51 +0000160 for (auto Ty : {s32, p0})
161 setAction({G_ICMP, 1, Ty}, Legal);
162
Diana Picusa5bab612017-04-07 09:41:39 +0000163 if (!ST.useSoftFloat() && ST.hasVFP2()) {
Diana Picus01bcfd22018-01-17 15:25:37 +0000164 for (unsigned Op : {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG})
Javed Absar5cde1cc2017-10-30 13:51:56 +0000165 for (auto Ty : {s32, s64})
Diana Picus01bcfd22018-01-17 15:25:37 +0000166 setAction({Op, Ty}, Legal);
Diana Picus7cab0782017-02-17 11:25:17 +0000167
168 setAction({G_LOAD, s64}, Legal);
Diana Picusa2b632a2017-02-24 11:28:24 +0000169 setAction({G_STORE, s64}, Legal);
Diana Picusd0104ea2017-07-06 09:09:33 +0000170
Diana Picusc768bbe2018-01-04 13:09:14 +0000171 setAction({G_PHI, s64}, Legal);
172
Diana Picusd0104ea2017-07-06 09:09:33 +0000173 setAction({G_FCMP, s1}, Legal);
174 setAction({G_FCMP, 1, s32}, Legal);
Diana Picusb57bba82017-07-11 08:50:01 +0000175 setAction({G_FCMP, 1, s64}, Legal);
Diana Picus8ee540c2017-12-18 13:22:28 +0000176
177 setAction({G_MERGE_VALUES, s64}, Legal);
178 setAction({G_MERGE_VALUES, 1, s32}, Legal);
179 setAction({G_UNMERGE_VALUES, s32}, Legal);
180 setAction({G_UNMERGE_VALUES, 1, s64}, Legal);
Diana Picus65ed3642018-01-17 13:34:10 +0000181
182 setAction({G_FPEXT, s64}, Legal);
183 setAction({G_FPEXT, 1, s32}, Legal);
184
185 setAction({G_FPTRUNC, s32}, Legal);
186 setAction({G_FPTRUNC, 1, s64}, Legal);
Diana Picus1314a282017-04-11 10:52:34 +0000187 } else {
Diana Picusc01f7f12017-11-23 13:26:07 +0000188 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
Javed Absar5cde1cc2017-10-30 13:51:56 +0000189 for (auto Ty : {s32, s64})
190 setAction({BinOp, Ty}, Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000191
Diana Picus8f148862018-01-10 10:01:49 +0000192 for (auto Ty : {s32, s64}) {
Diana Picusf949a0a2018-01-10 10:45:34 +0000193 setAction({G_FNEG, Ty}, Lower);
Diana Picus8f148862018-01-10 10:01:49 +0000194 setAction({G_FCONSTANT, Ty}, Custom);
195 }
196
Diana Picusd0104ea2017-07-06 09:09:33 +0000197 setAction({G_FCMP, s1}, Legal);
198 setAction({G_FCMP, 1, s32}, Custom);
Diana Picusb57bba82017-07-11 08:50:01 +0000199 setAction({G_FCMP, 1, s64}, Custom);
Diana Picusd0104ea2017-07-06 09:09:33 +0000200
Diana Picus65ed3642018-01-17 13:34:10 +0000201 setAction({G_FPEXT, s64}, Legal);
202 setAction({G_FPEXT, 1, s32}, Libcall);
203
204 setAction({G_FPTRUNC, s32}, Legal);
205 setAction({G_FPTRUNC, 1, s64}, Libcall);
206
Diana Picusd0104ea2017-07-06 09:09:33 +0000207 if (AEABI(ST))
208 setFCmpLibcallsAEABI();
209 else
210 setFCmpLibcallsGNU();
Diana Picus7cab0782017-02-17 11:25:17 +0000211 }
Diana Picus4fa83c02017-02-08 13:23:04 +0000212
Diana Picuse74243d2018-01-12 11:30:45 +0000213 if (!ST.useSoftFloat() && ST.hasVFP4())
214 for (auto Ty : {s32, s64})
215 setAction({G_FMA, Ty}, Legal);
216 else
217 for (auto Ty : {s32, s64})
218 setAction({G_FMA, Ty}, Libcall);
219
Diana Picus3ff82c82017-04-10 09:27:39 +0000220 for (unsigned Op : {G_FREM, G_FPOW})
221 for (auto Ty : {s32, s64})
222 setAction({Op, Ty}, Libcall);
Diana Picusa5bab612017-04-07 09:41:39 +0000223
Diana Picus22274932016-11-11 08:27:37 +0000224 computeTables();
225}
Diana Picusf53865d2017-04-24 09:12:19 +0000226
Diana Picusd0104ea2017-07-06 09:09:33 +0000227void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
228 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
229 // default-initialized.
230 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
231 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {
232 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}};
233 FCmp32Libcalls[CmpInst::FCMP_OGE] = {
234 {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}};
235 FCmp32Libcalls[CmpInst::FCMP_OGT] = {
236 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}};
237 FCmp32Libcalls[CmpInst::FCMP_OLE] = {
238 {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}};
239 FCmp32Libcalls[CmpInst::FCMP_OLT] = {
240 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
241 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
242 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}};
243 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}};
244 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}};
245 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}};
246 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}};
247 FCmp32Libcalls[CmpInst::FCMP_UNO] = {
248 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
249 FCmp32Libcalls[CmpInst::FCMP_ONE] = {
250 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE},
251 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
252 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {
253 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE},
254 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
Diana Picusb57bba82017-07-11 08:50:01 +0000255
256 FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
257 FCmp64Libcalls[CmpInst::FCMP_OEQ] = {
258 {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE}};
259 FCmp64Libcalls[CmpInst::FCMP_OGE] = {
260 {RTLIB::OGE_F64, CmpInst::BAD_ICMP_PREDICATE}};
261 FCmp64Libcalls[CmpInst::FCMP_OGT] = {
262 {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE}};
263 FCmp64Libcalls[CmpInst::FCMP_OLE] = {
264 {RTLIB::OLE_F64, CmpInst::BAD_ICMP_PREDICATE}};
265 FCmp64Libcalls[CmpInst::FCMP_OLT] = {
266 {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
267 FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
268 FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_EQ}};
269 FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_EQ}};
270 FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_EQ}};
271 FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_EQ}};
272 FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_EQ}};
273 FCmp64Libcalls[CmpInst::FCMP_UNO] = {
274 {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
275 FCmp64Libcalls[CmpInst::FCMP_ONE] = {
276 {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE},
277 {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
278 FCmp64Libcalls[CmpInst::FCMP_UEQ] = {
279 {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE},
280 {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
Diana Picusd0104ea2017-07-06 09:09:33 +0000281}
282
283void ARMLegalizerInfo::setFCmpLibcallsGNU() {
284 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
285 // default-initialized.
286 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
287 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}};
288 FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}};
289 FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}};
290 FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}};
291 FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
292 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
293 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}};
294 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}};
295 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}};
296 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}};
297 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}};
298 FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}};
299 FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT},
300 {RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
301 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ},
302 {RTLIB::UO_F32, CmpInst::ICMP_NE}};
Diana Picusb57bba82017-07-11 08:50:01 +0000303
304 FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
305 FCmp64Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ}};
306 FCmp64Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F64, CmpInst::ICMP_SGE}};
307 FCmp64Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT}};
308 FCmp64Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F64, CmpInst::ICMP_SLE}};
309 FCmp64Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
310 FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
311 FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_SGE}};
312 FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_SGT}};
313 FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SLE}};
314 FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_SLT}};
315 FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_NE}};
316 FCmp64Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F64, CmpInst::ICMP_NE}};
317 FCmp64Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT},
318 {RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
319 FCmp64Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ},
320 {RTLIB::UO_F64, CmpInst::ICMP_NE}};
Diana Picusd0104ea2017-07-06 09:09:33 +0000321}
322
323ARMLegalizerInfo::FCmpLibcallsList
Diana Picusb57bba82017-07-11 08:50:01 +0000324ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
325 unsigned Size) const {
Diana Picusd0104ea2017-07-06 09:09:33 +0000326 assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");
Diana Picusb57bba82017-07-11 08:50:01 +0000327 if (Size == 32)
328 return FCmp32Libcalls[Predicate];
329 if (Size == 64)
330 return FCmp64Libcalls[Predicate];
331 llvm_unreachable("Unsupported size for FCmp predicate");
Diana Picusd0104ea2017-07-06 09:09:33 +0000332}
333
Diana Picusf53865d2017-04-24 09:12:19 +0000334bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
335 MachineRegisterInfo &MRI,
336 MachineIRBuilder &MIRBuilder) const {
337 using namespace TargetOpcode;
338
Diana Picusfc1675e2017-07-05 12:57:24 +0000339 MIRBuilder.setInstr(MI);
Diana Picus8f148862018-01-10 10:01:49 +0000340 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Diana Picusfc1675e2017-07-05 12:57:24 +0000341
Diana Picusf53865d2017-04-24 09:12:19 +0000342 switch (MI.getOpcode()) {
343 default:
344 return false;
Diana Picus02e11012017-06-15 10:53:31 +0000345 case G_SREM:
346 case G_UREM: {
347 unsigned OriginalResult = MI.getOperand(0).getReg();
348 auto Size = MRI.getType(OriginalResult).getSizeInBits();
349 if (Size != 32)
350 return false;
351
352 auto Libcall =
353 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
354
355 // Our divmod libcalls return a struct containing the quotient and the
356 // remainder. We need to create a virtual register for it.
Diana Picus02e11012017-06-15 10:53:31 +0000357 Type *ArgTy = Type::getInt32Ty(Ctx);
358 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
359 auto RetVal = MRI.createGenericVirtualRegister(
360 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout()));
361
Diana Picusfc1675e2017-07-05 12:57:24 +0000362 auto Status = createLibcall(MIRBuilder, Libcall, {RetVal, RetTy},
363 {{MI.getOperand(1).getReg(), ArgTy},
364 {MI.getOperand(2).getReg(), ArgTy}});
Diana Picus02e11012017-06-15 10:53:31 +0000365 if (Status != LegalizerHelper::Legalized)
366 return false;
367
368 // The remainder is the second result of divmod. Split the return value into
369 // a new, unused register for the quotient and the destination of the
370 // original instruction for the remainder.
371 MIRBuilder.buildUnmerge(
372 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult},
373 RetVal);
Diana Picusd0104ea2017-07-06 09:09:33 +0000374 break;
375 }
376 case G_FCMP: {
Diana Picusb57bba82017-07-11 08:50:01 +0000377 assert(MRI.getType(MI.getOperand(2).getReg()) ==
378 MRI.getType(MI.getOperand(3).getReg()) &&
379 "Mismatched operands for G_FCMP");
380 auto OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
Diana Picus02e11012017-06-15 10:53:31 +0000381
Diana Picusd0104ea2017-07-06 09:09:33 +0000382 auto OriginalResult = MI.getOperand(0).getReg();
383 auto Predicate =
384 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
Diana Picusb57bba82017-07-11 08:50:01 +0000385 auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
Diana Picusd0104ea2017-07-06 09:09:33 +0000386
387 if (Libcalls.empty()) {
388 assert((Predicate == CmpInst::FCMP_TRUE ||
389 Predicate == CmpInst::FCMP_FALSE) &&
390 "Predicate needs libcalls, but none specified");
391 MIRBuilder.buildConstant(OriginalResult,
392 Predicate == CmpInst::FCMP_TRUE ? 1 : 0);
Diana Picus443135c2017-07-11 09:43:51 +0000393 MI.eraseFromParent();
Diana Picusd0104ea2017-07-06 09:09:33 +0000394 return true;
395 }
396
Diana Picusb57bba82017-07-11 08:50:01 +0000397 assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");
398 auto *ArgTy = OpSize == 32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
Diana Picusd0104ea2017-07-06 09:09:33 +0000399 auto *RetTy = Type::getInt32Ty(Ctx);
400
401 SmallVector<unsigned, 2> Results;
402 for (auto Libcall : Libcalls) {
403 auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
404 auto Status =
405 createLibcall(MIRBuilder, Libcall.LibcallID, {LibcallResult, RetTy},
406 {{MI.getOperand(2).getReg(), ArgTy},
407 {MI.getOperand(3).getReg(), ArgTy}});
408
409 if (Status != LegalizerHelper::Legalized)
410 return false;
411
412 auto ProcessedResult =
413 Libcalls.size() == 1
414 ? OriginalResult
415 : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult));
416
417 // We have a result, but we need to transform it into a proper 1-bit 0 or
418 // 1, taking into account the different peculiarities of the values
419 // returned by the comparison functions.
420 CmpInst::Predicate ResultPred = Libcall.Predicate;
421 if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) {
422 // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
423 // to keep the types consistent.
424 MIRBuilder.buildTrunc(ProcessedResult, LibcallResult);
425 } else {
426 // We need to compare against 0.
427 assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate");
428 auto Zero = MRI.createGenericVirtualRegister(LLT::scalar(32));
429 MIRBuilder.buildConstant(Zero, 0);
430 MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);
431 }
432 Results.push_back(ProcessedResult);
433 }
434
435 if (Results.size() != 1) {
436 assert(Results.size() == 2 && "Unexpected number of results");
437 MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);
438 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000439 break;
Diana Picus02e11012017-06-15 10:53:31 +0000440 }
Diana Picus8f148862018-01-10 10:01:49 +0000441 case G_FCONSTANT: {
442 // Convert to integer constants, while preserving the binary representation.
443 auto AsInteger =
444 MI.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
445 MIRBuilder.buildConstant(MI.getOperand(0).getReg(),
446 *ConstantInt::get(Ctx, AsInteger));
447 break;
448 }
Diana Picusf53865d2017-04-24 09:12:19 +0000449 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000450
451 MI.eraseFromParent();
452 return true;
Diana Picusf53865d2017-04-24 09:12:19 +0000453}