LLVM  14.0.0git
R600ClauseMergePass.cpp
Go to the documentation of this file.
1 //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===//
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 //
9 /// \file
10 /// R600EmitClauseMarker pass emits CFAlu instruction in a conservative maneer.
11 /// This pass is merging consecutive CFAlus where applicable.
12 /// It needs to be called after IfCvt for best results.
13 //===----------------------------------------------------------------------===//
14 
16 #include "R600.h"
17 #include "R600Subtarget.h"
18 
19 using namespace llvm;
20 
21 #define DEBUG_TYPE "r600mergeclause"
22 
23 namespace {
24 
25 static bool isCFAlu(const MachineInstr &MI) {
26  switch (MI.getOpcode()) {
27  case R600::CF_ALU:
28  case R600::CF_ALU_PUSH_BEFORE:
29  return true;
30  default:
31  return false;
32  }
33 }
34 
35 class R600ClauseMergePass : public MachineFunctionPass {
36 
37 private:
38  const R600InstrInfo *TII;
39 
40  unsigned getCFAluSize(const MachineInstr &MI) const;
41  bool isCFAluEnabled(const MachineInstr &MI) const;
42 
43  /// IfCvt pass can generate "disabled" ALU clause marker that need to be
44  /// removed and their content affected to the previous alu clause.
45  /// This function parse instructions after CFAlu until it find a disabled
46  /// CFAlu and merge the content, or an enabled CFAlu.
47  void cleanPotentialDisabledCFAlu(MachineInstr &CFAlu) const;
48 
49  /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if
50  /// it is the case.
51  bool mergeIfPossible(MachineInstr &RootCFAlu,
52  const MachineInstr &LatrCFAlu) const;
53 
54 public:
55  static char ID;
56 
57  R600ClauseMergePass() : MachineFunctionPass(ID) { }
58 
59  bool runOnMachineFunction(MachineFunction &MF) override;
60 
61  StringRef getPassName() const override;
62 };
63 
64 } // end anonymous namespace
65 
66 INITIALIZE_PASS_BEGIN(R600ClauseMergePass, DEBUG_TYPE,
67  "R600 Clause Merge", false, false)
68 INITIALIZE_PASS_END(R600ClauseMergePass, DEBUG_TYPE,
69  "R600 Clause Merge", false, false)
70 
71 char R600ClauseMergePass::ID = 0;
72 
73 char &llvm::R600ClauseMergePassID = R600ClauseMergePass::ID;
74 
75 unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr &MI) const {
76  assert(isCFAlu(MI));
77  return MI
78  .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::COUNT))
79  .getImm();
80 }
81 
82 bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr &MI) const {
83  assert(isCFAlu(MI));
84  return MI
85  .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::Enabled))
86  .getImm();
87 }
88 
89 void R600ClauseMergePass::cleanPotentialDisabledCFAlu(
90  MachineInstr &CFAlu) const {
91  int CntIdx = TII->getOperandIdx(R600::CF_ALU, R600::OpName::COUNT);
92  MachineBasicBlock::iterator I = CFAlu, E = CFAlu.getParent()->end();
93  I++;
94  do {
95  while (I != E && !isCFAlu(*I))
96  I++;
97  if (I == E)
98  return;
99  MachineInstr &MI = *I++;
100  if (isCFAluEnabled(MI))
101  break;
102  CFAlu.getOperand(CntIdx).setImm(getCFAluSize(CFAlu) + getCFAluSize(MI));
103  MI.eraseFromParent();
104  } while (I != E);
105 }
106 
107 bool R600ClauseMergePass::mergeIfPossible(MachineInstr &RootCFAlu,
108  const MachineInstr &LatrCFAlu) const {
109  assert(isCFAlu(RootCFAlu) && isCFAlu(LatrCFAlu));
110  int CntIdx = TII->getOperandIdx(R600::CF_ALU, R600::OpName::COUNT);
111  unsigned RootInstCount = getCFAluSize(RootCFAlu),
112  LaterInstCount = getCFAluSize(LatrCFAlu);
113  unsigned CumuledInsts = RootInstCount + LaterInstCount;
114  if (CumuledInsts >= TII->getMaxAlusPerClause()) {
115  LLVM_DEBUG(dbgs() << "Excess inst counts\n");
116  return false;
117  }
118  if (RootCFAlu.getOpcode() == R600::CF_ALU_PUSH_BEFORE)
119  return false;
120  // Is KCache Bank 0 compatible ?
121  int Mode0Idx =
122  TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE0);
123  int KBank0Idx =
124  TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK0);
125  int KBank0LineIdx =
126  TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_ADDR0);
127  if (LatrCFAlu.getOperand(Mode0Idx).getImm() &&
128  RootCFAlu.getOperand(Mode0Idx).getImm() &&
129  (LatrCFAlu.getOperand(KBank0Idx).getImm() !=
130  RootCFAlu.getOperand(KBank0Idx).getImm() ||
131  LatrCFAlu.getOperand(KBank0LineIdx).getImm() !=
132  RootCFAlu.getOperand(KBank0LineIdx).getImm())) {
133  LLVM_DEBUG(dbgs() << "Wrong KC0\n");
134  return false;
135  }
136  // Is KCache Bank 1 compatible ?
137  int Mode1Idx =
138  TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE1);
139  int KBank1Idx =
140  TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK1);
141  int KBank1LineIdx =
142  TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_ADDR1);
143  if (LatrCFAlu.getOperand(Mode1Idx).getImm() &&
144  RootCFAlu.getOperand(Mode1Idx).getImm() &&
145  (LatrCFAlu.getOperand(KBank1Idx).getImm() !=
146  RootCFAlu.getOperand(KBank1Idx).getImm() ||
147  LatrCFAlu.getOperand(KBank1LineIdx).getImm() !=
148  RootCFAlu.getOperand(KBank1LineIdx).getImm())) {
149  LLVM_DEBUG(dbgs() << "Wrong KC0\n");
150  return false;
151  }
152  if (LatrCFAlu.getOperand(Mode0Idx).getImm()) {
153  RootCFAlu.getOperand(Mode0Idx).setImm(
154  LatrCFAlu.getOperand(Mode0Idx).getImm());
155  RootCFAlu.getOperand(KBank0Idx).setImm(
156  LatrCFAlu.getOperand(KBank0Idx).getImm());
157  RootCFAlu.getOperand(KBank0LineIdx)
158  .setImm(LatrCFAlu.getOperand(KBank0LineIdx).getImm());
159  }
160  if (LatrCFAlu.getOperand(Mode1Idx).getImm()) {
161  RootCFAlu.getOperand(Mode1Idx).setImm(
162  LatrCFAlu.getOperand(Mode1Idx).getImm());
163  RootCFAlu.getOperand(KBank1Idx).setImm(
164  LatrCFAlu.getOperand(KBank1Idx).getImm());
165  RootCFAlu.getOperand(KBank1LineIdx)
166  .setImm(LatrCFAlu.getOperand(KBank1LineIdx).getImm());
167  }
168  RootCFAlu.getOperand(CntIdx).setImm(CumuledInsts);
169  RootCFAlu.setDesc(TII->get(LatrCFAlu.getOpcode()));
170  return true;
171 }
172 
173 bool R600ClauseMergePass::runOnMachineFunction(MachineFunction &MF) {
174  if (skipFunction(MF.getFunction()))
175  return false;
176 
178  TII = ST.getInstrInfo();
179 
180  for (MachineBasicBlock &MBB : MF) {
182  MachineBasicBlock::iterator LatestCFAlu = E;
183  while (I != E) {
184  MachineInstr &MI = *I++;
185  if ((!TII->canBeConsideredALU(MI) && !isCFAlu(MI)) ||
186  TII->mustBeLastInClause(MI.getOpcode()))
187  LatestCFAlu = E;
188  if (!isCFAlu(MI))
189  continue;
190  cleanPotentialDisabledCFAlu(MI);
191 
192  if (LatestCFAlu != E && mergeIfPossible(*LatestCFAlu, MI)) {
193  MI.eraseFromParent();
194  } else {
195  assert(MI.getOperand(8).getImm() && "CF ALU instruction disabled");
196  LatestCFAlu = MI;
197  }
198  }
199  }
200  return false;
201 }
202 
203 StringRef R600ClauseMergePass::getPassName() const {
204  return "R600 Merge Clause Markers Pass";
205 }
206 
208  return new R600ClauseMergePass();
209 }
DEBUG_TYPE
#define DEBUG_TYPE
Definition: R600ClauseMergePass.cpp:21
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
Merge
R600 Clause Merge
Definition: R600ClauseMergePass.cpp:69
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::MachineOperand::setImm
void setImm(int64_t immVal)
Definition: MachineOperand.h:655
llvm::createR600ClauseMergePass
FunctionPass * createR600ClauseMergePass()
Definition: R600ClauseMergePass.cpp:207
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
R600.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::MachineOperand::getImm
int64_t getImm() const
Definition: MachineOperand.h:537
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:499
false
Definition: StackSlotColoring.cpp:142
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:127
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
R600MCTargetDesc.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:641
llvm::Clause
Definition: DirectiveEmitter.h:123
llvm::R600Subtarget
Definition: R600Subtarget.h:29
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
const
aarch64 promote const
Definition: AArch64PromoteConstant.cpp:232
llvm::ARM_MB::ST
@ ST
Definition: ARMBaseInfo.h:73
I
#define I(x, y, z)
Definition: MD5.cpp:58
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(R600ClauseMergePass, DEBUG_TYPE, "R600 Clause Merge", false, false) INITIALIZE_PASS_END(R600ClauseMergePass
llvm::MachineFunction
Definition: MachineFunction.h:241
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:489
llvm::MachineInstr::getParent
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:286
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:607
llvm::R600ClauseMergePassID
char & R600ClauseMergePassID
Definition: R600ClauseMergePass.cpp:73
Enabled
static bool Enabled
Definition: Statistic.cpp:46
R600Subtarget.h
llvm::R600InstrInfo
Definition: R600InstrInfo.h:38
llvm::MachineInstr::setDesc
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
Definition: MachineInstr.h:1736
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:272
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::MachineInstrBundleIterator< MachineInstr >
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:274
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38