LLVM 19.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//===----------------------------------------------------------------------===//
12#include "AArch64InstrInfo.h"
15#include "llvm/IR/InstrTypes.h"
17
18using namespace llvm;
19
20std::optional<RegOrConstant>
22 const MachineRegisterInfo &MRI) {
23 if (auto Splat = getVectorSplat(MI, MRI))
24 return Splat;
25 if (MI.getOpcode() != AArch64::G_DUP)
26 return std::nullopt;
27 Register Src = MI.getOperand(1).getReg();
28 if (auto ValAndVReg =
29 getAnyConstantVRegValWithLookThrough(MI.getOperand(1).getReg(), MRI))
30 return RegOrConstant(ValAndVReg->Value.getSExtValue());
31 return RegOrConstant(Src);
32}
33
34std::optional<int64_t>
36 const MachineRegisterInfo &MRI) {
38 if (!Splat || Splat->isReg())
39 return std::nullopt;
40 return Splat->getCst();
41}
42
44 const CmpInst::Predicate &Pred,
45 const MachineRegisterInfo &MRI) {
46 // Match:
47 //
48 // %sub = G_SUB 0, %y
49 // %cmp = G_ICMP eq/ne, %sub, %z
50 //
51 // Or
52 //
53 // %sub = G_SUB 0, %y
54 // %cmp = G_ICMP eq/ne, %z, %sub
55 if (!MaybeSub || MaybeSub->getOpcode() != TargetOpcode::G_SUB ||
57 return false;
58 auto MaybeZero =
60 return MaybeZero && MaybeZero->Value.getZExtValue() == 0;
61}
62
64 MachineIRBuilder &MIRBuilder,
65 bool MinSize) {
66 assert(MI.getOpcode() == TargetOpcode::G_MEMSET);
67 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
68 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
69 if (!TLI.getLibcallName(RTLIB::BZERO))
70 return false;
71 auto Zero =
72 getIConstantVRegValWithLookThrough(MI.getOperand(1).getReg(), MRI);
73 if (!Zero || Zero->Value.getSExtValue() != 0)
74 return false;
75
76 // It's not faster to use bzero rather than memset for sizes <= 256.
77 // However, it *does* save us a mov from wzr, so if we're going for
78 // minsize, use bzero even if it's slower.
79 if (!MinSize) {
80 // If the size is known, check it. If it is not known, assume using bzero is
81 // better.
83 MI.getOperand(2).getReg(), MRI)) {
84 if (Size->Value.getSExtValue() <= 256)
85 return false;
86 }
87 }
88
89 MIRBuilder.setInstrAndDebugLoc(MI);
90 MIRBuilder
91 .buildInstr(TargetOpcode::G_BZERO, {},
92 {MI.getOperand(0), MI.getOperand(2)})
93 .addImm(MI.getOperand(3).getImm())
94 .addMemOperand(*MI.memoperands_begin());
95 MI.eraseFromParent();
96 return true;
97}
98
101 AArch64CC::CondCode &CondCode2) {
102 CondCode2 = AArch64CC::AL;
103 switch (P) {
104 default:
105 llvm_unreachable("Unknown FP condition!");
107 CondCode = AArch64CC::EQ;
108 break;
110 CondCode = AArch64CC::GT;
111 break;
113 CondCode = AArch64CC::GE;
114 break;
116 CondCode = AArch64CC::MI;
117 break;
119 CondCode = AArch64CC::LS;
120 break;
122 CondCode = AArch64CC::MI;
123 CondCode2 = AArch64CC::GT;
124 break;
126 CondCode = AArch64CC::VC;
127 break;
129 CondCode = AArch64CC::VS;
130 break;
132 CondCode = AArch64CC::EQ;
133 CondCode2 = AArch64CC::VS;
134 break;
136 CondCode = AArch64CC::HI;
137 break;
139 CondCode = AArch64CC::PL;
140 break;
142 CondCode = AArch64CC::LT;
143 break;
145 CondCode = AArch64CC::LE;
146 break;
148 CondCode = AArch64CC::NE;
149 break;
150 }
151}
152
155 AArch64CC::CondCode &CondCode2, bool &Invert) {
156 Invert = false;
157 switch (P) {
158 default:
159 // Mostly the scalar mappings work fine.
160 changeFCMPPredToAArch64CC(P, CondCode, CondCode2);
161 break;
163 Invert = true;
164 [[fallthrough]];
166 CondCode = AArch64CC::MI;
167 CondCode2 = AArch64CC::GE;
168 break;
174 // All of the compare-mask comparisons are ordered, but we can switch
175 // between the two by a double inversion. E.g. ULE == !OGT.
176 Invert = true;
178 CondCode2);
179 break;
180 }
181}
unsigned const MachineRegisterInfo * MRI
uint64_t Size
IRTranslator LLVM IR MI
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file describes how to lower LLVM code to machine code.
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition: InstrTypes.h:1222
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:960
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition: InstrTypes.h:963
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition: InstrTypes.h:966
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition: InstrTypes.h:975
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition: InstrTypes.h:964
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition: InstrTypes.h:965
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition: InstrTypes.h:974
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition: InstrTypes.h:968
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition: InstrTypes.h:971
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition: InstrTypes.h:972
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition: InstrTypes.h:967
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition: InstrTypes.h:969
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition: InstrTypes.h:976
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition: InstrTypes.h:973
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition: InstrTypes.h:970
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition: InstrTypes.h:1096
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:546
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:556
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Represents a value which can be a Register or a constant.
Definition: Utils.h:387
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
virtual const TargetLowering * getTargetLowering() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< RegOrConstant > getAArch64VectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
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.
bool tryEmitBZero(MachineInstr &MI, MachineIRBuilder &MIRBuilder, bool MinSize)
Replace a G_MEMSET with a value of 0 with a G_BZERO instruction if it is supported and beneficial to ...
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)
std::optional< int64_t > getAArch64VectorSplatScalar(const MachineInstr &MI, const MachineRegisterInfo &MRI)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::optional< RegOrConstant > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:1357
std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
Definition: Utils.cpp:419
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:413