LLVM 24.0.0git
AArch64GlobalISelUtils.cpp
Go to the documentation of this file.
1//===- AArch64GlobalISelUtils.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 Implementations of AArch64-specific helper functions used in the
9/// GlobalISel pipeline.
10//===----------------------------------------------------------------------===//
15#include "llvm/IR/InstrTypes.h"
16
17using namespace llvm;
18using namespace MIPatternMatch;
19
21 const CmpInst::Predicate &Pred,
22 const MachineRegisterInfo &MRI) {
23 // Match:
24 //
25 // %sub = G_SUB 0, %y
26 // %cmp = G_ICMP eq/ne, %sub, %z
27 //
28 // Or
29 //
30 // %sub = G_SUB 0, %y
31 // %cmp = G_ICMP eq/ne, %z, %sub
32 // or with signed comparisons with the no-signed-wrap flag set
33 if (!MaybeSub || MaybeSub->getOpcode() != TargetOpcode::G_SUB ||
34 (!CmpInst::isEquality(Pred) &&
35 !(CmpInst::isSigned(Pred) && MaybeSub->getFlag(MachineInstr::NoSWrap))))
36 return false;
37 auto MaybeZero =
39 return MaybeZero && MaybeZero->Value.getZExtValue() == 0;
40}
41
43 MachineIRBuilder &MIRBuilder) {
44 assert(MI.getOpcode() == TargetOpcode::G_MEMSET);
45
46 MIRBuilder.setInstrAndDebugLoc(MI);
47 MIRBuilder
48 .buildInstr(TargetOpcode::G_BZERO, {},
49 {MI.getOperand(0), MI.getOperand(2)})
50 .addImm(MI.getOperand(3).getImm())
51 .addMemOperand(*MI.memoperands_begin());
52 MI.eraseFromParent();
53}
54
56 const MachineRegisterInfo &MRI,
57 const LibcallLoweringInfo &Libcalls,
58 bool MinSize) {
59 assert(MI.getOpcode() == TargetOpcode::G_MEMSET);
60 if (Libcalls.getLibcallImpl(RTLIB::BZERO) == RTLIB::Unsupported)
61 return false;
62
63 auto Zero =
64 getIConstantVRegValWithLookThrough(MI.getOperand(1).getReg(), MRI);
65 if (!Zero || Zero->Value.getSExtValue() != 0)
66 return false;
67
68 // It's not faster to use bzero rather than memset for sizes <= 256.
69 // However, it *does* save us a mov from wzr, so if we're going for
70 // minsize, use bzero even if it's slower.
71 if (!MinSize) {
72 // If the size is known, check it. If it is not known, assume using bzero is
73 // better.
75 MI.getOperand(2).getReg(), MRI)) {
76 if (Size->Value.getSExtValue() <= 256)
77 return false;
78 }
79 }
80 return true;
81}
82
83std::tuple<uint16_t, Register>
86 Register AddrDisc = Disc;
87 uint16_t ConstDisc = 0;
88
89 if (auto ConstDiscVal = getIConstantVRegVal(Disc, MRI)) {
90 if (isUInt<16>(ConstDiscVal->getZExtValue())) {
91 ConstDisc = ConstDiscVal->getZExtValue();
92 AddrDisc = Register();
93 }
94 return std::make_tuple(ConstDisc, AddrDisc);
95 }
96
97 Register BlendAddrDisc, BlendConstDisc;
98 if (!mi_match(Disc, MRI,
100 m_Reg(BlendConstDisc))))
101 return std::make_tuple(ConstDisc, AddrDisc);
102
103 if (auto ConstDiscVal = getIConstantVRegVal(BlendConstDisc, MRI)) {
104 if (isUInt<16>(ConstDiscVal->getZExtValue())) {
105 ConstDisc = ConstDiscVal->getZExtValue();
106 AddrDisc = BlendAddrDisc;
107 }
108 }
109 return std::make_tuple(ConstDisc, AddrDisc);
110}
111
114 AArch64CC::CondCode &CondCode2) {
115 CondCode2 = AArch64CC::AL;
116 switch (P) {
117 default:
118 llvm_unreachable("Unknown FP condition!");
120 CondCode = AArch64CC::EQ;
121 break;
123 CondCode = AArch64CC::GT;
124 break;
126 CondCode = AArch64CC::GE;
127 break;
129 CondCode = AArch64CC::MI;
130 break;
132 CondCode = AArch64CC::LS;
133 break;
135 CondCode = AArch64CC::MI;
136 CondCode2 = AArch64CC::GT;
137 break;
139 CondCode = AArch64CC::VC;
140 break;
142 CondCode = AArch64CC::VS;
143 break;
145 CondCode = AArch64CC::EQ;
146 CondCode2 = AArch64CC::VS;
147 break;
149 CondCode = AArch64CC::HI;
150 break;
152 CondCode = AArch64CC::PL;
153 break;
155 CondCode = AArch64CC::LT;
156 break;
158 CondCode = AArch64CC::LE;
159 break;
161 CondCode = AArch64CC::NE;
162 break;
164 CondCode = AArch64CC::AL;
165 break;
167 CondCode = AArch64CC::NV;
168 break;
169 }
170}
171
174 AArch64CC::CondCode &CondCode2, bool &Invert) {
175 Invert = false;
176 switch (P) {
177 default:
178 // Mostly the scalar mappings work fine.
179 changeFCMPPredToAArch64CC(P, CondCode, CondCode2);
180 break;
182 Invert = true;
183 [[fallthrough]];
185 CondCode = AArch64CC::MI;
186 CondCode2 = AArch64CC::GE;
187 break;
193 // All of the compare-mask comparisons are ordered, but we can switch
194 // between the two by a double inversion. E.g. ULE == !OGT.
195 Invert = true;
197 CondCode2);
198 break;
199 }
200}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
IRTranslator LLVM IR MI
Contains matchers for matching SSA Machine Instructions.
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
This file describes how to lower LLVM code to machine code.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:757
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:755
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:754
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:752
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:753
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:742
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
bool isSigned() const
Definition InstrTypes.h:993
static LLVM_ABI bool isEquality(Predicate pred)
Determine if this is an equals/not equals predicate.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
Tracks which library functions to use for a particular subtarget or function.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::tuple< uint16_t, Register > extractPtrauthBlendDiscriminators(Register Disc, MachineRegisterInfo &MRI)
Analyze a ptrauth discriminator value to try to find the constant integer and address parts,...
bool matchEmitBZero(const MachineInstr &MI, const MachineRegisterInfo &MRI, const LibcallLoweringInfo &Libcalls, bool MinSize)
Replace a G_MEMSET with a value of 0 with a G_BZERO instruction if it is supported and beneficial to ...
void changeFCMPPredToAArch64CC(const CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
Find the AArch64 condition codes necessary to represent P for a scalar floating point comparison.
void changeVectorFCMPPredToAArch64CC(const CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2, bool &Invert)
Find the AArch64 condition codes necessary to represent P for a vector floating point comparison.
bool isCMN(const MachineInstr *MaybeSub, const CmpInst::Predicate &Pred, const MachineRegisterInfo &MRI)
void applyEmitBZero(MachineInstr &MI, MachineIRBuilder &MIRBuilder)
Replace MI with a G_BZERO.
operand_type_match m_Reg()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GInstrBind< GIntrinsic > m_GIntrinsic(GIntrinsic *&Inst)
Binds the defining instruction of Reg if it is a GIntrinsic (any of the four G_INTRINSIC* opcodes).
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition Utils.cpp:297
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436