blob: 8cff1f0869d0da0e127c0dc8d62f2c8b31adff7c [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
62widen_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});
72 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 Picuse6beac62017-02-28 11:33:46 +0000147 setAction({G_CONSTANT, s32}, Legal);
Diana Picus68773852017-12-22 11:09:18 +0000148 setAction({G_CONSTANT, p0}, Legal);
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000149 setLegalizeScalarToDifferentSizeStrategy(G_CONSTANT, 0, widen_1_8_16);
Diana Picuse6beac62017-02-28 11:33:46 +0000150
Diana Picus621894a2017-06-19 09:40:51 +0000151 setAction({G_ICMP, s1}, Legal);
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000152 setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 1,
153 widenToLargerTypesUnsupportedOtherwise);
Diana Picus621894a2017-06-19 09:40:51 +0000154 for (auto Ty : {s32, p0})
155 setAction({G_ICMP, 1, Ty}, Legal);
156
Diana Picusa5bab612017-04-07 09:41:39 +0000157 if (!ST.useSoftFloat() && ST.hasVFP2()) {
Diana Picusc01f7f12017-11-23 13:26:07 +0000158 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
Javed Absar5cde1cc2017-10-30 13:51:56 +0000159 for (auto Ty : {s32, s64})
160 setAction({BinOp, Ty}, Legal);
Diana Picus7cab0782017-02-17 11:25:17 +0000161
162 setAction({G_LOAD, s64}, Legal);
Diana Picusa2b632a2017-02-24 11:28:24 +0000163 setAction({G_STORE, s64}, Legal);
Diana Picusd0104ea2017-07-06 09:09:33 +0000164
165 setAction({G_FCMP, s1}, Legal);
166 setAction({G_FCMP, 1, s32}, Legal);
Diana Picusb57bba82017-07-11 08:50:01 +0000167 setAction({G_FCMP, 1, s64}, Legal);
Diana Picus8ee540c2017-12-18 13:22:28 +0000168
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);
Diana Picus1314a282017-04-11 10:52:34 +0000173 } else {
Diana Picusc01f7f12017-11-23 13:26:07 +0000174 for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
Javed Absar5cde1cc2017-10-30 13:51:56 +0000175 for (auto Ty : {s32, s64})
176 setAction({BinOp, Ty}, Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000177
178 setAction({G_FCMP, s1}, Legal);
179 setAction({G_FCMP, 1, s32}, Custom);
Diana Picusb57bba82017-07-11 08:50:01 +0000180 setAction({G_FCMP, 1, s64}, Custom);
Diana Picusd0104ea2017-07-06 09:09:33 +0000181
182 if (AEABI(ST))
183 setFCmpLibcallsAEABI();
184 else
185 setFCmpLibcallsGNU();
Diana Picus7cab0782017-02-17 11:25:17 +0000186 }
Diana Picus4fa83c02017-02-08 13:23:04 +0000187
Diana Picus3ff82c82017-04-10 09:27:39 +0000188 for (unsigned Op : {G_FREM, G_FPOW})
189 for (auto Ty : {s32, s64})
190 setAction({Op, Ty}, Libcall);
Diana Picusa5bab612017-04-07 09:41:39 +0000191
Diana Picus22274932016-11-11 08:27:37 +0000192 computeTables();
193}
Diana Picusf53865d2017-04-24 09:12:19 +0000194
Diana Picusd0104ea2017-07-06 09:09:33 +0000195void 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}};
Diana Picusb57bba82017-07-11 08:50:01 +0000223
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}};
Diana Picusd0104ea2017-07-06 09:09:33 +0000249}
250
251void 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}};
Diana Picusb57bba82017-07-11 08:50:01 +0000271
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}};
Diana Picusd0104ea2017-07-06 09:09:33 +0000289}
290
291ARMLegalizerInfo::FCmpLibcallsList
Diana Picusb57bba82017-07-11 08:50:01 +0000292ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
293 unsigned Size) const {
Diana Picusd0104ea2017-07-06 09:09:33 +0000294 assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");
Diana Picusb57bba82017-07-11 08:50:01 +0000295 if (Size == 32)
296 return FCmp32Libcalls[Predicate];
297 if (Size == 64)
298 return FCmp64Libcalls[Predicate];
299 llvm_unreachable("Unsupported size for FCmp predicate");
Diana Picusd0104ea2017-07-06 09:09:33 +0000300}
301
Diana Picusf53865d2017-04-24 09:12:19 +0000302bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
303 MachineRegisterInfo &MRI,
304 MachineIRBuilder &MIRBuilder) const {
305 using namespace TargetOpcode;
306
Diana Picusfc1675e2017-07-05 12:57:24 +0000307 MIRBuilder.setInstr(MI);
308
Diana Picusf53865d2017-04-24 09:12:19 +0000309 switch (MI.getOpcode()) {
310 default:
311 return false;
Diana Picus02e11012017-06-15 10:53:31 +0000312 case G_SREM:
313 case G_UREM: {
314 unsigned OriginalResult = MI.getOperand(0).getReg();
315 auto Size = MRI.getType(OriginalResult).getSizeInBits();
316 if (Size != 32)
317 return false;
318
319 auto Libcall =
320 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
321
322 // Our divmod libcalls return a struct containing the quotient and the
323 // remainder. We need to create a virtual register for it.
Matthias Braunf1caa282017-12-15 22:22:58 +0000324 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Diana Picus02e11012017-06-15 10:53:31 +0000325 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()));
329
Diana Picusfc1675e2017-07-05 12:57:24 +0000330 auto Status = createLibcall(MIRBuilder, Libcall, {RetVal, RetTy},
331 {{MI.getOperand(1).getReg(), ArgTy},
332 {MI.getOperand(2).getReg(), ArgTy}});
Diana Picus02e11012017-06-15 10:53:31 +0000333 if (Status != LegalizerHelper::Legalized)
334 return false;
335
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},
341 RetVal);
Diana Picusd0104ea2017-07-06 09:09:33 +0000342 break;
343 }
344 case G_FCMP: {
Diana Picusb57bba82017-07-11 08:50:01 +0000345 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();
Diana Picus02e11012017-06-15 10:53:31 +0000349
Diana Picusd0104ea2017-07-06 09:09:33 +0000350 auto OriginalResult = MI.getOperand(0).getReg();
351 auto Predicate =
352 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
Diana Picusb57bba82017-07-11 08:50:01 +0000353 auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
Diana Picusd0104ea2017-07-06 09:09:33 +0000354
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);
Diana Picus443135c2017-07-11 09:43:51 +0000361 MI.eraseFromParent();
Diana Picusd0104ea2017-07-06 09:09:33 +0000362 return true;
363 }
364
Matthias Braunf1caa282017-12-15 22:22:58 +0000365 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Diana Picusb57bba82017-07-11 08:50:01 +0000366 assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");
367 auto *ArgTy = OpSize == 32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
Diana Picusd0104ea2017-07-06 09:09:33 +0000368 auto *RetTy = Type::getInt32Ty(Ctx);
369
370 SmallVector<unsigned, 2> Results;
371 for (auto Libcall : Libcalls) {
372 auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
373 auto Status =
374 createLibcall(MIRBuilder, Libcall.LibcallID, {LibcallResult, RetTy},
375 {{MI.getOperand(2).getReg(), ArgTy},
376 {MI.getOperand(3).getReg(), ArgTy}});
377
378 if (Status != LegalizerHelper::Legalized)
379 return false;
380
381 auto ProcessedResult =
382 Libcalls.size() == 1
383 ? OriginalResult
384 : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult));
385
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);
394 } else {
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);
400 }
401 Results.push_back(ProcessedResult);
402 }
403
404 if (Results.size() != 1) {
405 assert(Results.size() == 2 && "Unexpected number of results");
406 MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);
407 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000408 break;
Diana Picus02e11012017-06-15 10:53:31 +0000409 }
Diana Picusf53865d2017-04-24 09:12:19 +0000410 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000411
412 MI.eraseFromParent();
413 return true;
Diana Picusf53865d2017-04-24 09:12:19 +0000414}