1 //===-- HexagonSplitTFRCondSets.cpp - split TFR condsets into xfers -------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 // 9 //===----------------------------------------------------------------------===// 10 // This pass tries to provide opportunities for better optimization of muxes. 11 // The default code generated for something like: flag = (a == b) ? 1 : 3; 12 // would be: 13 // 14 // {p0 = cmp.eq(r0,r1)} 15 // {r3 = mux(p0,#1,#3)} 16 // 17 // This requires two packets. If we use .new predicated immediate transfers, 18 // then we can do this in a single packet, e.g.: 19 // 20 // {p0 = cmp.eq(r0,r1) 21 // if (p0.new) r3 = #1 22 // if (!p0.new) r3 = #3} 23 // 24 // Note that the conditional assignments are not generated in .new form here. 25 // We assume opptimisically that they will be formed later. 26 // 27 //===----------------------------------------------------------------------===// 28 29 #include "Hexagon.h" 30 #include "HexagonMachineFunctionInfo.h" 31 #include "HexagonSubtarget.h" 32 #include "HexagonTargetMachine.h" 33 #include "llvm/CodeGen/LatencyPriorityQueue.h" 34 #include "llvm/CodeGen/MachineDominators.h" 35 #include "llvm/CodeGen/MachineFunctionPass.h" 36 #include "llvm/CodeGen/MachineInstrBuilder.h" 37 #include "llvm/CodeGen/MachineLoopInfo.h" 38 #include "llvm/CodeGen/MachineRegisterInfo.h" 39 #include "llvm/CodeGen/Passes.h" 40 #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 41 #include "llvm/CodeGen/SchedulerRegistry.h" 42 #include "llvm/Support/Compiler.h" 43 #include "llvm/Support/Debug.h" 44 #include "llvm/Support/MathExtras.h" 45 #include "llvm/Target/TargetInstrInfo.h" 46 #include "llvm/Target/TargetMachine.h" 47 #include "llvm/Target/TargetRegisterInfo.h" 48 49 using namespace llvm; 50 51 #define DEBUG_TYPE "xfer" 52 53 namespace llvm { 54 void initializeHexagonSplitTFRCondSetsPass(PassRegistry&); 55 } 56 57 58 namespace { 59 60 class HexagonSplitTFRCondSets : public MachineFunctionPass { 61 const HexagonTargetMachine &QTM; 62 const HexagonSubtarget &QST; 63 64 public: 65 static char ID; 66 HexagonSplitTFRCondSets(const HexagonTargetMachine& TM) : 67 MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { 68 initializeHexagonSplitTFRCondSetsPass(*PassRegistry::getPassRegistry()); 69 } 70 71 const char *getPassName() const override { 72 return "Hexagon Split TFRCondSets"; 73 } 74 bool runOnMachineFunction(MachineFunction &Fn) override; 75 }; 76 77 78 char HexagonSplitTFRCondSets::ID = 0; 79 80 81 bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { 82 83 const TargetInstrInfo *TII = QTM.getInstrInfo(); 84 85 // Loop over all of the basic blocks. 86 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 87 MBBb != MBBe; ++MBBb) { 88 MachineBasicBlock* MBB = MBBb; 89 // Traverse the basic block. 90 for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 91 ++MII) { 92 MachineInstr *MI = MII; 93 int Opc1, Opc2; 94 switch(MI->getOpcode()) { 95 case Hexagon::TFR_condset_rr: 96 case Hexagon::TFR_condset_rr_f: 97 case Hexagon::TFR_condset_rr64_f: { 98 int DestReg = MI->getOperand(0).getReg(); 99 int SrcReg1 = MI->getOperand(2).getReg(); 100 int SrcReg2 = MI->getOperand(3).getReg(); 101 102 if (MI->getOpcode() == Hexagon::TFR_condset_rr || 103 MI->getOpcode() == Hexagon::TFR_condset_rr_f) { 104 Opc1 = Hexagon::TFR_cPt; 105 Opc2 = Hexagon::TFR_cNotPt; 106 } 107 else if (MI->getOpcode() == Hexagon::TFR_condset_rr64_f) { 108 Opc1 = Hexagon::TFR64_cPt; 109 Opc2 = Hexagon::TFR64_cNotPt; 110 } 111 112 // Minor optimization: do not emit the predicated copy if the source 113 // and the destination is the same register. 114 if (DestReg != SrcReg1) { 115 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc1), 116 DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); 117 } 118 if (DestReg != SrcReg2) { 119 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc2), 120 DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); 121 } 122 MII = MBB->erase(MI); 123 --MII; 124 break; 125 } 126 case Hexagon::TFR_condset_ri: 127 case Hexagon::TFR_condset_ri_f: { 128 int DestReg = MI->getOperand(0).getReg(); 129 int SrcReg1 = MI->getOperand(2).getReg(); 130 131 // Do not emit the predicated copy if the source and the destination 132 // is the same register. 133 if (DestReg != SrcReg1) { 134 BuildMI(*MBB, MII, MI->getDebugLoc(), 135 TII->get(Hexagon::TFR_cPt), DestReg). 136 addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); 137 } 138 if (MI->getOpcode() == Hexagon::TFR_condset_ri ) { 139 BuildMI(*MBB, MII, MI->getDebugLoc(), 140 TII->get(Hexagon::TFRI_cNotPt), DestReg). 141 addReg(MI->getOperand(1).getReg()). 142 addImm(MI->getOperand(3).getImm()); 143 } else if (MI->getOpcode() == Hexagon::TFR_condset_ri_f ) { 144 BuildMI(*MBB, MII, MI->getDebugLoc(), 145 TII->get(Hexagon::TFRI_cNotPt_f), DestReg). 146 addReg(MI->getOperand(1).getReg()). 147 addFPImm(MI->getOperand(3).getFPImm()); 148 } 149 150 MII = MBB->erase(MI); 151 --MII; 152 break; 153 } 154 case Hexagon::TFR_condset_ir: 155 case Hexagon::TFR_condset_ir_f: { 156 int DestReg = MI->getOperand(0).getReg(); 157 int SrcReg2 = MI->getOperand(3).getReg(); 158 159 if (MI->getOpcode() == Hexagon::TFR_condset_ir ) { 160 BuildMI(*MBB, MII, MI->getDebugLoc(), 161 TII->get(Hexagon::TFRI_cPt), DestReg). 162 addReg(MI->getOperand(1).getReg()). 163 addImm(MI->getOperand(2).getImm()); 164 } else if (MI->getOpcode() == Hexagon::TFR_condset_ir_f ) { 165 BuildMI(*MBB, MII, MI->getDebugLoc(), 166 TII->get(Hexagon::TFRI_cPt_f), DestReg). 167 addReg(MI->getOperand(1).getReg()). 168 addFPImm(MI->getOperand(2).getFPImm()); 169 } 170 171 // Do not emit the predicated copy if the source and 172 // the destination is the same register. 173 if (DestReg != SrcReg2) { 174 BuildMI(*MBB, MII, MI->getDebugLoc(), 175 TII->get(Hexagon::TFR_cNotPt), DestReg). 176 addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); 177 } 178 MII = MBB->erase(MI); 179 --MII; 180 break; 181 } 182 case Hexagon::TFR_condset_ii: 183 case Hexagon::TFR_condset_ii_f: { 184 int DestReg = MI->getOperand(0).getReg(); 185 int SrcReg1 = MI->getOperand(1).getReg(); 186 187 if (MI->getOpcode() == Hexagon::TFR_condset_ii ) { 188 int Immed1 = MI->getOperand(2).getImm(); 189 int Immed2 = MI->getOperand(3).getImm(); 190 BuildMI(*MBB, MII, MI->getDebugLoc(), 191 TII->get(Hexagon::TFRI_cPt), 192 DestReg).addReg(SrcReg1).addImm(Immed1); 193 BuildMI(*MBB, MII, MI->getDebugLoc(), 194 TII->get(Hexagon::TFRI_cNotPt), 195 DestReg).addReg(SrcReg1).addImm(Immed2); 196 } else if (MI->getOpcode() == Hexagon::TFR_condset_ii_f ) { 197 BuildMI(*MBB, MII, MI->getDebugLoc(), 198 TII->get(Hexagon::TFRI_cPt_f), DestReg). 199 addReg(SrcReg1). 200 addFPImm(MI->getOperand(2).getFPImm()); 201 BuildMI(*MBB, MII, MI->getDebugLoc(), 202 TII->get(Hexagon::TFRI_cNotPt_f), DestReg). 203 addReg(SrcReg1). 204 addFPImm(MI->getOperand(3).getFPImm()); 205 } 206 MII = MBB->erase(MI); 207 --MII; 208 break; 209 } 210 } 211 } 212 } 213 return true; 214 } 215 216 } 217 218 //===----------------------------------------------------------------------===// 219 // Public Constructor Functions 220 //===----------------------------------------------------------------------===// 221 222 static void initializePassOnce(PassRegistry &Registry) { 223 const char *Name = "Hexagon Split TFRCondSets"; 224 PassInfo *PI = new PassInfo(Name, "hexagon-split-tfr", 225 &HexagonSplitTFRCondSets::ID, nullptr, false, 226 false); 227 Registry.registerPass(*PI, true); 228 } 229 230 void llvm::initializeHexagonSplitTFRCondSetsPass(PassRegistry &Registry) { 231 CALL_ONCE_INITIALIZATION(initializePassOnce) 232 } 233 234 FunctionPass* 235 llvm::createHexagonSplitTFRCondSets(const HexagonTargetMachine &TM) { 236 return new HexagonSplitTFRCondSets(TM); 237 } 238