1 //===- PPCMacroFusion.cpp - PowerPC Macro Fusion --------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 /// \file This file contains the PowerPC implementation of the DAG scheduling
10 /// mutation to pair instructions back to back.
12 //===----------------------------------------------------------------------===//
15 #include "PPCSubtarget.h"
16 #include "llvm/ADT/DenseSet.h"
17 #include "llvm/CodeGen/MacroFusion.h"
18 #include "llvm/CodeGen/ScheduleDAGMutation.h"
26 typedef SmallDenseSet
<unsigned> FusionOpSet
;
29 #define FUSION_KIND(KIND) FK_##KIND
30 #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) \
32 #include "PPCMacroFusion.def"
36 // Each fusion feature is assigned with one fusion kind. All the
37 // instructions with the same fusion kind have the same fusion characteristic.
39 // True if this feature is enabled.
43 // The dependent operand index in the second op(load). And the negative means
44 // it could be any one.
46 // The first fusion op set.
48 // The second fusion op set.
51 FusionFeature(FusionKind Kind
, bool HasFeature
, int Index
,
52 const FusionOpSet
&First
, const FusionOpSet
&Second
) :
53 Kd(Kind
), Supported(HasFeature
), DepOpIdx(Index
), OpSet1(First
),
56 bool hasOp1(unsigned Opc
) const { return OpSet1
.contains(Opc
); }
57 bool hasOp2(unsigned Opc
) const { return OpSet2
.contains(Opc
); }
58 bool isSupported() const { return Supported
; }
59 std::optional
<unsigned> depOpIdx() const {
65 FusionKind
getKind() const { return Kd
; }
68 static bool matchingRegOps(const MachineInstr
&FirstMI
,
70 const MachineInstr
&SecondMI
,
71 int SecondMIOpIndex
) {
72 const MachineOperand
&Op1
= FirstMI
.getOperand(FirstMIOpIndex
);
73 const MachineOperand
&Op2
= SecondMI
.getOperand(SecondMIOpIndex
);
74 if (!Op1
.isReg() || !Op2
.isReg())
77 return Op1
.getReg() == Op2
.getReg();
80 static bool matchingImmOps(const MachineInstr
&MI
,
83 unsigned ExtendFrom
= 64) {
84 const MachineOperand
&Op
= MI
.getOperand(MIOpIndex
);
87 int64_t Imm
= Op
.getImm();
89 Imm
= SignExtend64(Imm
, ExtendFrom
);
93 // Return true if the FirstMI meets the constraints of SecondMI according to
94 // fusion specification.
95 static bool checkOpConstraints(FusionFeature::FusionKind Kd
,
96 const MachineInstr
&FirstMI
,
97 const MachineInstr
&SecondMI
) {
99 // The hardware didn't require any specific check for the fused instructions'
100 // operands. Therefore, return true to indicate that, it is fusable.
101 default: return true;
102 // [addi rt,ra,si - lxvd2x xt,ra,rb] etc.
103 case FusionFeature::FK_AddiLoad
: {
104 // lxvd2x(ra) cannot be zero
105 const MachineOperand
&RA
= SecondMI
.getOperand(1);
109 return RA
.getReg().isVirtual() ||
110 (RA
.getReg() != PPC::ZERO
&& RA
.getReg() != PPC::ZERO8
);
112 // [addis rt,ra,si - ld rt,ds(ra)] etc.
113 case FusionFeature::FK_AddisLoad
: {
114 const MachineOperand
&RT
= SecondMI
.getOperand(0);
118 // Only check it for non-virtual register.
119 if (!RT
.getReg().isVirtual())
120 // addis(rt) = ld(ra) = ld(rt)
121 // ld(rt) cannot be zero
122 if (!matchingRegOps(SecondMI
, 0, SecondMI
, 2) ||
123 (RT
.getReg() == PPC::ZERO
|| RT
.getReg() == PPC::ZERO8
))
126 // addis(si) first 12 bits must be all 1s or all 0s
127 const MachineOperand
&SI
= FirstMI
.getOperand(2);
130 int64_t Imm
= SI
.getImm();
131 if (((Imm
& 0xFFF0) != 0) && ((Imm
& 0xFFF0) != 0xFFF0))
134 // If si = 1111111111110000 and the msb of the d/ds field of the load equals
135 // 1, then fusion does not occur.
136 if ((Imm
& 0xFFF0) == 0xFFF0) {
137 const MachineOperand
&D
= SecondMI
.getOperand(1);
141 // 14 bit for DS field, while 16 bit for D field.
143 if (SecondMI
.getOpcode() == PPC::LD
)
146 return (D
.getImm() & (1ULL << MSB
)) == 0;
151 case FusionFeature::FK_SldiAdd
:
152 return (matchingImmOps(FirstMI
, 2, 3) && matchingImmOps(FirstMI
, 3, 60)) ||
153 (matchingImmOps(FirstMI
, 2, 6) && matchingImmOps(FirstMI
, 3, 57));
155 // rldicl rx, ra, 1, 0 - xor
156 case FusionFeature::FK_RotateLeftXor
:
157 return matchingImmOps(FirstMI
, 2, 1) && matchingImmOps(FirstMI
, 3, 0);
159 // rldicr rx, ra, 1, 63 - xor
160 case FusionFeature::FK_RotateRightXor
:
161 return matchingImmOps(FirstMI
, 2, 1) && matchingImmOps(FirstMI
, 3, 63);
163 // We actually use CMPW* and CMPD*, 'l' doesn't exist as an operand in instr.
165 // { lbz,lbzx,lhz,lhzx,lwz,lwzx } - cmpi 0,1,rx,{ 0,1,-1 }
166 // { lbz,lbzx,lhz,lhzx,lwz,lwzx } - cmpli 0,L,rx,{ 0,1 }
167 case FusionFeature::FK_LoadCmp1
:
168 // { ld,ldx } - cmpi 0,1,rx,{ 0,1,-1 }
169 // { ld,ldx } - cmpli 0,1,rx,{ 0,1 }
170 case FusionFeature::FK_LoadCmp2
: {
171 const MachineOperand
&BT
= SecondMI
.getOperand(0);
172 if (!BT
.isReg() || (!BT
.getReg().isVirtual() && BT
.getReg() != PPC::CR0
))
174 if (SecondMI
.getOpcode() == PPC::CMPDI
&&
175 matchingImmOps(SecondMI
, 2, -1, 16))
177 return matchingImmOps(SecondMI
, 2, 0) || matchingImmOps(SecondMI
, 2, 1);
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() || (!BT
.getReg().isVirtual() && BT
.getReg() != PPC::CR0
))
185 return matchingImmOps(SecondMI
, 2, 0) || matchingImmOps(SecondMI
, 2, 1) ||
186 matchingImmOps(SecondMI
, 2, -1, 16);
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);
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);
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())
209 if (RA
.getReg() == PPC::ZERO
|| RA
.getReg() == PPC::ZERO8
)
211 return SignExtend64(SI
.getImm(), 16) >= 0;
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())
220 if (RA
.getReg() == PPC::ZERO
|| RA
.getReg() == PPC::ZERO8
)
222 int64_t ExtendedSI
= SignExtend64(SI
.getImm(), 16);
223 return ExtendedSI
>= 2;
227 llvm_unreachable("All the cases should have been handled");
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
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 },\
247 #include "PPCMacroFusion.def"
251 for (auto &Feature
: FusionFeatures
) {
252 // Skip if the feature is not supported.
253 if (!Feature
.isSupported())
256 // Only when the SecondMI is fusable, we are starting to look for the
258 if (Feature
.hasOp2(SecondMI
.getOpcode())) {
259 // If FirstMI == nullptr, that means, we're only checking whether SecondMI
260 // can be fused at all.
264 // Checking if the FirstMI is fusable with the SecondMI.
265 if (!Feature
.hasOp1(FirstMI
->getOpcode()))
268 auto DepOpIdx
= Feature
.depOpIdx();
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
))
276 // Checking more on the instruction operands.
277 if (checkOpConstraints(Feature
.getKind(), *FirstMI
, SecondMI
))
285 } // end anonymous namespace
289 std::unique_ptr
<ScheduleDAGMutation
> createPowerPCMacroFusionDAGMutation() {
290 return createMacroFusionDAGMutation(shouldScheduleAdjacent
);
293 } // end namespace llvm