31#define DEBUG_TYPE "aarch64-prelegalizer-combiner"
34using namespace MIPatternMatch;
40 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT);
42 const unsigned DstSize =
MRI.getType(DstReg).getSizeInBits();
43 if (DstSize != 32 && DstSize != 64)
49 return all_of(
MRI.use_nodbg_instructions(DstReg),
55 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT);
57 const APFloat &ImmValAPF =
MI.getOperand(1).getFPImm()->getValueAPF();
67 assert(
MI.getOpcode() == TargetOpcode::G_ICMP && KB);
85 LLT WideTy =
MRI.getType(WideReg);
98 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
100 LLT WideTy =
MRI.getType(WideReg);
104 auto WideZero =
Builder.buildConstant(WideTy, 0);
106 MI.getOperand(2).setReg(WideReg);
107 MI.getOperand(3).setReg(WideZero.getReg(0));
118 std::pair<uint64_t, uint64_t> &MatchInfo) {
119 assert(
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
121 auto &GlobalOp =
MI.getOperand(1);
122 auto *GV = GlobalOp.getGlobal();
123 if (GV->isThreadLocal())
147 for (
auto &UseInstr :
MRI.use_nodbg_instructions(Dst)) {
148 if (UseInstr.getOpcode() != TargetOpcode::G_PTR_ADD)
151 UseInstr.getOperand(2).getReg(),
MRI);
154 MinOffset = std::min(MinOffset, Cst->Value.getZExtValue());
159 uint64_t CurrOffset = GlobalOp.getOffset();
160 uint64_t NewOffset = MinOffset + CurrOffset;
161 if (NewOffset <= CurrOffset)
173 if (NewOffset >= (1 << 20))
176 Type *
T = GV->getValueType();
178 NewOffset > GV->getParent()->getDataLayout().getTypeAllocSize(
T))
180 MatchInfo = std::make_pair(NewOffset, MinOffset);
187 std::pair<uint64_t, uint64_t> &MatchInfo) {
209 std::tie(
Offset, MinOffset) = MatchInfo;
210 B.setInstrAndDebugLoc(
MI);
212 auto &GlobalOp =
MI.getOperand(1);
213 auto *GV = GlobalOp.getGlobal();
214 GlobalOp.ChangeToGA(GV,
Offset, GlobalOp.getTargetFlags());
217 MI.getOperand(0).setReg(NewGVDst);
221 B.buildConstant(
LLT::scalar(64), -
static_cast<int64_t
>(MinOffset)));
256 auto &
MRI = *
B.getMRI();
265 LLT WideTy0 =
MRI.getType(Op0Wide);
266 LLT WideTy1 =
MRI.getType(Op1Wide);
268 LLT OpTy =
MRI.getType(ResVal);
275 if (Op0WideDef->
getOpcode() != TargetOpcode::G_ASSERT_ZEXT ||
276 Op1WideDef->
getOpcode() != TargetOpcode::G_ASSERT_ZEXT ||
284 (OpTySize != 8 && OpTySize != 16))
288 Register ResStatus =
MI.getOperand(1).getReg();
289 if (!
MRI.hasOneNonDBGUse(ResStatus))
292 if (CondUser->
getOpcode() != TargetOpcode::G_BRCOND)
300 if (
any_of(
MRI.use_nodbg_instructions(ResVal),
303 (I.getParent() == FailMBB || I.getParent() == CurrentMBB);
308 B.setInstrAndDebugLoc(*
MI.getNextNode());
309 MI.eraseFromParent();
312 Register AddDst =
MRI.cloneVirtualRegister(Op0Wide);
313 B.buildInstr(TargetOpcode::G_ADD, {AddDst}, {Op0Wide, Op1Wide});
317 Register CondBit =
MRI.cloneVirtualRegister(Op0Wide);
320 B.buildConstant(
LLT::scalar(32), OpTySize == 8 ? 1 << 8 : 1 << 16));
326 B.buildZExtOrTrunc(ResVal, AddDst);
330 auto OldR = U.getParent()->getOperand(0).getReg();
332 U.getParent()->eraseFromParent();
349#define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
350#include "AArch64GenPreLegalizeGICombiner.inc"
351#undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
354#define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
355#include "AArch64GenPreLegalizeGICombiner.inc"
356#undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
358class AArch64PreLegalizerCombinerInfo :
public CombinerInfo {
361 AArch64GenPreLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
364 AArch64PreLegalizerCombinerInfo(
bool EnableOpt,
bool OptSize,
bool MinSize,
367 nullptr, EnableOpt, OptSize, MinSize),
369 if (!GeneratedRuleCfg.parseCommandLineOption())
380 const auto *LI =
MI.getMF()->getSubtarget().getLegalizerInfo();
382 AArch64GenPreLegalizerCombinerHelper
Generated(GeneratedRuleCfg, Helper);
387 unsigned Opc =
MI.getOpcode();
389 case TargetOpcode::G_CONCAT_VECTORS:
390 return Helper.tryCombineConcatVectors(
MI);
391 case TargetOpcode::G_SHUFFLE_VECTOR:
392 return Helper.tryCombineShuffleVector(
MI);
393 case TargetOpcode::G_UADDO:
395 case TargetOpcode::G_MEMCPY_INLINE:
396 return Helper.tryEmitMemcpyInline(
MI);
397 case TargetOpcode::G_MEMCPY:
398 case TargetOpcode::G_MEMMOVE:
399 case TargetOpcode::G_MEMSET: {
402 unsigned MaxLen = EnableOpt ? 0 : 32;
404 if (Helper.tryCombineMemCpyFamily(
MI, MaxLen))
406 if (Opc == TargetOpcode::G_MEMSET)
415#define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
416#include "AArch64GenPreLegalizeGICombiner.inc"
417#undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
426 AArch64PreLegalizerCombiner();
436void AArch64PreLegalizerCombiner::getAnalysisUsage(
AnalysisUsage &AU)
const {
449AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner()
454bool AArch64PreLegalizerCombiner::runOnMachineFunction(
MachineFunction &MF) {
456 MachineFunctionProperties::Property::FailedISel))
458 auto &TPC = getAnalysis<TargetPassConfig>();
462 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
463 auto *CSEInfo = &
Wrapper.get(TPC.getCSEConfig());
468 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
470 AArch64PreLegalizerCombinerInfo PCInfo(EnableOpt,
F.hasOptSize(),
471 F.hasMinSize(), KB, MDT);
473 return C.combineMachineInstrs(MF, CSEInfo);
476char AArch64PreLegalizerCombiner::ID = 0;
478 "Combine AArch64 machine instrs before legalization",
490 return new AArch64PreLegalizerCombiner();
unsigned const MachineRegisterInfo * MRI
static bool matchICmpRedundantTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, GISelKnownBits *KB, Register &MatchInfo)
Try to match a G_ICMP of a G_TRUNC with zero, in which the truncated bits are sign bits.
static bool applyFoldGlobalOffset(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer, std::pair< uint64_t, uint64_t > &MatchInfo)
static bool applyICmpRedundantTrunc(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &Builder, GISelChangeObserver &Observer, Register &WideReg)
static bool matchFConstantToConstant(MachineInstr &MI, MachineRegisterInfo &MRI)
Return true if a G_FCONSTANT instruction is known to be better-represented as a G_CONSTANT.
static bool tryToSimplifyUADDO(MachineInstr &MI, MachineIRBuilder &B, CombinerHelper &Helper, GISelChangeObserver &Observer)
static void applyFConstantToConstant(MachineInstr &MI)
Change a G_FCONSTANT into a G_CONSTANT.
static bool matchFoldGlobalOffset(MachineInstr &MI, MachineRegisterInfo &MRI, std::pair< uint64_t, uint64_t > &MatchInfo)
Combine AArch64 machine instrs before legalization
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This contains common combine transformations that may be used in a combine pass,or by the target else...
Interface for Targets to specify which operations are combined how and when.
This contains common code to drive combines.
Provides analysis for querying information about KnownBits during GISel passes.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Target-Independent Code Generator Pass Configuration Options pass.
AArch64PreLegalizerCombinerHelperState(CombinerHelper &Helper)
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
APInt bitcastToAPInt() const
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const
MachineRegisterInfo::replaceRegWith() and inform the observer of the changes.
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const =0
Attempt to combine instructions using MI as the root.
FunctionPass class - This class is used to implement most global optimizations.
The actual analysis pass wrapper.
Simple wrapper that does the following.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
virtual void erasingInstr(MachineInstr &MI)=0
An instruction is about to be erased.
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelKnownBitsInfoAnalysis...
unsigned computeNumSignBits(Register R, const APInt &DemandedElts, unsigned Depth=0)
bool isEquality() const
Return true if this predicate is either EQ or NE.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
bool hasProperty(Property P) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
StringRef - Represent a constant reference to a string, i.e.
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
A Use represents the edge between a Value definition and its users.
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 ...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(int64_t RequestedValue)
Matches a constant equal to RequestedValue.
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createAArch64PreLegalizerCombiner()
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void initializeAArch64PreLegalizerCombinerPass(PassRegistry &)
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
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...
auto instrs(const MachineBasicBlock &BB)