30#include "llvm/IR/IntrinsicsAMDGPU.h"
33#define GET_GICOMBINER_DEPS
34#include "AMDGPUGenPreLegalizeGICombiner.inc"
35#undef GET_GICOMBINER_DEPS
37#define DEBUG_TYPE "amdgpu-postlegalizer-combiner"
43#define GET_GICOMBINER_TYPES
44#include "AMDGPUGenPostLegalizeGICombiner.inc"
45#undef GET_GICOMBINER_TYPES
47class AMDGPUPostLegalizerCombinerImpl :
public Combiner {
49 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig;
56 AMDGPUPostLegalizerCombinerImpl(
59 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig,
63 static const char *
getName() {
return "AMDGPUPostLegalizerCombinerImpl"; }
68 struct FMinFMaxLegacyInfo {
76 FMinFMaxLegacyInfo &Info)
const;
78 const FMinFMaxLegacyInfo &Info)
const;
88 struct CvtF32UByteMatchInfo {
94 CvtF32UByteMatchInfo &MatchInfo)
const;
96 const CvtF32UByteMatchInfo &MatchInfo)
const;
102 bool matchCombineSignExtendInReg(
103 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchInfo)
const;
104 void applyCombineSignExtendInReg(
105 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchInfo)
const;
112 bool matchCombine_s_mul_u64(
MachineInstr &
MI,
unsigned &NewOpcode)
const;
117 bool shouldFoldCarryIntoAdd(
Register Src)
const;
120#define GET_GICOMBINER_CLASS_MEMBERS
121#define AMDGPUSubtarget GCNSubtarget
122#include "AMDGPUGenPostLegalizeGICombiner.inc"
123#undef GET_GICOMBINER_CLASS_MEMBERS
124#undef AMDGPUSubtarget
127#define GET_GICOMBINER_IMPL
128#define AMDGPUSubtarget GCNSubtarget
129#include "AMDGPUGenPostLegalizeGICombiner.inc"
130#undef AMDGPUSubtarget
131#undef GET_GICOMBINER_IMPL
133AMDGPUPostLegalizerCombinerImpl::AMDGPUPostLegalizerCombinerImpl(
136 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig,
138 :
Combiner(MF, CInfo, &VT, CSEInfo), RuleConfig(RuleConfig), STI(STI),
139 TII(*STI.getInstrInfo()),
140 Helper(Observer,
B,
false, &VT, MDT, LI, STI),
142#include
"AMDGPUGenPostLegalizeGICombiner.inc"
147bool AMDGPUPostLegalizerCombinerImpl::tryCombineAll(
MachineInstr &
MI)
const {
148 if (tryCombineAllImpl(
MI))
151 switch (
MI.getOpcode()) {
152 case TargetOpcode::G_SHL:
153 case TargetOpcode::G_LSHR:
154 case TargetOpcode::G_ASHR:
164bool AMDGPUPostLegalizerCombinerImpl::matchFMinFMaxLegacy(
165 MachineInstr &
MI, MachineInstr &FCmp, FMinFMaxLegacyInfo &Info)
const {
200void AMDGPUPostLegalizerCombinerImpl::applySelectFCmpToFMinFMaxLegacy(
201 MachineInstr &
MI,
const FMinFMaxLegacyInfo &Info)
const {
203 : AMDGPU::G_AMDGPU_FMIN_LEGACY;
213 B.buildInstr(
Opc, {
MI.getOperand(0)}, {
X,
Y},
MI.getFlags());
215 MI.eraseFromParent();
218bool AMDGPUPostLegalizerCombinerImpl::matchUCharToFloat(
219 MachineInstr &
MI)
const {
226 LLT Ty = MRI.getType(DstReg);
229 unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
230 assert(SrcSize == 16 || SrcSize == 32 || SrcSize == 64);
238void AMDGPUPostLegalizerCombinerImpl::applyUCharToFloat(
239 MachineInstr &
MI)
const {
244 LLT Ty = MRI.getType(DstReg);
245 LLT SrcTy = MRI.getType(SrcReg);
247 SrcReg =
B.buildAnyExtOrTrunc(
S32, SrcReg).getReg(0);
250 B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {DstReg}, {SrcReg},
253 auto Cvt0 =
B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {
S32}, {SrcReg},
255 B.buildFPTrunc(DstReg, Cvt0,
MI.getFlags());
258 MI.eraseFromParent();
261bool AMDGPUPostLegalizerCombinerImpl::matchFDivSqrtToRsqF16(
262 MachineInstr &
MI)
const {
264 return MRI.hasOneNonDBGUse(Sqrt);
267void AMDGPUPostLegalizerCombinerImpl::applyFDivSqrtToRsqF16(
271 LLT DstTy = MRI.getType(Dst);
272 uint32_t
Flags =
MI.getFlags();
273 Register RSQ =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {DstTy})
277 B.buildFMul(Dst, RSQ,
Y, Flags);
278 MI.eraseFromParent();
281bool AMDGPUPostLegalizerCombinerImpl::matchCvtF32UByteN(
282 MachineInstr &
MI, CvtF32UByteMatchInfo &MatchInfo)
const {
292 const unsigned Offset =
MI.getOpcode() - AMDGPU::G_AMDGPU_CVT_F32_UBYTE0;
294 unsigned ShiftOffset = 8 *
Offset;
296 ShiftOffset += ShiftAmt;
298 ShiftOffset -= ShiftAmt;
300 MatchInfo.CvtVal =
Src0;
301 MatchInfo.ShiftOffset = ShiftOffset;
302 return ShiftOffset < 32 && ShiftOffset >= 8 && (ShiftOffset % 8) == 0;
309void AMDGPUPostLegalizerCombinerImpl::applyCvtF32UByteN(
310 MachineInstr &
MI,
const CvtF32UByteMatchInfo &MatchInfo)
const {
311 unsigned NewOpc = AMDGPU::G_AMDGPU_CVT_F32_UBYTE0 + MatchInfo.ShiftOffset / 8;
315 LLT SrcTy = MRI.getType(MatchInfo.CvtVal);
318 CvtSrc =
B.buildAnyExt(
S32, CvtSrc).getReg(0);
322 B.buildInstr(NewOpc, {
MI.getOperand(0)}, {CvtSrc},
MI.getFlags());
323 MI.eraseFromParent();
326bool AMDGPUPostLegalizerCombinerImpl::matchRemoveFcanonicalize(
327 MachineInstr &
MI)
const {
328 const SITargetLowering *TLI =
static_cast<const SITargetLowering *
>(
329 MF.getSubtarget().getTargetLowering());
339bool AMDGPUPostLegalizerCombinerImpl::matchCombineSignExtendInReg(
340 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchData)
const {
342 if (!MRI.hasOneNonDBGUse(LoadReg))
347 MachineInstr *LoadMI = MRI.getVRegDef(LoadReg);
348 int64_t Width =
MI.getOperand(2).getImm();
350 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
351 MatchData = {LoadMI, AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE};
353 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
354 MatchData = {LoadMI, AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT};
356 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
357 MatchData = {LoadMI, AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE};
359 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
360 MatchData = {LoadMI, AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT};
368void AMDGPUPostLegalizerCombinerImpl::applyCombineSignExtendInReg(
369 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchData)
const {
370 auto [LoadMI, NewOpcode] = MatchData;
374 Register SignExtendInsnDst =
MI.getOperand(0).getReg();
377 MI.eraseFromParent();
380bool AMDGPUPostLegalizerCombinerImpl::matchCombine_s_mul_u64(
381 MachineInstr &
MI,
unsigned &NewOpcode)
const {
387 if (VT->getKnownBits(Src1).countMinLeadingZeros() >= 32 &&
388 VT->getKnownBits(Src0).countMinLeadingZeros() >= 32) {
389 NewOpcode = AMDGPU::G_AMDGPU_S_MUL_U64_U32;
393 if (VT->computeNumSignBits(Src1) >= 33 &&
394 VT->computeNumSignBits(Src0) >= 33) {
395 NewOpcode = AMDGPU::G_AMDGPU_S_MUL_I64_I32;
401bool AMDGPUPostLegalizerCombinerImpl::isCarryOut(
Register Reg)
const {
402 const MachineInstr *
Def = MRI.getVRegDef(
Reg);
406 switch (
Def->getOpcode()) {
407 case TargetOpcode::G_UADDO:
408 case TargetOpcode::G_UADDE:
409 case TargetOpcode::G_USUBO:
410 case TargetOpcode::G_USUBE:
411 return Def->getOperand(1).getReg() ==
Reg;
417bool AMDGPUPostLegalizerCombinerImpl::shouldFoldCarryIntoAdd(
427 !MRI.hasOneNonDBGUse(Src) || !isCarryOut(Carry);
434runCombiner(
MachineFunction &MF, GISelValueTracking *VT, GISelCSEInfo *CSEInfo,
435 MachineDominatorTree *MDT,
436 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig,
440 const LegalizerInfo *LI =
ST.getLegalizerInfo();
442 CombinerInfo CInfo(
false,
444 F.hasOptSize(),
F.hasMinSize());
446 CInfo.MaxIterations = 1;
447 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
449 CInfo.EnableFullDCE =
false;
450 AMDGPUPostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, ST,
452 return Impl.combineMachineInstrs();
455class AMDGPUPostLegalizerCombinerLegacy :
public MachineFunctionPass {
459 AMDGPUPostLegalizerCombinerLegacy(
bool IsOptNone =
false);
461 StringRef getPassName()
const override {
462 return "AMDGPUPostLegalizerCombiner";
467 void getAnalysisUsage(AnalysisUsage &AU)
const override;
471 AMDGPUPostLegalizerCombinerImplRuleConfig RuleConfig;
475void AMDGPUPostLegalizerCombinerLegacy::getAnalysisUsage(
476 AnalysisUsage &AU)
const {
479 AU.
addRequired<GISelValueTrackingAnalysisLegacy>();
489AMDGPUPostLegalizerCombinerLegacy::AMDGPUPostLegalizerCombinerLegacy(
491 : MachineFunctionPass(
ID), IsOptNone(IsOptNone) {
492 if (!RuleConfig.parseCommandLineOption())
496bool AMDGPUPostLegalizerCombinerLegacy::runOnMachineFunction(
504 GISelValueTracking *VT =
505 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
506 GISelCSEAnalysisWrapper &
Wrapper =
507 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
508 GISelCSEInfo *CSEInfo =
510 MachineDominatorTree *MDT =
512 : &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
514 return runCombiner(MF, VT, CSEInfo, MDT, RuleConfig, EnableOpt);
517char AMDGPUPostLegalizerCombinerLegacy::ID = 0;
519 "Combine AMDGPU machine instrs after legalization",
false,
524 "Combine AMDGPU machine instrs after legalization",
false,
528 return new AMDGPUPostLegalizerCombinerLegacy(IsOptNone);
537 AMDGPUPostLegalizerCombinerImplRuleConfig RuleConfig;
538 if (!RuleConfig.parseCommandLineOption())
549 if (!runCombiner(MF, &VT, CSEInfo, MDT, RuleConfig,
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define GET_GICOMBINER_CONSTRUCTOR_INITS
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
This contains common combine transformations that may be used in a combine pass.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
Provides AMDGPU specific target descriptions.
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...
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
const HexagonInstrInfo * TII
Contains matchers for matching SSA Machine Instructions.
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static StringRef getName(Value *V)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Target-Independent Code Generator Pass Configuration Options pass.
bool canIgnoreLegacyMinMaxTies(const MachineInstr &MI, Register LHS, Register RHS) const
fmin_legacy/fmax_legacy select s1 on NaN, and on a +0.0/-0.0 tie (s1 for min, s0 for max).
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Predicate getUnorderedPredicate() const
GISelValueTracking * getValueTracking() const
LLVM_ABI bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount) const
FunctionPass class - This class is used to implement most global optimizations.
The actual analysis pass wrapper.
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnal...
bool maskedValueIsZero(Register Val, const APInt &Mask)
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.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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 MachineFunctionProperties & getProperties() const
Get the function properties.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Wrapper class representing virtual and physical registers.
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createAMDGPUPostLegalizeCombinerLegacy(bool IsOptNone)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI std::unique_ptr< CSEConfigBase > getStandardCSEConfigForOpt(CodeGenOptLevel Level)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool shouldSkipOptimizationForOptBisect(IRUnitRef IR)