26using namespace LegalizeActions;
40 for (
unsigned i = 0; i < v.size(); ++i) {
41 result.push_back(v[i]);
42 if (i + 1 < v[i].first && i + 1 < v.size() &&
43 v[i + 1].first != v[i].first + 1)
59 auto Largest = result.back().first;
65 return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
69 using namespace TargetOpcode;
80 if (ST.isThumb1Only()) {
82 LegacyInfo.computeTables();
83 verify(*ST.getInstrInfo());
88 .legalForCartesianProduct({s8, s16, s32}, {s1, s8, s16});
94 .clampScalar(0, s32, s32);
106 .legalFor({{s32, s32}})
110 bool HasHWDivide = (!ST.isThumb() && ST.hasDivideInARMMode()) ||
111 (ST.isThumb() && ST.hasDivideInThumbMode());
115 .clampScalar(0, s32, s32);
119 .clampScalar(0, s32, s32);
121 for (
unsigned Op : {G_SREM, G_UREM}) {
122 LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
Op, 0,
widen_8_16);
140 .clampScalar(0, s32, s32);
153 .legalForTypesWithMemDesc({{s8, p0, s8, 8},
157 .unsupportedIfMemSizeNotPow2();
173 if (!ST.useSoftFloat() && ST.hasVFP2Base()) {
175 {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG})
176 .legalFor({s32, s64});
193 .legalForCartesianProduct({s32}, {s32, s64});
195 .legalForCartesianProduct({s32, s64}, {s32});
198 .libcallFor({s32, s64});
202 for (
auto Ty : {s32, s64})
211 setFCmpLibcallsAEABI();
213 setFCmpLibcallsGNU();
219 .libcallForCartesianProduct({s32}, {s32, s64});
221 .libcallForCartesianProduct({s32, s64}, {s32});
225 LoadStoreBuilder.
lower();
227 if (!ST.useSoftFloat() && ST.hasVFP4Base())
234 if (ST.hasV5TOps()) {
237 .clampScalar(1, s32, s32)
241 .clampScalar(1, s32, s32)
246 .clampScalar(1, s32, s32)
250 .clampScalar(1, s32, s32)
254 LegacyInfo.computeTables();
255 verify(*ST.getInstrInfo());
258void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
314void ARMLegalizerInfo::setFCmpLibcallsGNU() {
356 unsigned Size)
const {
367 using namespace TargetOpcode;
373 switch (
MI.getOpcode()) {
378 Register OriginalResult =
MI.getOperand(0).getReg();
379 auto Size =
MRI.getType(OriginalResult).getSizeInBits();
384 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
394 {{
MI.getOperand(1).
getReg(), ArgTy, 0},
395 {
MI.getOperand(2).
getReg(), ArgTy, 0}});
402 MRI.getType(
MI.getOperand(3).getReg()) &&
403 "Mismatched operands for G_FCMP");
404 auto OpSize =
MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits();
406 auto OriginalResult =
MI.getOperand(0).getReg();
409 auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
411 if (Libcalls.empty()) {
414 "Predicate needs libcalls, but none specified");
417 MI.eraseFromParent();
421 assert((OpSize == 32 || OpSize == 64) &&
"Unsupported operand size");
426 for (
auto Libcall : Libcalls) {
427 auto LibcallResult =
MRI.createGenericVirtualRegister(
LLT::scalar(32));
429 {LibcallResult, RetTy, 0},
430 {{MI.getOperand(2).getReg(), ArgTy, 0},
431 {MI.getOperand(3).getReg(), ArgTy, 0}});
436 auto ProcessedResult =
439 :
MRI.createGenericVirtualRegister(
MRI.getType(OriginalResult));
448 MIRBuilder.
buildTrunc(ProcessedResult, LibcallResult);
453 MIRBuilder.
buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);
455 Results.push_back(ProcessedResult);
467 MI.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
474 MI.eraseFromParent();
unsigned const MachineRegisterInfo * MRI
This file describes how to lower LLVM calls to machine code calls.
static LegacyLegalizerInfo::SizeAndActionsVec widen_8_16(const LegacyLegalizerInfo::SizeAndActionsVec &v)
static void addAndInterleaveWithUnsupported(LegacyLegalizerInfo::SizeAndActionsVec &result, const LegacyLegalizerInfo::SizeAndActionsVec &v)
FIXME: The following static functions are SizeChangeStrategy functions that are meant to temporarily ...
static bool AEABI(const ARMSubtarget &ST)
This file declares the targeting of the Machinelegalizer class for ARM.
Function Alias Analysis Results
Implement a low-level type suitable for MachineInstr level instruction selection.
This file declares the MachineIRBuilder class.
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ARMLegalizerInfo(const ARMSubtarget &ST)
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI) const override
Called for instructions with the Custom LegalizationAction.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
bool isFPPredicate() const
bool isIntPredicate() const
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
This class represents an Operation in the Expression.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void resize(typename StorageT::size_type s)
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
This is an important class for using LLVM in a threaded context.
std::vector< SizeAndAction > SizeAndActionsVec
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & libcallFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & customForCartesianProduct(std::initializer_list< LLT > Types)
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & legalForTypesWithMemDesc(std::initializer_list< LegalityPredicates::TypePairAndMemDesc > TypesAndMemDesc)
The instruction is legal when type indexes 0 and 1 along with the memory size and minimum alignment i...
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_TRUNC Op.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getDoubleTy(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Unsupported
This operation is completely unsupported on the target.
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
@ Custom
The target wants to do something special with this combination of operand and type.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
This is an optimization pass for GlobalISel generic memory operations.
LegalizerHelper::LegalizeResult createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC)
Helper function that creates a libcall to the given Name using the given calling convention CC.
DWARFExpression::Operation Op