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"
24 typedef SmallDenseSet
<unsigned> FusionOpSet
;
27 #define FUSION_KIND(KIND) FK_##KIND
28 #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) \
30 #include "PPCMacroFusion.def"
34 // Each fusion feature is assigned with one fusion kind. All the
35 // instructions with the same fusion kind have the same fusion characteristic.
37 // True if this feature is enabled.
41 // The dependent operand index in the second op(load). And the negative means
42 // it could be any one.
44 // The first fusion op set.
46 // The second fusion op set.
49 FusionFeature(FusionKind Kind
, bool HasFeature
, int Index
,
50 const FusionOpSet
&First
, const FusionOpSet
&Second
) :
51 Kd(Kind
), Supported(HasFeature
), DepOpIdx(Index
), OpSet1(First
),
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 {
63 FusionKind
getKind() const { return Kd
; }
66 static bool matchingRegOps(const MachineInstr
&FirstMI
,
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())
75 return Op1
.getReg() == Op2
.getReg();
78 // Return true if the FirstMI meets the constraints of SecondMI according to
79 // fusion specification.
80 static bool checkOpConstraints(FusionFeature::FusionKind Kd
,
81 const MachineInstr
&FirstMI
,
82 const MachineInstr
&SecondMI
) {
84 // The hardware didn't require any specific check for the fused instructions'
85 // operands. Therefore, return true to indicate that, it is fusable.
87 // [addi rt,ra,si - lxvd2x xt,ra,rb] etc.
88 case FusionFeature::FK_AddiLoad
: {
89 // lxvd2x(ra) cannot be zero
90 const MachineOperand
&RA
= SecondMI
.getOperand(1);
94 return Register::isVirtualRegister(RA
.getReg()) ||
95 (RA
.getReg() != PPC::ZERO
&& RA
.getReg() != PPC::ZERO8
);
97 // [addis rt,ra,si - ld rt,ds(ra)] etc.
98 case FusionFeature::FK_AddisLoad
: {
99 const MachineOperand
&RT
= SecondMI
.getOperand(0);
103 // Only check it for non-virtual register.
104 if (!Register::isVirtualRegister(RT
.getReg()))
105 // addis(rt) = ld(ra) = ld(rt)
106 // ld(rt) cannot be zero
107 if (!matchingRegOps(SecondMI
, 0, SecondMI
, 2) ||
108 (RT
.getReg() == PPC::ZERO
|| RT
.getReg() == PPC::ZERO8
))
111 // addis(si) first 12 bits must be all 1s or all 0s
112 const MachineOperand
&SI
= FirstMI
.getOperand(2);
115 int64_t Imm
= SI
.getImm();
116 if (((Imm
& 0xFFF0) != 0) && ((Imm
& 0xFFF0) != 0xFFF0))
119 // If si = 1111111111110000 and the msb of the d/ds field of the load equals
120 // 1, then fusion does not occur.
121 if ((Imm
& 0xFFF0) == 0xFFF0) {
122 const MachineOperand
&D
= SecondMI
.getOperand(1);
126 // 14 bit for DS field, while 16 bit for D field.
128 if (SecondMI
.getOpcode() == PPC::LD
)
131 return (D
.getImm() & (1ULL << MSB
)) == 0;
137 llvm_unreachable("All the cases should have been handled");
141 /// Check if the instr pair, FirstMI and SecondMI, should be fused together.
142 /// Given SecondMI, when FirstMI is unspecified, then check if SecondMI may be
143 /// part of a fused pair at all.
144 static bool shouldScheduleAdjacent(const TargetInstrInfo
&TII
,
145 const TargetSubtargetInfo
&TSI
,
146 const MachineInstr
*FirstMI
,
147 const MachineInstr
&SecondMI
) {
148 // We use the PPC namespace to avoid the need to prefix opcodes with PPC:: in
152 const PPCSubtarget
&ST
= static_cast<const PPCSubtarget
&>(TSI
);
153 static const FusionFeature FusionFeatures
[] = {
154 #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) { \
155 FusionFeature::FUSION_KIND(KIND), ST.HAS_FEATURE(), DEP_OP_IDX, { OPSET1 },\
157 #include "PPCMacroFusion.def"
161 for (auto &Feature
: FusionFeatures
) {
162 // Skip if the feature is not supported.
163 if (!Feature
.isSupported())
166 // Only when the SecondMI is fusable, we are starting to look for the
168 if (Feature
.hasOp2(SecondMI
.getOpcode())) {
169 // If FirstMI == nullptr, that means, we're only checking whether SecondMI
170 // can be fused at all.
174 // Checking if the FirstMI is fusable with the SecondMI.
175 if (!Feature
.hasOp1(FirstMI
->getOpcode()))
178 auto DepOpIdx
= Feature
.depOpIdx();
179 if (DepOpIdx
.hasValue()) {
180 // Checking if the result of the FirstMI is the desired operand of the
181 // SecondMI if the DepOpIdx is set. Otherwise, ignore it.
182 if (!matchingRegOps(*FirstMI
, 0, SecondMI
, *DepOpIdx
))
186 // Checking more on the instruction operands.
187 if (checkOpConstraints(Feature
.getKind(), *FirstMI
, SecondMI
))
195 } // end anonymous namespace
199 std::unique_ptr
<ScheduleDAGMutation
> createPowerPCMacroFusionDAGMutation () {
200 return createMacroFusionDAGMutation(shouldScheduleAdjacent
);
203 } // end namespace llvm