28#include "llvm/IR/IntrinsicsAMDGPU.h"
31#define GET_GICOMBINER_DEPS
32#include "AMDGPUGenPreLegalizeGICombiner.inc"
33#undef GET_GICOMBINER_DEPS
35#define DEBUG_TYPE "amdgpu-postlegalizer-combiner"
41#define GET_GICOMBINER_TYPES
42#include "AMDGPUGenPostLegalizeGICombiner.inc"
43#undef GET_GICOMBINER_TYPES
45class AMDGPUPostLegalizerCombinerImpl :
public Combiner {
47 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig;
54 AMDGPUPostLegalizerCombinerImpl(
57 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig,
61 static const char *
getName() {
return "AMDGPUPostLegalizerCombinerImpl"; }
66 struct FMinFMaxLegacyInfo {
74 FMinFMaxLegacyInfo &Info)
const;
76 const FMinFMaxLegacyInfo &Info)
const;
86 struct CvtF32UByteMatchInfo {
92 CvtF32UByteMatchInfo &MatchInfo)
const;
94 const CvtF32UByteMatchInfo &MatchInfo)
const;
100 bool matchCombineSignExtendInReg(
101 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchInfo)
const;
102 void applyCombineSignExtendInReg(
103 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchInfo)
const;
110 bool matchCombine_s_mul_u64(
MachineInstr &
MI,
unsigned &NewOpcode)
const;
113#define GET_GICOMBINER_CLASS_MEMBERS
114#define AMDGPUSubtarget GCNSubtarget
115#include "AMDGPUGenPostLegalizeGICombiner.inc"
116#undef GET_GICOMBINER_CLASS_MEMBERS
117#undef AMDGPUSubtarget
120#define GET_GICOMBINER_IMPL
121#define AMDGPUSubtarget GCNSubtarget
122#include "AMDGPUGenPostLegalizeGICombiner.inc"
123#undef AMDGPUSubtarget
124#undef GET_GICOMBINER_IMPL
126AMDGPUPostLegalizerCombinerImpl::AMDGPUPostLegalizerCombinerImpl(
129 const AMDGPUPostLegalizerCombinerImplRuleConfig &RuleConfig,
131 :
Combiner(MF, CInfo, &VT, CSEInfo), RuleConfig(RuleConfig), STI(STI),
132 TII(*STI.getInstrInfo()),
133 Helper(Observer,
B,
false, &VT, MDT, LI, STI),
135#include
"AMDGPUGenPostLegalizeGICombiner.inc"
140bool AMDGPUPostLegalizerCombinerImpl::tryCombineAll(
MachineInstr &
MI)
const {
141 if (tryCombineAllImpl(
MI))
144 switch (
MI.getOpcode()) {
145 case TargetOpcode::G_SHL:
146 case TargetOpcode::G_LSHR:
147 case TargetOpcode::G_ASHR:
157bool AMDGPUPostLegalizerCombinerImpl::matchFMinFMaxLegacy(
158 MachineInstr &
MI, MachineInstr &FCmp, FMinFMaxLegacyInfo &Info)
const {
171 if ((
Info.LHS != True ||
Info.RHS != False) &&
172 (
Info.LHS != False ||
Info.RHS != True))
178 if (
Info.LHS != True)
185void AMDGPUPostLegalizerCombinerImpl::applySelectFCmpToFMinFMaxLegacy(
186 MachineInstr &
MI,
const FMinFMaxLegacyInfo &Info)
const {
188 : AMDGPU::G_AMDGPU_FMIN_LEGACY;
198 B.buildInstr(
Opc, {
MI.getOperand(0)}, {
X,
Y},
MI.getFlags());
200 MI.eraseFromParent();
203bool AMDGPUPostLegalizerCombinerImpl::matchUCharToFloat(
204 MachineInstr &
MI)
const {
211 LLT Ty = MRI.getType(DstReg);
214 unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
215 assert(SrcSize == 16 || SrcSize == 32 || SrcSize == 64);
223void AMDGPUPostLegalizerCombinerImpl::applyUCharToFloat(
224 MachineInstr &
MI)
const {
229 LLT Ty = MRI.getType(DstReg);
230 LLT SrcTy = MRI.getType(SrcReg);
232 SrcReg =
B.buildAnyExtOrTrunc(
S32, SrcReg).getReg(0);
235 B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {DstReg}, {SrcReg},
238 auto Cvt0 =
B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {
S32}, {SrcReg},
240 B.buildFPTrunc(DstReg, Cvt0,
MI.getFlags());
243 MI.eraseFromParent();
246bool AMDGPUPostLegalizerCombinerImpl::matchFDivSqrtToRsqF16(
247 MachineInstr &
MI)
const {
249 return MRI.hasOneNonDBGUse(Sqrt);
252void AMDGPUPostLegalizerCombinerImpl::applyFDivSqrtToRsqF16(
256 LLT DstTy = MRI.getType(Dst);
257 uint32_t
Flags =
MI.getFlags();
258 Register RSQ =
B.buildIntrinsic(Intrinsic::amdgcn_rsq, {DstTy})
262 B.buildFMul(Dst, RSQ,
Y, Flags);
263 MI.eraseFromParent();
266bool AMDGPUPostLegalizerCombinerImpl::matchCvtF32UByteN(
267 MachineInstr &
MI, CvtF32UByteMatchInfo &MatchInfo)
const {
277 const unsigned Offset =
MI.getOpcode() - AMDGPU::G_AMDGPU_CVT_F32_UBYTE0;
279 unsigned ShiftOffset = 8 *
Offset;
281 ShiftOffset += ShiftAmt;
283 ShiftOffset -= ShiftAmt;
285 MatchInfo.CvtVal = Src0;
286 MatchInfo.ShiftOffset = ShiftOffset;
287 return ShiftOffset < 32 && ShiftOffset >= 8 && (ShiftOffset % 8) == 0;
294void AMDGPUPostLegalizerCombinerImpl::applyCvtF32UByteN(
295 MachineInstr &
MI,
const CvtF32UByteMatchInfo &MatchInfo)
const {
296 unsigned NewOpc = AMDGPU::G_AMDGPU_CVT_F32_UBYTE0 + MatchInfo.ShiftOffset / 8;
300 LLT SrcTy = MRI.getType(MatchInfo.CvtVal);
303 CvtSrc =
B.buildAnyExt(
S32, CvtSrc).getReg(0);
307 B.buildInstr(NewOpc, {
MI.getOperand(0)}, {CvtSrc},
MI.getFlags());
308 MI.eraseFromParent();
311bool AMDGPUPostLegalizerCombinerImpl::matchRemoveFcanonicalize(
312 MachineInstr &
MI)
const {
313 const SITargetLowering *TLI =
static_cast<const SITargetLowering *
>(
314 MF.getSubtarget().getTargetLowering());
324bool AMDGPUPostLegalizerCombinerImpl::matchCombineSignExtendInReg(
325 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchData)
const {
327 if (!MRI.hasOneNonDBGUse(LoadReg))
332 MachineInstr *LoadMI = MRI.getVRegDef(LoadReg);
333 int64_t Width =
MI.getOperand(2).getImm();
335 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
336 MatchData = {LoadMI, AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE};
338 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
339 MatchData = {LoadMI, AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT};
341 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
342 MatchData = {LoadMI, AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE};
344 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
345 MatchData = {LoadMI, AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT};
353void AMDGPUPostLegalizerCombinerImpl::applyCombineSignExtendInReg(
354 MachineInstr &
MI, std::pair<MachineInstr *, unsigned> &MatchData)
const {
355 auto [LoadMI, NewOpcode] = MatchData;
359 Register SignExtendInsnDst =
MI.getOperand(0).getReg();
362 MI.eraseFromParent();
365bool AMDGPUPostLegalizerCombinerImpl::matchCombine_s_mul_u64(
366 MachineInstr &
MI,
unsigned &NewOpcode)
const {
372 if (VT->getKnownBits(Src1).countMinLeadingZeros() >= 32 &&
373 VT->getKnownBits(Src0).countMinLeadingZeros() >= 32) {
374 NewOpcode = AMDGPU::G_AMDGPU_S_MUL_U64_U32;
378 if (VT->computeNumSignBits(Src1) >= 33 &&
379 VT->computeNumSignBits(Src0) >= 33) {
380 NewOpcode = AMDGPU::G_AMDGPU_S_MUL_I64_I32;
389class AMDGPUPostLegalizerCombiner :
public MachineFunctionPass {
393 AMDGPUPostLegalizerCombiner(
bool IsOptNone =
false);
395 StringRef getPassName()
const override {
396 return "AMDGPUPostLegalizerCombiner";
401 void getAnalysisUsage(AnalysisUsage &AU)
const override;
405 AMDGPUPostLegalizerCombinerImplRuleConfig RuleConfig;
409void AMDGPUPostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU)
const {
412 AU.
addRequired<GISelValueTrackingAnalysisLegacy>();
420AMDGPUPostLegalizerCombiner::AMDGPUPostLegalizerCombiner(
bool IsOptNone)
421 : MachineFunctionPass(
ID), IsOptNone(IsOptNone) {
422 if (!RuleConfig.parseCommandLineOption())
426bool AMDGPUPostLegalizerCombiner::runOnMachineFunction(
MachineFunction &MF) {
438 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
441 : &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
444 LI, EnableOpt,
F.hasOptSize(),
F.hasMinSize());
446 CInfo.MaxIterations = 1;
449 CInfo.EnableFullDCE =
false;
450 AMDGPUPostLegalizerCombinerImpl Impl(MF, CInfo, *VT,
nullptr,
451 RuleConfig, ST, MDT, LI);
452 return Impl.combineMachineInstrs();
455char AMDGPUPostLegalizerCombiner::ID = 0;
457 "Combine AMDGPU machine instrs after legalization",
false,
461 "Combine AMDGPU machine instrs after legalization",
false,
465 return new AMDGPUPostLegalizerCombiner(IsOptNone);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define GET_GICOMBINER_CONSTRUCTOR_INITS
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")
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.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
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.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
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:
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
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.
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.
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.
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()
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.
This is an optimization pass for GlobalISel generic memory operations.
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.
FunctionPass * createAMDGPUPostLegalizeCombiner(bool IsOptNone)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ SinglePass
Enables Observer-based DCE and additional heuristics that retry combining defined and used instructio...