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_MUL
, G_AND
, G_OR
, G_XOR
})
92 getActionDefinitionsBuilder({G_ADD
, G_SUB
})
96 getActionDefinitionsBuilder({G_ADD
, G_SUB
})
100 getActionDefinitionsBuilder({G_ASHR
, G_LSHR
, G_SHL
})
101 .legalFor({{s32
, s32
}})
103 .clampScalar(1, s32
, s32
);
105 bool HasHWDivide
= (!ST
.isThumb() && ST
.hasDivideInARMMode()) ||
106 (ST
.isThumb() && ST
.hasDivideInThumbMode());
108 getActionDefinitionsBuilder({G_SDIV
, G_UDIV
})
110 .clampScalar(0, s32
, s32
);
112 getActionDefinitionsBuilder({G_SDIV
, G_UDIV
})
114 .clampScalar(0, s32
, s32
);
116 for (unsigned Op
: {G_SREM
, G_UREM
}) {
117 setLegalizeScalarToDifferentSizeStrategy(Op
, 0, widen_8_16
);
119 setAction({Op
, s32
}, Lower
);
121 setAction({Op
, s32
}, Custom
);
123 setAction({Op
, s32
}, Libcall
);
126 getActionDefinitionsBuilder(G_INTTOPTR
)
127 .legalFor({{p0
, s32
}})
129 getActionDefinitionsBuilder(G_PTRTOINT
)
130 .legalFor({{s32
, p0
}})
133 getActionDefinitionsBuilder(G_CONSTANT
)
135 .clampScalar(0, s32
, s32
);
137 getActionDefinitionsBuilder(G_ICMP
)
138 .legalForCartesianProduct({s1
}, {s32
, p0
})
141 getActionDefinitionsBuilder(G_SELECT
)
142 .legalForCartesianProduct({s32
, p0
}, {s1
})
145 // We're keeping these builders around because we'll want to add support for
146 // floating point to them.
147 auto &LoadStoreBuilder
= getActionDefinitionsBuilder({G_LOAD
, G_STORE
})
148 .legalForTypesWithMemDesc({{s1
, p0
, 8, 8},
153 .unsupportedIfMemSizeNotPow2();
155 getActionDefinitionsBuilder(G_FRAME_INDEX
).legalFor({p0
});
156 getActionDefinitionsBuilder(G_GLOBAL_VALUE
).legalFor({p0
});
159 getActionDefinitionsBuilder(G_PHI
)
163 getActionDefinitionsBuilder(G_GEP
)
164 .legalFor({{p0
, s32
}})
167 getActionDefinitionsBuilder(G_BRCOND
).legalFor({s1
});
169 if (!ST
.useSoftFloat() && ST
.hasVFP2Base()) {
170 getActionDefinitionsBuilder(
171 {G_FADD
, G_FSUB
, G_FMUL
, G_FDIV
, G_FCONSTANT
, G_FNEG
})
172 .legalFor({s32
, s64
});
175 .legalForTypesWithMemDesc({{s64
, p0
, 64, 32}})
177 PhiBuilder
.legalFor({s64
});
179 getActionDefinitionsBuilder(G_FCMP
).legalForCartesianProduct({s1
},
182 getActionDefinitionsBuilder(G_MERGE_VALUES
).legalFor({{s64
, s32
}});
183 getActionDefinitionsBuilder(G_UNMERGE_VALUES
).legalFor({{s32
, s64
}});
185 getActionDefinitionsBuilder(G_FPEXT
).legalFor({{s64
, s32
}});
186 getActionDefinitionsBuilder(G_FPTRUNC
).legalFor({{s32
, s64
}});
188 getActionDefinitionsBuilder({G_FPTOSI
, G_FPTOUI
})
189 .legalForCartesianProduct({s32
}, {s32
, s64
});
190 getActionDefinitionsBuilder({G_SITOFP
, G_UITOFP
})
191 .legalForCartesianProduct({s32
, s64
}, {s32
});
193 getActionDefinitionsBuilder({G_FADD
, G_FSUB
, G_FMUL
, G_FDIV
})
194 .libcallFor({s32
, s64
});
196 LoadStoreBuilder
.maxScalar(0, s32
);
198 for (auto Ty
: {s32
, s64
})
199 setAction({G_FNEG
, Ty
}, Lower
);
201 getActionDefinitionsBuilder(G_FCONSTANT
).customFor({s32
, s64
});
203 getActionDefinitionsBuilder(G_FCMP
).customForCartesianProduct({s1
},
207 setFCmpLibcallsAEABI();
209 setFCmpLibcallsGNU();
211 getActionDefinitionsBuilder(G_FPEXT
).libcallFor({{s64
, s32
}});
212 getActionDefinitionsBuilder(G_FPTRUNC
).libcallFor({{s32
, s64
}});
214 getActionDefinitionsBuilder({G_FPTOSI
, G_FPTOUI
})
215 .libcallForCartesianProduct({s32
}, {s32
, s64
});
216 getActionDefinitionsBuilder({G_SITOFP
, G_UITOFP
})
217 .libcallForCartesianProduct({s32
, s64
}, {s32
});
220 if (!ST
.useSoftFloat() && ST
.hasVFP4Base())
221 getActionDefinitionsBuilder(G_FMA
).legalFor({s32
, s64
});
223 getActionDefinitionsBuilder(G_FMA
).libcallFor({s32
, s64
});
225 getActionDefinitionsBuilder({G_FREM
, G_FPOW
}).libcallFor({s32
, s64
});
227 if (ST
.hasV5TOps()) {
228 getActionDefinitionsBuilder(G_CTLZ
)
229 .legalFor({s32
, s32
})
230 .clampScalar(1, s32
, s32
)
231 .clampScalar(0, s32
, s32
);
232 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
)
233 .lowerFor({s32
, s32
})
234 .clampScalar(1, s32
, s32
)
235 .clampScalar(0, s32
, s32
);
237 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
)
238 .libcallFor({s32
, s32
})
239 .clampScalar(1, s32
, s32
)
240 .clampScalar(0, s32
, s32
);
241 getActionDefinitionsBuilder(G_CTLZ
)
242 .lowerFor({s32
, s32
})
243 .clampScalar(1, s32
, s32
)
244 .clampScalar(0, s32
, s32
);
248 verify(*ST
.getInstrInfo());
251 void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
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
] = {
256 {RTLIB::OEQ_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
257 FCmp32Libcalls
[CmpInst::FCMP_OGE
] = {
258 {RTLIB::OGE_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
259 FCmp32Libcalls
[CmpInst::FCMP_OGT
] = {
260 {RTLIB::OGT_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
261 FCmp32Libcalls
[CmpInst::FCMP_OLE
] = {
262 {RTLIB::OLE_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
263 FCmp32Libcalls
[CmpInst::FCMP_OLT
] = {
264 {RTLIB::OLT_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
265 FCmp32Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F32
, CmpInst::ICMP_EQ
}};
266 FCmp32Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F32
, CmpInst::ICMP_EQ
}};
267 FCmp32Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F32
, CmpInst::ICMP_EQ
}};
268 FCmp32Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_EQ
}};
269 FCmp32Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F32
, CmpInst::ICMP_EQ
}};
270 FCmp32Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F32
, CmpInst::ICMP_EQ
}};
271 FCmp32Libcalls
[CmpInst::FCMP_UNO
] = {
272 {RTLIB::UO_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
273 FCmp32Libcalls
[CmpInst::FCMP_ONE
] = {
274 {RTLIB::OGT_F32
, CmpInst::BAD_ICMP_PREDICATE
},
275 {RTLIB::OLT_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
276 FCmp32Libcalls
[CmpInst::FCMP_UEQ
] = {
277 {RTLIB::OEQ_F32
, CmpInst::BAD_ICMP_PREDICATE
},
278 {RTLIB::UO_F32
, CmpInst::BAD_ICMP_PREDICATE
}};
280 FCmp64Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
281 FCmp64Libcalls
[CmpInst::FCMP_OEQ
] = {
282 {RTLIB::OEQ_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
283 FCmp64Libcalls
[CmpInst::FCMP_OGE
] = {
284 {RTLIB::OGE_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
285 FCmp64Libcalls
[CmpInst::FCMP_OGT
] = {
286 {RTLIB::OGT_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
287 FCmp64Libcalls
[CmpInst::FCMP_OLE
] = {
288 {RTLIB::OLE_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
289 FCmp64Libcalls
[CmpInst::FCMP_OLT
] = {
290 {RTLIB::OLT_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
291 FCmp64Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F64
, CmpInst::ICMP_EQ
}};
292 FCmp64Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F64
, CmpInst::ICMP_EQ
}};
293 FCmp64Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F64
, CmpInst::ICMP_EQ
}};
294 FCmp64Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_EQ
}};
295 FCmp64Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F64
, CmpInst::ICMP_EQ
}};
296 FCmp64Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F64
, CmpInst::ICMP_EQ
}};
297 FCmp64Libcalls
[CmpInst::FCMP_UNO
] = {
298 {RTLIB::UO_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
299 FCmp64Libcalls
[CmpInst::FCMP_ONE
] = {
300 {RTLIB::OGT_F64
, CmpInst::BAD_ICMP_PREDICATE
},
301 {RTLIB::OLT_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
302 FCmp64Libcalls
[CmpInst::FCMP_UEQ
] = {
303 {RTLIB::OEQ_F64
, CmpInst::BAD_ICMP_PREDICATE
},
304 {RTLIB::UO_F64
, CmpInst::BAD_ICMP_PREDICATE
}};
307 void ARMLegalizerInfo::setFCmpLibcallsGNU() {
308 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
309 // default-initialized.
310 FCmp32Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
311 FCmp32Libcalls
[CmpInst::FCMP_OEQ
] = {{RTLIB::OEQ_F32
, CmpInst::ICMP_EQ
}};
312 FCmp32Libcalls
[CmpInst::FCMP_OGE
] = {{RTLIB::OGE_F32
, CmpInst::ICMP_SGE
}};
313 FCmp32Libcalls
[CmpInst::FCMP_OGT
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_SGT
}};
314 FCmp32Libcalls
[CmpInst::FCMP_OLE
] = {{RTLIB::OLE_F32
, CmpInst::ICMP_SLE
}};
315 FCmp32Libcalls
[CmpInst::FCMP_OLT
] = {{RTLIB::OLT_F32
, CmpInst::ICMP_SLT
}};
316 FCmp32Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F32
, CmpInst::ICMP_EQ
}};
317 FCmp32Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F32
, CmpInst::ICMP_SGE
}};
318 FCmp32Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F32
, CmpInst::ICMP_SGT
}};
319 FCmp32Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_SLE
}};
320 FCmp32Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F32
, CmpInst::ICMP_SLT
}};
321 FCmp32Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F32
, CmpInst::ICMP_NE
}};
322 FCmp32Libcalls
[CmpInst::FCMP_UNO
] = {{RTLIB::UO_F32
, CmpInst::ICMP_NE
}};
323 FCmp32Libcalls
[CmpInst::FCMP_ONE
] = {{RTLIB::OGT_F32
, CmpInst::ICMP_SGT
},
324 {RTLIB::OLT_F32
, CmpInst::ICMP_SLT
}};
325 FCmp32Libcalls
[CmpInst::FCMP_UEQ
] = {{RTLIB::OEQ_F32
, CmpInst::ICMP_EQ
},
326 {RTLIB::UO_F32
, CmpInst::ICMP_NE
}};
328 FCmp64Libcalls
.resize(CmpInst::LAST_FCMP_PREDICATE
+ 1);
329 FCmp64Libcalls
[CmpInst::FCMP_OEQ
] = {{RTLIB::OEQ_F64
, CmpInst::ICMP_EQ
}};
330 FCmp64Libcalls
[CmpInst::FCMP_OGE
] = {{RTLIB::OGE_F64
, CmpInst::ICMP_SGE
}};
331 FCmp64Libcalls
[CmpInst::FCMP_OGT
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_SGT
}};
332 FCmp64Libcalls
[CmpInst::FCMP_OLE
] = {{RTLIB::OLE_F64
, CmpInst::ICMP_SLE
}};
333 FCmp64Libcalls
[CmpInst::FCMP_OLT
] = {{RTLIB::OLT_F64
, CmpInst::ICMP_SLT
}};
334 FCmp64Libcalls
[CmpInst::FCMP_ORD
] = {{RTLIB::O_F64
, CmpInst::ICMP_EQ
}};
335 FCmp64Libcalls
[CmpInst::FCMP_UGE
] = {{RTLIB::OLT_F64
, CmpInst::ICMP_SGE
}};
336 FCmp64Libcalls
[CmpInst::FCMP_UGT
] = {{RTLIB::OLE_F64
, CmpInst::ICMP_SGT
}};
337 FCmp64Libcalls
[CmpInst::FCMP_ULE
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_SLE
}};
338 FCmp64Libcalls
[CmpInst::FCMP_ULT
] = {{RTLIB::OGE_F64
, CmpInst::ICMP_SLT
}};
339 FCmp64Libcalls
[CmpInst::FCMP_UNE
] = {{RTLIB::UNE_F64
, CmpInst::ICMP_NE
}};
340 FCmp64Libcalls
[CmpInst::FCMP_UNO
] = {{RTLIB::UO_F64
, CmpInst::ICMP_NE
}};
341 FCmp64Libcalls
[CmpInst::FCMP_ONE
] = {{RTLIB::OGT_F64
, CmpInst::ICMP_SGT
},
342 {RTLIB::OLT_F64
, CmpInst::ICMP_SLT
}};
343 FCmp64Libcalls
[CmpInst::FCMP_UEQ
] = {{RTLIB::OEQ_F64
, CmpInst::ICMP_EQ
},
344 {RTLIB::UO_F64
, CmpInst::ICMP_NE
}};
347 ARMLegalizerInfo::FCmpLibcallsList
348 ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate
,
349 unsigned Size
) const {
350 assert(CmpInst::isFPPredicate(Predicate
) && "Unsupported FCmp predicate");
352 return FCmp32Libcalls
[Predicate
];
354 return FCmp64Libcalls
[Predicate
];
355 llvm_unreachable("Unsupported size for FCmp predicate");
358 bool ARMLegalizerInfo::legalizeCustom(MachineInstr
&MI
,
359 MachineRegisterInfo
&MRI
,
360 MachineIRBuilder
&MIRBuilder
,
361 GISelChangeObserver
&Observer
) const {
362 using namespace TargetOpcode
;
364 MIRBuilder
.setInstr(MI
);
365 LLVMContext
&Ctx
= MIRBuilder
.getMF().getFunction().getContext();
367 switch (MI
.getOpcode()) {
372 Register OriginalResult
= MI
.getOperand(0).getReg();
373 auto Size
= MRI
.getType(OriginalResult
).getSizeInBits();
378 MI
.getOpcode() == G_SREM
? RTLIB::SDIVREM_I32
: RTLIB::UDIVREM_I32
;
380 // Our divmod libcalls return a struct containing the quotient and the
381 // remainder. Create a new, unused register for the quotient and use the
382 // destination of the original instruction for the remainder.
383 Type
*ArgTy
= Type::getInt32Ty(Ctx
);
384 StructType
*RetTy
= StructType::get(Ctx
, {ArgTy
, ArgTy
}, /* Packed */ true);
385 Register RetRegs
[] = {MRI
.createGenericVirtualRegister(LLT::scalar(32)),
387 auto Status
= createLibcall(MIRBuilder
, Libcall
, {RetRegs
, RetTy
},
388 {{MI
.getOperand(1).getReg(), ArgTy
},
389 {MI
.getOperand(2).getReg(), ArgTy
}});
390 if (Status
!= LegalizerHelper::Legalized
)
395 assert(MRI
.getType(MI
.getOperand(2).getReg()) ==
396 MRI
.getType(MI
.getOperand(3).getReg()) &&
397 "Mismatched operands for G_FCMP");
398 auto OpSize
= MRI
.getType(MI
.getOperand(2).getReg()).getSizeInBits();
400 auto OriginalResult
= MI
.getOperand(0).getReg();
402 static_cast<CmpInst::Predicate
>(MI
.getOperand(1).getPredicate());
403 auto Libcalls
= getFCmpLibcalls(Predicate
, OpSize
);
405 if (Libcalls
.empty()) {
406 assert((Predicate
== CmpInst::FCMP_TRUE
||
407 Predicate
== CmpInst::FCMP_FALSE
) &&
408 "Predicate needs libcalls, but none specified");
409 MIRBuilder
.buildConstant(OriginalResult
,
410 Predicate
== CmpInst::FCMP_TRUE
? 1 : 0);
411 MI
.eraseFromParent();
415 assert((OpSize
== 32 || OpSize
== 64) && "Unsupported operand size");
416 auto *ArgTy
= OpSize
== 32 ? Type::getFloatTy(Ctx
) : Type::getDoubleTy(Ctx
);
417 auto *RetTy
= Type::getInt32Ty(Ctx
);
419 SmallVector
<Register
, 2> Results
;
420 for (auto Libcall
: Libcalls
) {
421 auto LibcallResult
= MRI
.createGenericVirtualRegister(LLT::scalar(32));
423 createLibcall(MIRBuilder
, Libcall
.LibcallID
, {LibcallResult
, RetTy
},
424 {{MI
.getOperand(2).getReg(), ArgTy
},
425 {MI
.getOperand(3).getReg(), ArgTy
}});
427 if (Status
!= LegalizerHelper::Legalized
)
430 auto ProcessedResult
=
433 : MRI
.createGenericVirtualRegister(MRI
.getType(OriginalResult
));
435 // We have a result, but we need to transform it into a proper 1-bit 0 or
436 // 1, taking into account the different peculiarities of the values
437 // returned by the comparison functions.
438 CmpInst::Predicate ResultPred
= Libcall
.Predicate
;
439 if (ResultPred
== CmpInst::BAD_ICMP_PREDICATE
) {
440 // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
441 // to keep the types consistent.
442 MIRBuilder
.buildTrunc(ProcessedResult
, LibcallResult
);
444 // We need to compare against 0.
445 assert(CmpInst::isIntPredicate(ResultPred
) && "Unsupported predicate");
446 auto Zero
= MRI
.createGenericVirtualRegister(LLT::scalar(32));
447 MIRBuilder
.buildConstant(Zero
, 0);
448 MIRBuilder
.buildICmp(ResultPred
, ProcessedResult
, LibcallResult
, Zero
);
450 Results
.push_back(ProcessedResult
);
453 if (Results
.size() != 1) {
454 assert(Results
.size() == 2 && "Unexpected number of results");
455 MIRBuilder
.buildOr(OriginalResult
, Results
[0], Results
[1]);
460 // Convert to integer constants, while preserving the binary representation.
462 MI
.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
463 MIRBuilder
.buildConstant(MI
.getOperand(0).getReg(),
464 *ConstantInt::get(Ctx
, AsInteger
));
469 MI
.eraseFromParent();