Go to the documentation of this file.
40 #define DEBUG_TYPE "aarch64-postlegalizer-combiner"
43 using namespace MIPatternMatch;
55 std::tuple<unsigned, LLT, Register> &MatchInfo) {
61 if (!Cst || Cst->Value != 0)
72 if (DstSize != 16 && DstSize != 32 && DstSize != 64)
75 Register Src1Op1 = FAddMI->getOperand(1).getReg();
76 Register Src1Op2 = FAddMI->getOperand(2).getReg();
88 std::get<0>(MatchInfo) = TargetOpcode::G_FADD;
89 std::get<1>(MatchInfo) = DstTy;
90 std::get<2>(MatchInfo) =
Other->getOperand(0).getReg();
98 std::tuple<unsigned, LLT, Register> &MatchInfo) {
99 unsigned Opc = std::get<0>(MatchInfo);
100 assert(Opc == TargetOpcode::G_FADD &&
"Unexpected opcode!");
102 LLT Ty = std::get<1>(MatchInfo);
103 Register Src = std::get<2>(MatchInfo);
105 B.setInstrAndDebugLoc(
MI);
106 auto Elt0 =
B.buildExtractVectorElement(Ty, Src,
B.buildConstant(s64, 0));
107 auto Elt1 =
B.buildExtractVectorElement(Ty, Src,
B.buildConstant(s64, 1));
108 B.buildInstr(Opc, {
MI.getOperand(0).
getReg()}, {Elt0, Elt1});
109 MI.eraseFromParent();
116 return Opc == TargetOpcode::G_SEXT || Opc == TargetOpcode::G_SEXT_INREG;
127 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
153 if (TrailingZeroes) {
163 unsigned UseOpc =
UseMI.getOpcode();
164 if (UseOpc == TargetOpcode::G_ADD || UseOpc == TargetOpcode::G_PTR_ADD ||
165 UseOpc == TargetOpcode::G_SUB)
171 APInt ShiftedConstValue = ConstValue.
ashr(TrailingZeroes);
173 unsigned ShiftAmt, AddSubOpc;
175 bool ShiftValUseIsLHS =
true;
177 bool NegateResult =
false;
183 APInt SCVMinus1 = ShiftedConstValue - 1;
184 APInt CVPlus1 = ConstValue + 1;
187 AddSubOpc = TargetOpcode::G_ADD;
190 AddSubOpc = TargetOpcode::G_SUB;
196 APInt CVNegPlus1 = -ConstValue + 1;
197 APInt CVNegMinus1 = -ConstValue - 1;
200 AddSubOpc = TargetOpcode::G_SUB;
201 ShiftValUseIsLHS =
false;
204 AddSubOpc = TargetOpcode::G_ADD;
210 if (NegateResult && TrailingZeroes)
215 auto ShiftedVal =
B.buildShl(Ty,
LHS,
Shift);
217 Register AddSubLHS = ShiftValUseIsLHS ? ShiftedVal.getReg(0) :
LHS;
218 Register AddSubRHS = ShiftValUseIsLHS ?
LHS : ShiftedVal.getReg(0);
219 auto Res =
B.buildInstr(AddSubOpc, {Ty}, {AddSubLHS, AddSubRHS});
220 assert(!(NegateResult && TrailingZeroes) &&
221 "NegateResult and TrailingZeroes cannot both be true for now.");
224 B.buildSub(DstReg,
B.buildConstant(Ty, 0), Res);
228 if (TrailingZeroes) {
229 B.buildShl(DstReg, Res,
B.buildConstant(
LLT::scalar(64), TrailingZeroes));
232 B.buildCopy(DstReg, Res.getReg(0));
240 B.setInstrAndDebugLoc(
MI);
241 ApplyFn(
B,
MI.getOperand(0).getReg());
242 MI.eraseFromParent();
249 auto &
Merge = cast<GMerge>(
MI);
262 MI.setDesc(
B.getTII().get(TargetOpcode::G_ZEXT));
277 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT);
290 MI.setDesc(
B.getTII().get(TargetOpcode::G_ZEXT));
298 if (!
Store.isSimple())
309 return MaybeCst && MaybeCst->isZero();
315 B.setInstrAndDebugLoc(
MI);
318 "Expected a vector store value");
321 auto Zero =
B.buildConstant(NewTy, 0);
322 auto HighPtr =
B.buildPtrAdd(
MRI.
getType(PtrReg), PtrReg,
324 auto &MF = *
MI.getMF();
325 auto *LowMMO = MF.getMachineMemOperand(&
Store.getMMO(), 0, NewTy);
326 auto *HighMMO = MF.getMachineMemOperand(&
Store.getMMO(), 8, NewTy);
327 B.buildStore(Zero, PtrReg, *LowMMO);
328 B.buildStore(Zero, HighPtr, *HighMMO);
329 Store.eraseFromParent();
332 #define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
333 #include "AArch64GenPostLegalizeGICombiner.inc"
334 #undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
337 #define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
338 #include "AArch64GenPostLegalizeGICombiner.inc"
339 #undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
341 class AArch64PostLegalizerCombinerInfo :
public CombinerInfo {
346 AArch64GenPostLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
348 AArch64PostLegalizerCombinerInfo(
bool EnableOpt,
bool OptSize,
bool MinSize,
352 nullptr, EnableOpt, OptSize, MinSize),
354 if (!GeneratedRuleCfg.parseCommandLineOption())
366 MI.getParent()->getParent()->getSubtarget().getLegalizerInfo();
368 AArch64GenPostLegalizerCombinerHelper Generated(GeneratedRuleCfg);
369 return Generated.tryCombineAll(Observer,
MI,
B, Helper);
372 #define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
373 #include "AArch64GenPostLegalizeGICombiner.inc"
374 #undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
380 AArch64PostLegalizerCombiner(
bool IsOptNone =
false);
383 return "AArch64PostLegalizerCombiner";
394 void AArch64PostLegalizerCombiner::getAnalysisUsage(
AnalysisUsage &AU)
const {
409 AArch64PostLegalizerCombiner::AArch64PostLegalizerCombiner(
bool IsOptNone)
414 bool AArch64PostLegalizerCombiner::runOnMachineFunction(
MachineFunction &MF) {
416 MachineFunctionProperties::Property::FailedISel))
419 MachineFunctionProperties::Property::Legalized) &&
420 "Expected a legalized function?");
421 auto *TPC = &getAnalysis<TargetPassConfig>();
425 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
427 IsOptNone ? nullptr : &getAnalysis<MachineDominatorTree>();
428 AArch64PostLegalizerCombinerInfo PCInfo(EnableOpt,
F.hasOptSize(),
429 F.hasMinSize(), KB, MDT);
431 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
432 auto *CSEInfo = &
Wrapper.get(TPC->getCSEConfig());
434 return C.combineMachineInstrs(MF, CSEInfo);
439 "Combine AArch64 MachineInstrs after legalization",
false,
449 return new AArch64PostLegalizerCombiner(IsOptNone);
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
bool matchExtractVecEltPairwiseAdd(MachineInstr &MI, MachineRegisterInfo &MRI, std::tuple< unsigned, LLT, Register > &MatchInfo)
This combine tries do what performExtractVectorEltCombine does in SDAG.
bool hasProperty(Property P) const
INITIALIZE_PASS_BEGIN(AArch64PostLegalizerCombiner, DEBUG_TYPE, "Combine AArch64 MachineInstrs after legalization", false, false) INITIALIZE_PASS_END(AArch64PostLegalizerCombiner
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder & UseMI
The actual analysis pass wrapper.
operand_type_match m_Reg()
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
bool applyAArch64MulConstCombine(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, std::function< void(MachineIRBuilder &B, Register DstReg)> &ApplyFn)
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
static void applySplitStoreZero128(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer)
Combine AArch64 MachineInstrs after legalization
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
bool matchFoldMergeToZext(MachineInstr &MI, MachineRegisterInfo &MRI)
Try to fold a G_MERGE_VALUES of 2 s32 sources, where the second source is a zero, into a G_ZEXT of th...
static bool isZeroExtended(Register R, MachineRegisterInfo &MRI)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
bool matchAArch64MulConstCombine(MachineInstr &MI, MachineRegisterInfo &MRI, std::function< void(MachineIRBuilder &B, Register DstReg)> &ApplyFn)
static bool matchSplitStoreZero128(MachineInstr &MI, MachineRegisterInfo &MRI)
Match a 128b store of zero and split it into two 64 bit stores, for size/performance reasons.
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelKnownBitsInfoAnalysis...
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
(vector float) vec_cmpeq(*A, *B) C
const MachineOperand & getOperand(unsigned i) const
TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Represent the analysis usage information of a pass.
const MachineFunctionProperties & getProperties() const
Get the function properties.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
SpecificConstantMatch m_SpecificICst(int64_t RequestedValue)
Matches a constant equal to RequestedValue.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bind_ty< CmpInst::Predicate > m_Pred(CmpInst::Predicate &P)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
Target-Independent Code Generator Pass Configuration Options.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Helper class to build MachineInstr.
Representation of each machine instruction.
use_instr_iterator use_instr_begin(Register RegNo) const
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
unsigned logBase2() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FunctionPass * createAArch64PostLegalizerCombiner(bool IsOptNone)
ArrayRef< int > getShuffleMask() const
print Print MemDeps of function
Register getReg() const
getReg - Returns the register number.
Class for arbitrary precision integers.
void initializeAArch64PostLegalizerCombinerPass(PassRegistry &)
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...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void applyFoldMergeToZext(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer)
Or< Preds... > m_any_of(Preds &&... preds)
static bool matchMutateAnyExtToZExt(MachineInstr &MI, MachineRegisterInfo &MRI)
Abstract class that contains various methods for clients to notify about changes.
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
bool applyExtractVecEltPairwiseAdd(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, std::tuple< unsigned, LLT, Register > &MatchInfo)
Function & getFunction()
Return the LLVM function that this machine code represents.
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Simple wrapper that does the following.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
FunctionPass class - This class is used to implement most global optimizations.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
AnalysisUsage & addRequired()
static void applyMutateAnyExtToZExt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer)
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Optional< std::vector< StOtherPiece > > Other
static bool isSignExtended(Register R, MachineRegisterInfo &MRI)