Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
/// This file implements the targeting of the Machinelegalizer class for ARM.
10
/// \todo This should be generated by TableGen.
11
//===----------------------------------------------------------------------===//
12
13
#include "ARMLegalizerInfo.h"
14
#include "ARMCallLowering.h"
15
#include "ARMSubtarget.h"
16
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17
#include "llvm/CodeGen/LowLevelType.h"
18
#include "llvm/CodeGen/MachineRegisterInfo.h"
19
#include "llvm/CodeGen/TargetOpcodes.h"
20
#include "llvm/CodeGen/ValueTypes.h"
21
#include "llvm/IR/DerivedTypes.h"
22
#include "llvm/IR/Type.h"
23
24
using namespace llvm;
25
using namespace LegalizeActions;
26
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
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.
36
static void
37
addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
38
13.4k
                                const LegalizerInfo::SizeAndActionsVec &v) {
39
26.8k
  for (unsigned i = 0; i < v.size(); 
++i13.4k
) {
40
13.4k
    result.push_back(v[i]);
41
13.4k
    if (i + 1 < v[i].first && i + 1 < v.size() &&
42
13.4k
        
v[i + 1].first != v[i].first + 10
)
43
0
      result.push_back({v[i].first + 1, Unsupported});
44
13.4k
  }
45
13.4k
}
46
47
static LegalizerInfo::SizeAndActionsVec
48
13.4k
widen_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
49
13.4k
  assert(v.size() >= 1);
50
13.4k
  assert(v[0].first > 17);
51
13.4k
  LegalizerInfo::SizeAndActionsVec result = {{1, Unsupported},
52
13.4k
                                             {8, WidenScalar},
53
13.4k
                                             {9, Unsupported},
54
13.4k
                                             {16, WidenScalar},
55
13.4k
                                             {17, Unsupported}};
56
13.4k
  addAndInterleaveWithUnsupported(result, v);
57
13.4k
  auto Largest = result.back().first;
58
13.4k
  result.push_back({Largest + 1, Unsupported});
59
13.4k
  return result;
60
13.4k
}
61
62
10.8k
static bool AEABI(const ARMSubtarget &ST) {
63
10.8k
  return ST.isTargetAEABI() || 
ST.isTargetGNUAEABI()7.27k
||
ST.isTargetMuslAEABI()5.21k
;
64
10.8k
}
65
66
7.46k
ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
67
7.46k
  using namespace TargetOpcode;
68
7.46k
69
7.46k
  const LLT p0 = LLT::pointer(0, 32);
70
7.46k
71
7.46k
  const LLT s1 = LLT::scalar(1);
72
7.46k
  const LLT s8 = LLT::scalar(8);
73
7.46k
  const LLT s16 = LLT::scalar(16);
74
7.46k
  const LLT s32 = LLT::scalar(32);
75
7.46k
  const LLT s64 = LLT::scalar(64);
76
7.46k
77
7.46k
  if (ST.isThumb1Only()) {
78
740
    // Thumb1 is not supported yet.
79
740
    computeTables();
80
740
    verify(*ST.getInstrInfo());
81
740
    return;
82
740
  }
83
6.72k
84
6.72k
  getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
85
6.72k
      .legalForCartesianProduct({s8, s16, s32}, {s1, s8, s16});
86
6.72k
87
6.72k
  getActionDefinitionsBuilder({G_MUL, G_AND, G_OR, G_XOR})
88
6.72k
      .legalFor({s32})
89
6.72k
      .minScalar(0, s32);
90
6.72k
91
6.72k
  if (ST.hasNEON())
92
3.76k
    getActionDefinitionsBuilder({G_ADD, G_SUB})
93
3.76k
        .legalFor({s32, s64})
94
3.76k
        .minScalar(0, s32);
95
2.95k
  else
96
2.95k
    getActionDefinitionsBuilder({G_ADD, G_SUB})
97
2.95k
        .legalFor({s32})
98
2.95k
        .minScalar(0, s32);
99
6.72k
100
6.72k
  getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL})
101
6.72k
    .legalFor({{s32, s32}})
102
6.72k
    .minScalar(0, s32)
103
6.72k
    .clampScalar(1, s32, s32);
104
6.72k
105
6.72k
  bool HasHWDivide = (!ST.isThumb() && 
ST.hasDivideInARMMode()3.19k
) ||
106
6.72k
                     
(6.16k
ST.isThumb()6.16k
&&
ST.hasDivideInThumbMode()3.52k
);
107
6.72k
  if (HasHWDivide)
108
2.42k
    getActionDefinitionsBuilder({G_SDIV, G_UDIV})
109
2.42k
        .legalFor({s32})
110
2.42k
        .clampScalar(0, s32, s32);
111
4.29k
  else
112
4.29k
    getActionDefinitionsBuilder({G_SDIV, G_UDIV})
113
4.29k
        .libcallFor({s32})
114
4.29k
        .clampScalar(0, s32, s32);
115
6.72k
116
13.4k
  for (unsigned Op : {G_SREM, G_UREM}) {
117
13.4k
    setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
118
13.4k
    if (HasHWDivide)
119
4.85k
      setAction({Op, s32}, Lower);
120
8.58k
    else if (AEABI(ST))
121
4.54k
      setAction({Op, s32}, Custom);
122
4.04k
    else
123
4.04k
      setAction({Op, s32}, Libcall);
124
13.4k
  }
125
6.72k
126
6.72k
  getActionDefinitionsBuilder(G_INTTOPTR)
127
6.72k
      .legalFor({{p0, s32}})
128
6.72k
      .minScalar(1, s32);
129
6.72k
  getActionDefinitionsBuilder(G_PTRTOINT)
130
6.72k
      .legalFor({{s32, p0}})
131
6.72k
      .minScalar(0, s32);
132
6.72k
133
6.72k
  getActionDefinitionsBuilder(G_CONSTANT)
134
6.72k
      .legalFor({s32, p0})
135
6.72k
      .clampScalar(0, s32, s32);
136
6.72k
137
6.72k
  getActionDefinitionsBuilder(G_ICMP)
138
6.72k
      .legalForCartesianProduct({s1}, {s32, p0})
139
6.72k
      .minScalar(1, s32);
140
6.72k
141
6.72k
  getActionDefinitionsBuilder(G_SELECT)
142
6.72k
      .legalForCartesianProduct({s32, p0}, {s1})
143
6.72k
      .minScalar(0, s32);
144
6.72k
145
6.72k
  // We're keeping these builders around because we'll want to add support for
146
6.72k
  // floating point to them.
147
6.72k
  auto &LoadStoreBuilder = getActionDefinitionsBuilder({G_LOAD, G_STORE})
148
6.72k
                               .legalForTypesWithMemDesc({{s1, p0, 8, 8},
149
6.72k
                                                          {s8, p0, 8, 8},
150
6.72k
                                                          {s16, p0, 16, 8},
151
6.72k
                                                          {s32, p0, 32, 8},
152
6.72k
                                                          {p0, p0, 32, 8}})
153
6.72k
                               .unsupportedIfMemSizeNotPow2();
154
6.72k
155
6.72k
  getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
156
6.72k
  getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
157
6.72k
158
6.72k
  auto &PhiBuilder =
159
6.72k
      getActionDefinitionsBuilder(G_PHI)
160
6.72k
          .legalFor({s32, p0})
161
6.72k
          .minScalar(0, s32);
162
6.72k
163
6.72k
  getActionDefinitionsBuilder(G_GEP)
164
6.72k
      .legalFor({{p0, s32}})
165
6.72k
      .minScalar(1, s32);
166
6.72k
167
6.72k
  getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
168
6.72k
169
6.72k
  if (!ST.useSoftFloat() && 
ST.hasVFP2Base()6.22k
) {
170
4.49k
    getActionDefinitionsBuilder(
171
4.49k
        {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG})
172
4.49k
        .legalFor({s32, s64});
173
4.49k
174
4.49k
    LoadStoreBuilder
175
4.49k
        .legalForTypesWithMemDesc({{s64, p0, 64, 32}})
176
4.49k
        .maxScalar(0, s32);
177
4.49k
    PhiBuilder.legalFor({s64});
178
4.49k
179
4.49k
    getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct({s1},
180
4.49k
                                                                 {s32, s64});
181
4.49k
182
4.49k
    getActionDefinitionsBuilder(G_MERGE_VALUES).legalFor({{s64, s32}});
183
4.49k
    getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});
184
4.49k
185
4.49k
    getActionDefinitionsBuilder(G_FPEXT).legalFor({{s64, s32}});
186
4.49k
    getActionDefinitionsBuilder(G_FPTRUNC).legalFor({{s32, s64}});
187
4.49k
188
4.49k
    getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
189
4.49k
        .legalForCartesianProduct({s32}, {s32, s64});
190
4.49k
    getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
191
4.49k
        .legalForCartesianProduct({s32, s64}, {s32});
192
4.49k
  } else {
193
2.22k
    getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
194
2.22k
        .libcallFor({s32, s64});
195
2.22k
196
2.22k
    LoadStoreBuilder.maxScalar(0, s32);
197
2.22k
198
2.22k
    for (auto Ty : {s32, s64})
199
4.45k
      setAction({G_FNEG, Ty}, Lower);
200
2.22k
201
2.22k
    getActionDefinitionsBuilder(G_FCONSTANT).customFor({s32, s64});
202
2.22k
203
2.22k
    getActionDefinitionsBuilder(G_FCMP).customForCartesianProduct({s1},
204
2.22k
                                                                  {s32, s64});
205
2.22k
206
2.22k
    if (AEABI(ST))
207
1.19k
      setFCmpLibcallsAEABI();
208
1.03k
    else
209
1.03k
      setFCmpLibcallsGNU();
210
2.22k
211
2.22k
    getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s64, s32}});
212
2.22k
    getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s32, s64}});
213
2.22k
214
2.22k
    getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
215
2.22k
        .libcallForCartesianProduct({s32}, {s32, s64});
216
2.22k
    getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
217
2.22k
        .libcallForCartesianProduct({s32, s64}, {s32});
218
2.22k
  }
219
6.72k
220
6.72k
  if (!ST.useSoftFloat() && 
ST.hasVFP4Base()6.22k
)
221
1.78k
    getActionDefinitionsBuilder(G_FMA).legalFor({s32, s64});
222
4.93k
  else
223
4.93k
    getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64});
224
6.72k
225
6.72k
  getActionDefinitionsBuilder({G_FREM, G_FPOW}).libcallFor({s32, s64});
226
6.72k
227
6.72k
  if (ST.hasV5TOps()) {
228
5.51k
    getActionDefinitionsBuilder(G_CTLZ)
229
5.51k
        .legalFor({s32, s32})
230
5.51k
        .clampScalar(1, s32, s32)
231
5.51k
        .clampScalar(0, s32, s32);
232
5.51k
    getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
233
5.51k
        .lowerFor({s32, s32})
234
5.51k
        .clampScalar(1, s32, s32)
235
5.51k
        .clampScalar(0, s32, s32);
236
5.51k
  } else {
237
1.20k
    getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
238
1.20k
        .libcallFor({s32, s32})
239
1.20k
        .clampScalar(1, s32, s32)
240
1.20k
        .clampScalar(0, s32, s32);
241
1.20k
    getActionDefinitionsBuilder(G_CTLZ)
242
1.20k
        .lowerFor({s32, s32})
243
1.20k
        .clampScalar(1, s32, s32)
244
1.20k
        .clampScalar(0, s32, s32);
245
1.20k
  }
246
6.72k
247
6.72k
  computeTables();
248
6.72k
  verify(*ST.getInstrInfo());
249
6.72k
}
250
251
1.19k
void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
252
1.19k
  // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
253
1.19k
  // default-initialized.
254
1.19k
  FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
255
1.19k
  FCmp32Libcalls[CmpInst::FCMP_OEQ] = {
256
1.19k
      {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}};
257
1.19k
  FCmp32Libcalls[CmpInst::FCMP_OGE] = {
258
1.19k
      {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}};
259
1.19k
  FCmp32Libcalls[CmpInst::FCMP_OGT] = {
260
1.19k
      {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}};
261
1.19k
  FCmp32Libcalls[CmpInst::FCMP_OLE] = {
262
1.19k
      {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}};
263
1.19k
  FCmp32Libcalls[CmpInst::FCMP_OLT] = {
264
1.19k
      {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
265
1.19k
  FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
266
1.19k
  FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}};
267
1.19k
  FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}};
268
1.19k
  FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}};
269
1.19k
  FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}};
270
1.19k
  FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}};
271
1.19k
  FCmp32Libcalls[CmpInst::FCMP_UNO] = {
272
1.19k
      {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
273
1.19k
  FCmp32Libcalls[CmpInst::FCMP_ONE] = {
274
1.19k
      {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE},
275
1.19k
      {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
276
1.19k
  FCmp32Libcalls[CmpInst::FCMP_UEQ] = {
277
1.19k
      {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE},
278
1.19k
      {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
279
1.19k
280
1.19k
  FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
281
1.19k
  FCmp64Libcalls[CmpInst::FCMP_OEQ] = {
282
1.19k
      {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE}};
283
1.19k
  FCmp64Libcalls[CmpInst::FCMP_OGE] = {
284
1.19k
      {RTLIB::OGE_F64, CmpInst::BAD_ICMP_PREDICATE}};
285
1.19k
  FCmp64Libcalls[CmpInst::FCMP_OGT] = {
286
1.19k
      {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE}};
287
1.19k
  FCmp64Libcalls[CmpInst::FCMP_OLE] = {
288
1.19k
      {RTLIB::OLE_F64, CmpInst::BAD_ICMP_PREDICATE}};
289
1.19k
  FCmp64Libcalls[CmpInst::FCMP_OLT] = {
290
1.19k
      {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
291
1.19k
  FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
292
1.19k
  FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_EQ}};
293
1.19k
  FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_EQ}};
294
1.19k
  FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_EQ}};
295
1.19k
  FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_EQ}};
296
1.19k
  FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_EQ}};
297
1.19k
  FCmp64Libcalls[CmpInst::FCMP_UNO] = {
298
1.19k
      {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
299
1.19k
  FCmp64Libcalls[CmpInst::FCMP_ONE] = {
300
1.19k
      {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE},
301
1.19k
      {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
302
1.19k
  FCmp64Libcalls[CmpInst::FCMP_UEQ] = {
303
1.19k
      {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE},
304
1.19k
      {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
305
1.19k
}
306
307
1.03k
void ARMLegalizerInfo::setFCmpLibcallsGNU() {
308
1.03k
  // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
309
1.03k
  // default-initialized.
310
1.03k
  FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
311
1.03k
  FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}};
312
1.03k
  FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}};
313
1.03k
  FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}};
314
1.03k
  FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}};
315
1.03k
  FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
316
1.03k
  FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
317
1.03k
  FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}};
318
1.03k
  FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}};
319
1.03k
  FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}};
320
1.03k
  FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}};
321
1.03k
  FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}};
322
1.03k
  FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}};
323
1.03k
  FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT},
324
1.03k
                                       {RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
325
1.03k
  FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ},
326
1.03k
                                       {RTLIB::UO_F32, CmpInst::ICMP_NE}};
327
1.03k
328
1.03k
  FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
329
1.03k
  FCmp64Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ}};
330
1.03k
  FCmp64Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F64, CmpInst::ICMP_SGE}};
331
1.03k
  FCmp64Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT}};
332
1.03k
  FCmp64Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F64, CmpInst::ICMP_SLE}};
333
1.03k
  FCmp64Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
334
1.03k
  FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
335
1.03k
  FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_SGE}};
336
1.03k
  FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_SGT}};
337
1.03k
  FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SLE}};
338
1.03k
  FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_SLT}};
339
1.03k
  FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_NE}};
340
1.03k
  FCmp64Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F64, CmpInst::ICMP_NE}};
341
1.03k
  FCmp64Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT},
342
1.03k
                                       {RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
343
1.03k
  FCmp64Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ},
344
1.03k
                                       {RTLIB::UO_F64, CmpInst::ICMP_NE}};
345
1.03k
}
346
347
ARMLegalizerInfo::FCmpLibcallsList
348
ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
349
132
                                  unsigned Size) const {
350
132
  assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");
351
132
  if (Size == 32)
352
68
    return FCmp32Libcalls[Predicate];
353
64
  if (Size == 64)
354
64
    return FCmp64Libcalls[Predicate];
355
0
  llvm_unreachable("Unsupported size for FCmp predicate");
356
0
}
357
358
bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
359
                                      MachineRegisterInfo &MRI,
360
                                      MachineIRBuilder &MIRBuilder,
361
166
                                      GISelChangeObserver &Observer) const {
362
166
  using namespace TargetOpcode;
363
166
364
166
  MIRBuilder.setInstr(MI);
365
166
  LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
366
166
367
166
  switch (MI.getOpcode()) {
368
166
  default:
369
0
    return false;
370
166
  case G_SREM:
371
18
  case G_UREM: {
372
18
    Register OriginalResult = MI.getOperand(0).getReg();
373
18
    auto Size = MRI.getType(OriginalResult).getSizeInBits();
374
18
    if (Size != 32)
375
0
      return false;
376
18
377
18
    auto Libcall =
378
18
        MI.getOpcode() == G_SREM ? 
RTLIB::SDIVREM_I329
:
RTLIB::UDIVREM_I329
;
379
18
380
18
    // Our divmod libcalls return a struct containing the quotient and the
381
18
    // remainder. Create a new, unused register for the quotient and use the
382
18
    // destination of the original instruction for the remainder.
383
18
    Type *ArgTy = Type::getInt32Ty(Ctx);
384
18
    StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
385
18
    Register RetRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
386
18
                          OriginalResult};
387
18
    auto Status = createLibcall(MIRBuilder, Libcall, {RetRegs, RetTy},
388
18
                                {{MI.getOperand(1).getReg(), ArgTy},
389
18
                                 {MI.getOperand(2).getReg(), ArgTy}});
390
18
    if (Status != LegalizerHelper::Legalized)
391
0
      return false;
392
18
    break;
393
18
  }
394
132
  case G_FCMP: {
395
132
    assert(MRI.getType(MI.getOperand(2).getReg()) ==
396
132
               MRI.getType(MI.getOperand(3).getReg()) &&
397
132
           "Mismatched operands for G_FCMP");
398
132
    auto OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
399
132
400
132
    auto OriginalResult = MI.getOperand(0).getReg();
401
132
    auto Predicate =
402
132
        static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
403
132
    auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
404
132
405
132
    if (Libcalls.empty()) {
406
16
      assert((Predicate == CmpInst::FCMP_TRUE ||
407
16
              Predicate == CmpInst::FCMP_FALSE) &&
408
16
             "Predicate needs libcalls, but none specified");
409
16
      MIRBuilder.buildConstant(OriginalResult,
410
16
                               Predicate == CmpInst::FCMP_TRUE ? 
18
:
08
);
411
16
      MI.eraseFromParent();
412
16
      return true;
413
16
    }
414
116
415
116
    assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");
416
116
    auto *ArgTy = OpSize == 32 ? 
Type::getFloatTy(Ctx)60
:
Type::getDoubleTy(Ctx)56
;
417
116
    auto *RetTy = Type::getInt32Ty(Ctx);
418
116
419
116
    SmallVector<Register, 2> Results;
420
134
    for (auto Libcall : Libcalls) {
421
134
      auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
422
134
      auto Status =
423
134
          createLibcall(MIRBuilder, Libcall.LibcallID, {LibcallResult, RetTy},
424
134
                        {{MI.getOperand(2).getReg(), ArgTy},
425
134
                         {MI.getOperand(3).getReg(), ArgTy}});
426
134
427
134
      if (Status != LegalizerHelper::Legalized)
428
0
        return false;
429
134
430
134
      auto ProcessedResult =
431
134
          Libcalls.size() == 1
432
134
              ? 
OriginalResult98
433
134
              : 
MRI.createGenericVirtualRegister(MRI.getType(OriginalResult))36
;
434
134
435
134
      // We have a result, but we need to transform it into a proper 1-bit 0 or
436
134
      // 1, taking into account the different peculiarities of the values
437
134
      // returned by the comparison functions.
438
134
      CmpInst::Predicate ResultPred = Libcall.Predicate;
439
134
      if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) {
440
43
        // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
441
43
        // to keep the types consistent.
442
43
        MIRBuilder.buildTrunc(ProcessedResult, LibcallResult);
443
91
      } else {
444
91
        // We need to compare against 0.
445
91
        assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate");
446
91
        auto Zero = MRI.createGenericVirtualRegister(LLT::scalar(32));
447
91
        MIRBuilder.buildConstant(Zero, 0);
448
91
        MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);
449
91
      }
450
134
      Results.push_back(ProcessedResult);
451
134
    }
452
116
453
116
    if (Results.size() != 1) {
454
18
      assert(Results.size() == 2 && "Unexpected number of results");
455
18
      MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);
456
18
    }
457
116
    break;
458
116
  }
459
116
  case G_FCONSTANT: {
460
16
    // Convert to integer constants, while preserving the binary representation.
461
16
    auto AsInteger =
462
16
        MI.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
463
16
    MIRBuilder.buildConstant(MI.getOperand(0).getReg(),
464
16
                             *ConstantInt::get(Ctx, AsInteger));
465
16
    break;
466
150
  }
467
150
  }
468
150
469
150
  MI.eraseFromParent();
470
150
  return true;
471
150
}