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" 17 #include "llvm/CodeGen/MacroFusion.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. 117 if (!Register::isVirtualRegister(RT.getReg())) 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 154 llvm_unreachable("All the cases should have been handled"); 155 return true; 156 } 157 158 /// Check if the instr pair, FirstMI and SecondMI, should be fused together. 159 /// Given SecondMI, when FirstMI is unspecified, then check if SecondMI may be 160 /// part of a fused pair at all. 161 static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, 162 const TargetSubtargetInfo &TSI, 163 const MachineInstr *FirstMI, 164 const MachineInstr &SecondMI) { 165 // We use the PPC namespace to avoid the need to prefix opcodes with PPC:: in 166 // the def file. 167 using namespace PPC; 168 169 const PPCSubtarget &ST = static_cast<const PPCSubtarget&>(TSI); 170 static const FusionFeature FusionFeatures[] = { 171 #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) { \ 172 FusionFeature::FUSION_KIND(KIND), ST.HAS_FEATURE(), DEP_OP_IDX, { OPSET1 },\ 173 { OPSET2 } }, 174 #include "PPCMacroFusion.def" 175 }; 176 #undef FUSION_KIND 177 178 for (auto &Feature : FusionFeatures) { 179 // Skip if the feature is not supported. 180 if (!Feature.isSupported()) 181 continue; 182 183 // Only when the SecondMI is fusable, we are starting to look for the 184 // fusable FirstMI. 185 if (Feature.hasOp2(SecondMI.getOpcode())) { 186 // If FirstMI == nullptr, that means, we're only checking whether SecondMI 187 // can be fused at all. 188 if (!FirstMI) 189 return true; 190 191 // Checking if the FirstMI is fusable with the SecondMI. 192 if (!Feature.hasOp1(FirstMI->getOpcode())) 193 continue; 194 195 auto DepOpIdx = Feature.depOpIdx(); 196 if (DepOpIdx.hasValue()) { 197 // Checking if the result of the FirstMI is the desired operand of the 198 // SecondMI if the DepOpIdx is set. Otherwise, ignore it. 199 if (!matchingRegOps(*FirstMI, 0, SecondMI, *DepOpIdx)) 200 return false; 201 } 202 203 // Checking more on the instruction operands. 204 if (checkOpConstraints(Feature.getKind(), *FirstMI, SecondMI)) 205 return true; 206 } 207 } 208 209 return false; 210 } 211 212 } // end anonymous namespace 213 214 namespace llvm { 215 216 std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation () { 217 return createMacroFusionDAGMutation(shouldScheduleAdjacent); 218 } 219 220 } // end namespace llvm 221