LLVM  14.0.0git
PPCMacroFusion.cpp
Go to the documentation of this file.
1 //===- PPCMacroFusion.cpp - PowerPC Macro Fusion --------------------------===//
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 This file contains the PowerPC implementation of the DAG scheduling
10 /// mutation to pair instructions back to back.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "PPC.h"
15 #include "PPCSubtarget.h"
16 #include "llvm/ADT/DenseSet.h"
18 
19 using namespace llvm;
20 namespace {
21 
22 class FusionFeature {
23 public:
24  typedef SmallDenseSet<unsigned> FusionOpSet;
25 
26  enum FusionKind {
27  #define FUSION_KIND(KIND) FK_##KIND
28  #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) \
29  FUSION_KIND(KIND),
30  #include "PPCMacroFusion.def"
31  FUSION_KIND(END)
32  };
33 private:
34  // Each fusion feature is assigned with one fusion kind. All the
35  // instructions with the same fusion kind have the same fusion characteristic.
36  FusionKind Kd;
37  // True if this feature is enabled.
38  bool Supported;
39  // li rx, si
40  // load rt, ra, rx
41  // The dependent operand index in the second op(load). And the negative means
42  // it could be any one.
43  int DepOpIdx;
44  // The first fusion op set.
45  FusionOpSet OpSet1;
46  // The second fusion op set.
47  FusionOpSet OpSet2;
48 public:
49  FusionFeature(FusionKind Kind, bool HasFeature, int Index,
50  const FusionOpSet &First, const FusionOpSet &Second) :
51  Kd(Kind), Supported(HasFeature), DepOpIdx(Index), OpSet1(First),
52  OpSet2(Second) {}
53 
54  bool hasOp1(unsigned Opc) const { return OpSet1.contains(Opc); }
55  bool hasOp2(unsigned Opc) const { return OpSet2.contains(Opc); }
56  bool isSupported() const { return Supported; }
57  Optional<unsigned> depOpIdx() const {
58  if (DepOpIdx < 0)
59  return None;
60  return DepOpIdx;
61  }
62 
63  FusionKind getKind() const { return Kd; }
64 };
65 
66 static bool matchingRegOps(const MachineInstr &FirstMI,
67  int FirstMIOpIndex,
68  const MachineInstr &SecondMI,
69  int SecondMIOpIndex) {
70  const MachineOperand &Op1 = FirstMI.getOperand(FirstMIOpIndex);
71  const MachineOperand &Op2 = SecondMI.getOperand(SecondMIOpIndex);
72  if (!Op1.isReg() || !Op2.isReg())
73  return false;
74 
75  return Op1.getReg() == Op2.getReg();
76 }
77 
78 static bool matchingImmOps(const MachineInstr &MI,
79  int MIOpIndex,
80  int64_t Expect,
81  unsigned ExtendFrom = 64) {
82  const MachineOperand &Op = MI.getOperand(MIOpIndex);
83  if (!Op.isImm())
84  return false;
85  int64_t Imm = Op.getImm();
86  if (ExtendFrom < 64)
87  Imm = SignExtend64(Imm, ExtendFrom);
88  return Imm == Expect;
89 }
90 
91 // Return true if the FirstMI meets the constraints of SecondMI according to
92 // fusion specification.
93 static bool checkOpConstraints(FusionFeature::FusionKind Kd,
94  const MachineInstr &FirstMI,
95  const MachineInstr &SecondMI) {
96  switch (Kd) {
97  // The hardware didn't require any specific check for the fused instructions'
98  // operands. Therefore, return true to indicate that, it is fusable.
99  default: return true;
100  // [addi rt,ra,si - lxvd2x xt,ra,rb] etc.
101  case FusionFeature::FK_AddiLoad: {
102  // lxvd2x(ra) cannot be zero
103  const MachineOperand &RA = SecondMI.getOperand(1);
104  if (!RA.isReg())
105  return true;
106 
107  return Register::isVirtualRegister(RA.getReg()) ||
108  (RA.getReg() != PPC::ZERO && RA.getReg() != PPC::ZERO8);
109  }
110  // [addis rt,ra,si - ld rt,ds(ra)] etc.
111  case FusionFeature::FK_AddisLoad: {
112  const MachineOperand &RT = SecondMI.getOperand(0);
113  if (!RT.isReg())
114  return true;
115 
116  // Only check it for non-virtual register.
118  // addis(rt) = ld(ra) = ld(rt)
119  // ld(rt) cannot be zero
120  if (!matchingRegOps(SecondMI, 0, SecondMI, 2) ||
121  (RT.getReg() == PPC::ZERO || RT.getReg() == PPC::ZERO8))
122  return false;
123 
124  // addis(si) first 12 bits must be all 1s or all 0s
125  const MachineOperand &SI = FirstMI.getOperand(2);
126  if (!SI.isImm())
127  return true;
128  int64_t Imm = SI.getImm();
129  if (((Imm & 0xFFF0) != 0) && ((Imm & 0xFFF0) != 0xFFF0))
130  return false;
131 
132  // If si = 1111111111110000 and the msb of the d/ds field of the load equals
133  // 1, then fusion does not occur.
134  if ((Imm & 0xFFF0) == 0xFFF0) {
135  const MachineOperand &D = SecondMI.getOperand(1);
136  if (!D.isImm())
137  return true;
138 
139  // 14 bit for DS field, while 16 bit for D field.
140  int MSB = 15;
141  if (SecondMI.getOpcode() == PPC::LD)
142  MSB = 13;
143 
144  return (D.getImm() & (1ULL << MSB)) == 0;
145  }
146  return true;
147  }
148 
149  case FusionFeature::FK_SldiAdd:
150  return (matchingImmOps(FirstMI, 2, 3) && matchingImmOps(FirstMI, 3, 60)) ||
151  (matchingImmOps(FirstMI, 2, 6) && matchingImmOps(FirstMI, 3, 57));
152 
153  // rldicl rx, ra, 1, 0 - xor
154  case FusionFeature::FK_RotateLeftXor:
155  return matchingImmOps(FirstMI, 2, 1) && matchingImmOps(FirstMI, 3, 0);
156 
157  // rldicr rx, ra, 1, 63 - xor
158  case FusionFeature::FK_RotateRightXor:
159  return matchingImmOps(FirstMI, 2, 1) && matchingImmOps(FirstMI, 3, 63);
160 
161  // We actually use CMPW* and CMPD*, 'l' doesn't exist as an operand in instr.
162 
163  // { lbz,lbzx,lhz,lhzx,lwz,lwzx } - cmpi 0,1,rx,{ 0,1,-1 }
164  // { lbz,lbzx,lhz,lhzx,lwz,lwzx } - cmpli 0,L,rx,{ 0,1 }
165  case FusionFeature::FK_LoadCmp1:
166  // { ld,ldx } - cmpi 0,1,rx,{ 0,1,-1 }
167  // { ld,ldx } - cmpli 0,1,rx,{ 0,1 }
168  case FusionFeature::FK_LoadCmp2: {
169  const MachineOperand &BT = SecondMI.getOperand(0);
170  if (!BT.isReg() ||
171  (!Register::isVirtualRegister(BT.getReg()) && BT.getReg() != PPC::CR0))
172  return false;
173  if (SecondMI.getOpcode() == PPC::CMPDI &&
174  matchingImmOps(SecondMI, 2, -1, 16))
175  return true;
176  return matchingImmOps(SecondMI, 2, 0) || matchingImmOps(SecondMI, 2, 1);
177  }
178 
179  // { lha,lhax,lwa,lwax } - cmpi 0,L,rx,{ 0,1,-1 }
180  case FusionFeature::FK_LoadCmp3: {
181  const MachineOperand &BT = SecondMI.getOperand(0);
182  if (!BT.isReg() ||
183  (!Register::isVirtualRegister(BT.getReg()) && BT.getReg() != PPC::CR0))
184  return false;
185  return matchingImmOps(SecondMI, 2, 0) || matchingImmOps(SecondMI, 2, 1) ||
186  matchingImmOps(SecondMI, 2, -1, 16);
187  }
188 
189  // mtctr - { bcctr,bcctrl }
190  case FusionFeature::FK_ZeroMoveCTR:
191  // ( mtctr rx ) is alias of ( mtspr 9, rx )
192  return (FirstMI.getOpcode() != PPC::MTSPR &&
193  FirstMI.getOpcode() != PPC::MTSPR8) ||
194  matchingImmOps(FirstMI, 0, 9);
195 
196  // mtlr - { bclr,bclrl }
197  case FusionFeature::FK_ZeroMoveLR:
198  // ( mtlr rx ) is alias of ( mtspr 8, rx )
199  return (FirstMI.getOpcode() != PPC::MTSPR &&
200  FirstMI.getOpcode() != PPC::MTSPR8) ||
201  matchingImmOps(FirstMI, 0, 8);
202 
203  // addis rx,ra,si - addi rt,rx,SI, SI >= 0
204  case FusionFeature::FK_AddisAddi: {
205  const MachineOperand &RA = FirstMI.getOperand(1);
206  const MachineOperand &SI = SecondMI.getOperand(2);
207  if (!SI.isImm() || !RA.isReg())
208  return false;
209  if (RA.getReg() == PPC::ZERO || RA.getReg() == PPC::ZERO8)
210  return false;
211  return SignExtend64(SI.getImm(), 16) >= 0;
212  }
213 
214  // addi rx,ra,si - addis rt,rx,SI, ra > 0, SI >= 2
215  case FusionFeature::FK_AddiAddis: {
216  const MachineOperand &RA = FirstMI.getOperand(1);
217  const MachineOperand &SI = FirstMI.getOperand(2);
218  if (!SI.isImm() || !RA.isReg())
219  return false;
220  if (RA.getReg() == PPC::ZERO || RA.getReg() == PPC::ZERO8)
221  return false;
222  int64_t ExtendedSI = SignExtend64(SI.getImm(), 16);
223  return ExtendedSI >= 2;
224  }
225  }
226 
227  llvm_unreachable("All the cases should have been handled");
228  return true;
229 }
230 
231 /// Check if the instr pair, FirstMI and SecondMI, should be fused together.
232 /// Given SecondMI, when FirstMI is unspecified, then check if SecondMI may be
233 /// part of a fused pair at all.
234 static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
235  const TargetSubtargetInfo &TSI,
236  const MachineInstr *FirstMI,
237  const MachineInstr &SecondMI) {
238  // We use the PPC namespace to avoid the need to prefix opcodes with PPC:: in
239  // the def file.
240  using namespace PPC;
241 
242  const PPCSubtarget &ST = static_cast<const PPCSubtarget&>(TSI);
243  static const FusionFeature FusionFeatures[] = {
244  #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) { \
245  FusionFeature::FUSION_KIND(KIND), ST.HAS_FEATURE(), DEP_OP_IDX, { OPSET1 },\
246  { OPSET2 } },
247  #include "PPCMacroFusion.def"
248  };
249  #undef FUSION_KIND
250 
251  for (auto &Feature : FusionFeatures) {
252  // Skip if the feature is not supported.
253  if (!Feature.isSupported())
254  continue;
255 
256  // Only when the SecondMI is fusable, we are starting to look for the
257  // fusable FirstMI.
258  if (Feature.hasOp2(SecondMI.getOpcode())) {
259  // If FirstMI == nullptr, that means, we're only checking whether SecondMI
260  // can be fused at all.
261  if (!FirstMI)
262  return true;
263 
264  // Checking if the FirstMI is fusable with the SecondMI.
265  if (!Feature.hasOp1(FirstMI->getOpcode()))
266  continue;
267 
268  auto DepOpIdx = Feature.depOpIdx();
269  if (DepOpIdx.hasValue()) {
270  // Checking if the result of the FirstMI is the desired operand of the
271  // SecondMI if the DepOpIdx is set. Otherwise, ignore it.
272  if (!matchingRegOps(*FirstMI, 0, SecondMI, *DepOpIdx))
273  return false;
274  }
275 
276  // Checking more on the instruction operands.
277  if (checkOpConstraints(Feature.getKind(), *FirstMI, SecondMI))
278  return true;
279  }
280  }
281 
282  return false;
283 }
284 
285 } // end anonymous namespace
286 
287 namespace llvm {
288 
289 std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation () {
291 }
292 
293 } // end namespace llvm
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
FUSION_KIND
#define FUSION_KIND(KIND)
Definition: PPCMacroFusion.cpp:27
llvm::ARM_MB::LD
@ LD
Definition: ARMBaseInfo.h:72
llvm::SmallDenseSet
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition: DenseSet.h:286
llvm::createPowerPCMacroFusionDAGMutation
std::unique_ptr< ScheduleDAGMutation > createPowerPCMacroFusionDAGMutation()
Note that you have to add: DAG.addMutation(createPowerPCMacroFusionDAGMutation()); to PPCPassConfig::...
Definition: PPCMacroFusion.cpp:289
llvm::Optional< unsigned >
PPCSubtarget.h
llvm::TargetInstrInfo
TargetInstrInfo - Interface to description of machine instruction set.
Definition: TargetInstrInfo.h:97
llvm::PPCSubtarget
Definition: PPCSubtarget.h:71
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:499
llvm::BitTracker
Definition: BitTracker.h:35
DenseSet.h
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:129
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
PPC.h
llvm::None
const NoneType None
Definition: None.h:23
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::createMacroFusionDAGMutation
std::unique_ptr< ScheduleDAGMutation > createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent)
Create a DAG scheduling mutation to pair instructions back to back for instructions that benefit acco...
Definition: MacroFusion.cpp:201
llvm::shouldScheduleAdjacent
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
Definition: ARMMacroFusion.cpp:51
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:321
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
MacroFusion.h
llvm::ARM_MB::ST
@ ST
Definition: ARMBaseInfo.h:73
llvm::Register::isVirtualRegister
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:71
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
RA
SI optimize exec mask operations pre RA
Definition: SIOptimizeExecMaskingPreRA.cpp:71
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:489
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::TargetSubtargetInfo
TargetSubtargetInfo - Generic base class for all target subtargets.
Definition: TargetSubtargetInfo.h:59
llvm::SignExtend64
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition: MathExtras.h:777
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:325
PPC
should just be implemented with a CLZ instruction Since there are other e PPC
Definition: README.txt:709