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