1 //===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements the targeting of the Machinelegalizer class for ARM.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
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"
25 using namespace LegalizeActions
;
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, 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
= {{1, Unsupported
},
56 addAndInterleaveWithUnsupported(result
, v
);
57 auto Largest
= result
.back().first
;
58 result
.push_back({Largest
+ 1, Unsupported
});
62 static bool AEABI(const ARMSubtarget
&ST
) {
63 return ST
.isTargetAEABI() || ST
.isTargetGNUAEABI() || ST
.isTargetMuslAEABI();
66 ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget
&ST
) {
67 using namespace TargetOpcode
;
69 const LLT p0
= LLT::pointer(0, 32);
71 const LLT s1
= LLT::scalar(1);
72 const LLT s8
= LLT::scalar(8);
73 const LLT s16
= LLT::scalar(16);
74 const LLT s32
= LLT::scalar(32);
75 const LLT s64
= LLT::scalar(64);
77 if (ST
.isThumb1Only()) {
78 // Thumb1 is not supported yet.
80 verify(*ST
.getInstrInfo());
84 getActionDefinitionsBuilder({G_SEXT
, G_ZEXT
, G_ANYEXT
})
85 .legalForCartesianProduct({s8
, s16
, s32
}, {s1
, s8
, s16
});
87 getActionDefinitionsBuilder(G_SEXT_INREG
).lower();
89 getActionDefinitionsBuilder({G_MUL
, G_AND
, G_OR
, G_XOR
})
94 getActionDefinitionsBuilder({G_ADD
, G_SUB
})
98 getActionDefinitionsBuilder({G_ADD
, G_SUB
})
102 getActionDefinitionsBuilder({G_ASHR
, G_LSHR
, G_SHL
})
103 .legalFor({{s32
, s32
}})
105 .clampScalar(1, s32
, s32
);
107 bool HasHWDivide
= (!ST
.isThumb() && ST
.hasDivideInARMMode()) ||
108 (ST
.isThumb() && ST
.hasDivideInThumbMode());
110 getActionDefinitionsBuilder({G_SDIV
, G_UDIV
})
112 .clampScalar(0, s32
, s32
);
114 getActionDefinitionsBuilder({G_SDIV
, G_UDIV
})
116 .clampScalar(0, s32
, s32
);
118 for (unsigned Op
: {G_SREM
, G_UREM
}) {
119 setLegalizeScalarToDifferentSizeStrategy(Op
, 0, widen_8_16
);
121 setAction({Op
, s32
}, Lower
);
123 setAction({Op
, s32
}, Custom
);
125 setAction({Op
, s32
}, Libcall
);
128 getActionDefinitionsBuilder(G_INTTOPTR
)
129 .legalFor({{p0
, s32
}})
131 getActionDefinitionsBuilder(G_PTRTOINT
)
132 .legalFor({{s32
, p0
}})
135 getActionDefinitionsBuilder(G_CONSTANT
)
137 .clampScalar(0, s32
, s32
);
139 getActionDefinitionsBuilder(G_ICMP
)
140 .legalForCartesianProduct({s1
}, {s32
, p0
})
143 getActionDefinitionsBuilder(G_SELECT
)
144 .legalForCartesianProduct({s32
, p0
}, {s1
})
147 // We're keeping these builders around because we'll want to add support for
148 // floating point to them.
149 auto &LoadStoreBuilder
= getActionDefinitionsBuilder({G_LOAD
, G_STORE
})
150 .legalForTypesWithMemDesc({{s1
, p0
, 8, 8},
155 .unsupportedIfMemSizeNotPow2();
157 getActionDefinitionsBuilder(G_FRAME_INDEX
).legalFor({p0
});
158 getActionDefinitionsBuilder(G_GLOBAL_VALUE
).legalFor({p0
});
161 getActionDefinitionsBuilder(G_PHI
)
165 getActionDefinitionsBuilder(G_GEP
)
166 .legalFor({{p0
, s32
}})
169 getActionDefinitionsBuilder(G_BRCOND
).legalFor({s1
});
171 if (!ST
.useSoftFloat() && ST
.hasVFP2Base()) {
172 getActionDefinitionsBuilder(
173 {G_FADD
, G_FSUB
, G_FMUL
, G_FDIV
, G_FCONSTANT
, G_FNEG
})
174 .legalFor({s32
, s64
});
177 .legalForTypesWithMemDesc({{s64
, p0
, 64, 32}})
179 PhiBuilder
.legalFor({s64
});
181 getActionDefinitionsBuilder(G_FCMP
).legalForCartesianProduct({s1
},
184 getActionDefinitionsBuilder(G_MERGE_VALUES
).legalFor({{s64
, s32
}});
185 getActionDefinitionsBuilder(G_UNMERGE_VALUES
).legalFor({{s32
, s64
}});
187 getActionDefinitionsBuilder(G_FPEXT
).legalFor({{s64
, s32
}});
188 getActionDefinitionsBuilder(G_FPTRUNC
).legalFor({{s32
, s64
}});
190 getActionDefinitionsBuilder({G_FPTOSI
, G_FPTOUI
})
191 .legalForCartesianProduct({s32
}, {s32
, s64
});
192 getActionDefinitionsBuilder({G_SITOFP
, G_UITOFP
})
193 .legalForCartesianProduct({s32
, s64
}, {s32
});
195 getActionDefinitionsBuilder({G_FADD
, G_FSUB
, G_FMUL
, G_FDIV
})
196 .libcallFor({s32
, s64
});
198 LoadStoreBuilder
.maxScalar(0, s32
);
200 for (auto Ty
: {s32
, s64
})
201 setAction({G_FNEG
, Ty
}, Lower
);
203 getActionDefinitionsBuilder(G_FCONSTANT
).customFor({s32
, s64
});
205 getActionDefinitionsBuilder(G_FCMP
).customForCartesianProduct({s1
},
209 setFCmpLibcallsAEABI();
211 setFCmpLibcallsGNU();
213 getActionDefinitionsBuilder(G_FPEXT
).libcallFor({{s64
, s32
}});
214 getActionDefinitionsBuilder(G_FPTRUNC
).libcallFor({{s32
, s64
}});
216 getActionDefinitionsBuilder({G_FPTOSI
, G_FPTOUI
})
217 .libcallForCartesianProduct({s32
}, {s32
, s64
});
218 getActionDefinitionsBuilder({G_SITOFP
, G_UITOFP
})
219 .libcallForCartesianProduct({s32
, s64
}, {s32
});
222 if (!ST
.useSoftFloat() && ST
.hasVFP4Base())
223 getActionDefinitionsBuilder(G_FMA
).legalFor({s32
, s64
});
225 getActionDefinitionsBuilder(G_FMA
).libcallFor({s32
, s64
});
227 getActionDefinitionsBuilder({G_FREM
, G_FPOW
}).libcallFor({s32
, s64
});
229 if (ST
.hasV5TOps()) {
230 getActionDefinitionsBuilder(G_CTLZ
)
231 .legalFor({s32
, s32
})
232 .clampScalar(1, s32
, s32
)
233 .clampScalar(0, s32
, s32
);
234 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
)
235 .lowerFor({s32
, s32
})
236 .clampScalar(1, s32
, s32
)
237 .clampScalar(0, s32
, s32
);
239 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
)
240 .libcallFor({s32
, s32
})
241 .clampScalar(1, s32
, s32
)
242 .clampScalar(0, s32
, s32
);
243 getActionDefinitionsBuilder(G_CTLZ
)
244 .lowerFor({s32
, s32
})
245 .clampScalar(1, s32
, s32
)
246 .clampScalar(0, s32
, s32
);
250 verify(*ST
.getInstrInfo());
253 void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
254 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
255 // default-initialized.
256 FCmp32Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
257 FCmp32Libcalls
[CmpInst::FCMP_OEQ
] = {
258 {RTLIB::OEQ_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
259 FCmp32Libcalls
[CmpInst::FCMP_OGE
] = {
260 {RTLIB::OGE_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
261 FCmp32Libcalls
[CmpInst::FCMP_OGT
] = {
262 {RTLIB::OGT_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
263 FCmp32Libcalls
[CmpInst::FCMP_OLE
] = {
264 {RTLIB::OLE_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
265 FCmp32Libcalls
[CmpInst::FCMP_OLT
] = {
266 {RTLIB::OLT_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
267 FCmp32Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F32
, CmpInst::ICMP_EQ
}};
268 FCmp32Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F32
, CmpInst::ICMP_EQ
}};
269 FCmp32Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F32
, CmpInst::ICMP_EQ
}};
270 FCmp32Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_EQ
}};
271 FCmp32Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F32
, CmpInst::ICMP_EQ
}};
272 FCmp32Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F32
, CmpInst::ICMP_EQ
}};
273 FCmp32Libcalls
[CmpInst::FCMP_UNO
] = {
274 {RTLIB::UO_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
275 FCmp32Libcalls
[CmpInst::FCMP_ONE
] = {
276 {RTLIB::OGT_F32
, CmpInst::BAD_ICMP_PREDICATE
},
277 {RTLIB::OLT_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
278 FCmp32Libcalls
[CmpInst::FCMP_UEQ
] = {
279 {RTLIB::OEQ_F32
, CmpInst::BAD_ICMP_PREDICATE
},
280 {RTLIB::UO_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
282 FCmp64Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
283 FCmp64Libcalls
[CmpInst::FCMP_OEQ
] = {
284 {RTLIB::OEQ_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
285 FCmp64Libcalls
[CmpInst::FCMP_OGE
] = {
286 {RTLIB::OGE_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
287 FCmp64Libcalls
[CmpInst::FCMP_OGT
] = {
288 {RTLIB::OGT_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
289 FCmp64Libcalls
[CmpInst::FCMP_OLE
] = {
290 {RTLIB::OLE_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
291 FCmp64Libcalls
[CmpInst::FCMP_OLT
] = {
292 {RTLIB::OLT_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
293 FCmp64Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F64
, CmpInst::ICMP_EQ
}};
294 FCmp64Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F64
, CmpInst::ICMP_EQ
}};
295 FCmp64Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F64
, CmpInst::ICMP_EQ
}};
296 FCmp64Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_EQ
}};
297 FCmp64Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F64
, CmpInst::ICMP_EQ
}};
298 FCmp64Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F64
, CmpInst::ICMP_EQ
}};
299 FCmp64Libcalls
[CmpInst::FCMP_UNO
] = {
300 {RTLIB::UO_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
301 FCmp64Libcalls
[CmpInst::FCMP_ONE
] = {
302 {RTLIB::OGT_F64
, CmpInst::BAD_ICMP_PREDICATE
},
303 {RTLIB::OLT_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
304 FCmp64Libcalls
[CmpInst::FCMP_UEQ
] = {
305 {RTLIB::OEQ_F64
, CmpInst::BAD_ICMP_PREDICATE
},
306 {RTLIB::UO_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
309 void ARMLegalizerInfo::setFCmpLibcallsGNU() {
310 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
311 // default-initialized.
312 FCmp32Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
313 FCmp32Libcalls
[CmpInst::FCMP_OEQ
] = {{RTLIB::OEQ_F32
, CmpInst::ICMP_EQ
}};
314 FCmp32Libcalls
[CmpInst::FCMP_OGE
] = {{RTLIB::OGE_F32
, CmpInst::ICMP_SGE
}};
315 FCmp32Libcalls
[CmpInst::FCMP_OGT
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_SGT
}};
316 FCmp32Libcalls
[CmpInst::FCMP_OLE
] = {{RTLIB::OLE_F32
, CmpInst::ICMP_SLE
}};
317 FCmp32Libcalls
[CmpInst::FCMP_OLT
] = {{RTLIB::OLT_F32
, CmpInst::ICMP_SLT
}};
318 FCmp32Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F32
, CmpInst::ICMP_EQ
}};
319 FCmp32Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F32
, CmpInst::ICMP_SGE
}};
320 FCmp32Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F32
, CmpInst::ICMP_SGT
}};
321 FCmp32Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_SLE
}};
322 FCmp32Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F32
, CmpInst::ICMP_SLT
}};
323 FCmp32Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F32
, CmpInst::ICMP_NE
}};
324 FCmp32Libcalls
[CmpInst::FCMP_UNO
] = {{RTLIB::UO_F32
, CmpInst::ICMP_NE
}};
325 FCmp32Libcalls
[CmpInst::FCMP_ONE
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_SGT
},
326 {RTLIB::OLT_F32
, CmpInst::ICMP_SLT
}};
327 FCmp32Libcalls
[CmpInst::FCMP_UEQ
] = {{RTLIB::OEQ_F32
, CmpInst::ICMP_EQ
},
328 {RTLIB::UO_F32
, CmpInst::ICMP_NE
}};
330 FCmp64Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
331 FCmp64Libcalls
[CmpInst::FCMP_OEQ
] = {{RTLIB::OEQ_F64
, CmpInst::ICMP_EQ
}};
332 FCmp64Libcalls
[CmpInst::FCMP_OGE
] = {{RTLIB::OGE_F64
, CmpInst::ICMP_SGE
}};
333 FCmp64Libcalls
[CmpInst::FCMP_OGT
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_SGT
}};
334 FCmp64Libcalls
[CmpInst::FCMP_OLE
] = {{RTLIB::OLE_F64
, CmpInst::ICMP_SLE
}};
335 FCmp64Libcalls
[CmpInst::FCMP_OLT
] = {{RTLIB::OLT_F64
, CmpInst::ICMP_SLT
}};
336 FCmp64Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F64
, CmpInst::ICMP_EQ
}};
337 FCmp64Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F64
, CmpInst::ICMP_SGE
}};
338 FCmp64Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F64
, CmpInst::ICMP_SGT
}};
339 FCmp64Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_SLE
}};
340 FCmp64Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F64
, CmpInst::ICMP_SLT
}};
341 FCmp64Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F64
, CmpInst::ICMP_NE
}};
342 FCmp64Libcalls
[CmpInst::FCMP_UNO
] = {{RTLIB::UO_F64
, CmpInst::ICMP_NE
}};
343 FCmp64Libcalls
[CmpInst::FCMP_ONE
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_SGT
},
344 {RTLIB::OLT_F64
, CmpInst::ICMP_SLT
}};
345 FCmp64Libcalls
[CmpInst::FCMP_UEQ
] = {{RTLIB::OEQ_F64
, CmpInst::ICMP_EQ
},
346 {RTLIB::UO_F64
, CmpInst::ICMP_NE
}};
349 ARMLegalizerInfo::FCmpLibcallsList
350 ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate
,
351 unsigned Size
) const {
352 assert(CmpInst::isFPPredicate(Predicate
) && "Unsupported FCmp predicate");
354 return FCmp32Libcalls
[Predicate
];
356 return FCmp64Libcalls
[Predicate
];
357 llvm_unreachable("Unsupported size for FCmp predicate");
360 bool ARMLegalizerInfo::legalizeCustom(MachineInstr
&MI
,
361 MachineRegisterInfo
&MRI
,
362 MachineIRBuilder
&MIRBuilder
,
363 GISelChangeObserver
&Observer
) const {
364 using namespace TargetOpcode
;
366 MIRBuilder
.setInstr(MI
);
367 LLVMContext
&Ctx
= MIRBuilder
.getMF().getFunction().getContext();
369 switch (MI
.getOpcode()) {
374 Register OriginalResult
= MI
.getOperand(0).getReg();
375 auto Size
= MRI
.getType(OriginalResult
).getSizeInBits();
380 MI
.getOpcode() == G_SREM
? RTLIB::SDIVREM_I32
: RTLIB::UDIVREM_I32
;
382 // Our divmod libcalls return a struct containing the quotient and the
383 // remainder. Create a new, unused register for the quotient and use the
384 // destination of the original instruction for the remainder.
385 Type
*ArgTy
= Type::getInt32Ty(Ctx
);
386 StructType
*RetTy
= StructType::get(Ctx
, {ArgTy
, ArgTy
}, /* Packed */ true);
387 Register RetRegs
[] = {MRI
.createGenericVirtualRegister(LLT::scalar(32)),
389 auto Status
= createLibcall(MIRBuilder
, Libcall
, {RetRegs
, RetTy
},
390 {{MI
.getOperand(1).getReg(), ArgTy
},
391 {MI
.getOperand(2).getReg(), ArgTy
}});
392 if (Status
!= LegalizerHelper::Legalized
)
397 assert(MRI
.getType(MI
.getOperand(2).getReg()) ==
398 MRI
.getType(MI
.getOperand(3).getReg()) &&
399 "Mismatched operands for G_FCMP");
400 auto OpSize
= MRI
.getType(MI
.getOperand(2).getReg()).getSizeInBits();
402 auto OriginalResult
= MI
.getOperand(0).getReg();
404 static_cast<CmpInst::Predicate
>(MI
.getOperand(1).getPredicate());
405 auto Libcalls
= getFCmpLibcalls(Predicate
, OpSize
);
407 if (Libcalls
.empty()) {
408 assert((Predicate
== CmpInst::FCMP_TRUE
||
409 Predicate
== CmpInst::FCMP_FALSE
) &&
410 "Predicate needs libcalls, but none specified");
411 MIRBuilder
.buildConstant(OriginalResult
,
412 Predicate
== CmpInst::FCMP_TRUE
? 1 : 0);
413 MI
.eraseFromParent();
417 assert((OpSize
== 32 || OpSize
== 64) && "Unsupported operand size");
418 auto *ArgTy
= OpSize
== 32 ? Type::getFloatTy(Ctx
) : Type::getDoubleTy(Ctx
);
419 auto *RetTy
= Type::getInt32Ty(Ctx
);
421 SmallVector
<Register
, 2> Results
;
422 for (auto Libcall
: Libcalls
) {
423 auto LibcallResult
= MRI
.createGenericVirtualRegister(LLT::scalar(32));
425 createLibcall(MIRBuilder
, Libcall
.LibcallID
, {LibcallResult
, RetTy
},
426 {{MI
.getOperand(2).getReg(), ArgTy
},
427 {MI
.getOperand(3).getReg(), ArgTy
}});
429 if (Status
!= LegalizerHelper::Legalized
)
432 auto ProcessedResult
=
435 : MRI
.createGenericVirtualRegister(MRI
.getType(OriginalResult
));
437 // We have a result, but we need to transform it into a proper 1-bit 0 or
438 // 1, taking into account the different peculiarities of the values
439 // returned by the comparison functions.
440 CmpInst::Predicate ResultPred
= Libcall
.Predicate
;
441 if (ResultPred
== CmpInst::BAD_ICMP_PREDICATE
) {
442 // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
443 // to keep the types consistent.
444 MIRBuilder
.buildTrunc(ProcessedResult
, LibcallResult
);
446 // We need to compare against 0.
447 assert(CmpInst::isIntPredicate(ResultPred
) && "Unsupported predicate");
448 auto Zero
= MRI
.createGenericVirtualRegister(LLT::scalar(32));
449 MIRBuilder
.buildConstant(Zero
, 0);
450 MIRBuilder
.buildICmp(ResultPred
, ProcessedResult
, LibcallResult
, Zero
);
452 Results
.push_back(ProcessedResult
);
455 if (Results
.size() != 1) {
456 assert(Results
.size() == 2 && "Unexpected number of results");
457 MIRBuilder
.buildOr(OriginalResult
, Results
[0], Results
[1]);
462 // Convert to integer constants, while preserving the binary representation.
464 MI
.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
465 MIRBuilder
.buildConstant(MI
.getOperand(0).getReg(),
466 *ConstantInt::get(Ctx
, AsInteger
));
471 MI
.eraseFromParent();