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 // 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) { 83 switch (Kd) { 84 // The hardware didn't require any specific check for the fused instructions' 85 // operands. Therefore, return true to indicate that, it is fusable. 86 default: return true; 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); 91 if (!RA.isReg()) 92 return true; 93 94 return Register::isVirtualRegister(RA.getReg()) || 95 (RA.getReg() != PPC::ZERO && RA.getReg() != PPC::ZERO8); 96 } 97 // [addis rt,ra,si - ld rt,ds(ra)] etc. 98 case FusionFeature::FK_AddisLoad: { 99 const MachineOperand &RT = SecondMI.getOperand(0); 100 if (!RT.isReg()) 101 return true; 102 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)) 109 return false; 110 111 // addis(si) first 12 bits must be all 1s or all 0s 112 const MachineOperand &SI = FirstMI.getOperand(2); 113 if (!SI.isImm()) 114 return true; 115 int64_t Imm = SI.getImm(); 116 if (((Imm & 0xFFF0) != 0) && ((Imm & 0xFFF0) != 0xFFF0)) 117 return false; 118 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); 123 if (!D.isImm()) 124 return true; 125 126 // 14 bit for DS field, while 16 bit for D field. 127 int MSB = 15; 128 if (SecondMI.getOpcode() == PPC::LD) 129 MSB = 13; 130 131 return (D.getImm() & (1ULL << MSB)) == 0; 132 } 133 return true; 134 } 135 } 136 137 llvm_unreachable("All the cases should have been handled"); 138 return true; 139 } 140 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 149 // the def file. 150 using namespace PPC; 151 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 },\ 156 { OPSET2 } }, 157 #include "PPCMacroFusion.def" 158 }; 159 #undef FUSION_KIND 160 161 for (auto &Feature : FusionFeatures) { 162 // Skip if the feature is not supported. 163 if (!Feature.isSupported()) 164 continue; 165 166 // Only when the SecondMI is fusable, we are starting to look for the 167 // fusable FirstMI. 168 if (Feature.hasOp2(SecondMI.getOpcode())) { 169 // If FirstMI == nullptr, that means, we're only checking whether SecondMI 170 // can be fused at all. 171 if (!FirstMI) 172 return true; 173 174 // Checking if the FirstMI is fusable with the SecondMI. 175 if (!Feature.hasOp1(FirstMI->getOpcode())) 176 continue; 177 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)) 183 return false; 184 } 185 186 // Checking more on the instruction operands. 187 if (checkOpConstraints(Feature.getKind(), *FirstMI, SecondMI)) 188 return true; 189 } 190 } 191 192 return false; 193 } 194 195 } // end anonymous namespace 196 197 namespace llvm { 198 199 std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation () { 200 return createMacroFusionDAGMutation(shouldScheduleAdjacent); 201 } 202 203 } // end namespace llvm 204