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#define DEBUG_TYPE "xfer" 30#include "Hexagon.h" 31#include "HexagonMachineFunctionInfo.h" 32#include "HexagonSubtarget.h" 33#include "HexagonTargetMachine.h" 34#include "llvm/CodeGen/LatencyPriorityQueue.h" 35#include "llvm/CodeGen/MachineDominators.h" 36#include "llvm/CodeGen/MachineFunctionPass.h" 37#include "llvm/CodeGen/MachineInstrBuilder.h" 38#include "llvm/CodeGen/MachineLoopInfo.h" 39#include "llvm/CodeGen/MachineRegisterInfo.h" 40#include "llvm/CodeGen/Passes.h" 41#include "llvm/CodeGen/ScheduleHazardRecognizer.h" 42#include "llvm/CodeGen/SchedulerRegistry.h" 43#include "llvm/Support/Compiler.h" 44#include "llvm/Support/Debug.h" 45#include "llvm/Support/MathExtras.h" 46#include "llvm/Target/TargetInstrInfo.h" 47#include "llvm/Target/TargetMachine.h" 48#include "llvm/Target/TargetRegisterInfo.h" 49 50using namespace llvm; 51 52namespace { 53 54class HexagonSplitTFRCondSets : public MachineFunctionPass { 55 HexagonTargetMachine& QTM; 56 const HexagonSubtarget &QST; 57 58 public: 59 static char ID; 60 HexagonSplitTFRCondSets(HexagonTargetMachine& TM) : 61 MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} 62 63 const char *getPassName() const { 64 return "Hexagon Split TFRCondSets"; 65 } 66 bool runOnMachineFunction(MachineFunction &Fn); 67}; 68 69 70char HexagonSplitTFRCondSets::ID = 0; 71 72 73bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { 74 75 const TargetInstrInfo *TII = QTM.getInstrInfo(); 76 77 // Loop over all of the basic blocks. 78 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 79 MBBb != MBBe; ++MBBb) { 80 MachineBasicBlock* MBB = MBBb; 81 // Traverse the basic block. 82 for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 83 ++MII) { 84 MachineInstr *MI = MII; 85 int Opc1, Opc2; 86 switch(MI->getOpcode()) { 87 case Hexagon::TFR_condset_rr: 88 case Hexagon::TFR_condset_rr_f: 89 case Hexagon::TFR_condset_rr64_f: { 90 int DestReg = MI->getOperand(0).getReg(); 91 int SrcReg1 = MI->getOperand(2).getReg(); 92 int SrcReg2 = MI->getOperand(3).getReg(); 93 94 if (MI->getOpcode() == Hexagon::TFR_condset_rr || 95 MI->getOpcode() == Hexagon::TFR_condset_rr_f) { 96 Opc1 = Hexagon::TFR_cPt; 97 Opc2 = Hexagon::TFR_cNotPt; 98 } 99 else if (MI->getOpcode() == Hexagon::TFR_condset_rr64_f) { 100 Opc1 = Hexagon::TFR64_cPt; 101 Opc2 = Hexagon::TFR64_cNotPt; 102 } 103 104 // Minor optimization: do not emit the predicated copy if the source 105 // and the destination is the same register. 106 if (DestReg != SrcReg1) { 107 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc1), 108 DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); 109 } 110 if (DestReg != SrcReg2) { 111 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc2), 112 DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); 113 } 114 MII = MBB->erase(MI); 115 --MII; 116 break; 117 } 118 case Hexagon::TFR_condset_ri: 119 case Hexagon::TFR_condset_ri_f: { 120 int DestReg = MI->getOperand(0).getReg(); 121 int SrcReg1 = MI->getOperand(2).getReg(); 122 123 // Do not emit the predicated copy if the source and the destination 124 // is the same register. 125 if (DestReg != SrcReg1) { 126 BuildMI(*MBB, MII, MI->getDebugLoc(), 127 TII->get(Hexagon::TFR_cPt), DestReg). 128 addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); 129 } 130 if (MI->getOpcode() == Hexagon::TFR_condset_ri ) { 131 BuildMI(*MBB, MII, MI->getDebugLoc(), 132 TII->get(Hexagon::TFRI_cNotPt), DestReg). 133 addReg(MI->getOperand(1).getReg()). 134 addImm(MI->getOperand(3).getImm()); 135 } else if (MI->getOpcode() == Hexagon::TFR_condset_ri_f ) { 136 BuildMI(*MBB, MII, MI->getDebugLoc(), 137 TII->get(Hexagon::TFRI_cNotPt_f), DestReg). 138 addReg(MI->getOperand(1).getReg()). 139 addFPImm(MI->getOperand(3).getFPImm()); 140 } 141 142 MII = MBB->erase(MI); 143 --MII; 144 break; 145 } 146 case Hexagon::TFR_condset_ir: 147 case Hexagon::TFR_condset_ir_f: { 148 int DestReg = MI->getOperand(0).getReg(); 149 int SrcReg2 = MI->getOperand(3).getReg(); 150 151 if (MI->getOpcode() == Hexagon::TFR_condset_ir ) { 152 BuildMI(*MBB, MII, MI->getDebugLoc(), 153 TII->get(Hexagon::TFRI_cPt), DestReg). 154 addReg(MI->getOperand(1).getReg()). 155 addImm(MI->getOperand(2).getImm()); 156 } else if (MI->getOpcode() == Hexagon::TFR_condset_ir_f ) { 157 BuildMI(*MBB, MII, MI->getDebugLoc(), 158 TII->get(Hexagon::TFRI_cPt_f), DestReg). 159 addReg(MI->getOperand(1).getReg()). 160 addFPImm(MI->getOperand(2).getFPImm()); 161 } 162 163 // Do not emit the predicated copy if the source and 164 // the destination is the same register. 165 if (DestReg != SrcReg2) { 166 BuildMI(*MBB, MII, MI->getDebugLoc(), 167 TII->get(Hexagon::TFR_cNotPt), DestReg). 168 addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); 169 } 170 MII = MBB->erase(MI); 171 --MII; 172 break; 173 } 174 case Hexagon::TFR_condset_ii: 175 case Hexagon::TFR_condset_ii_f: { 176 int DestReg = MI->getOperand(0).getReg(); 177 int SrcReg1 = MI->getOperand(1).getReg(); 178 179 if (MI->getOpcode() == Hexagon::TFR_condset_ii ) { 180 int Immed1 = MI->getOperand(2).getImm(); 181 int Immed2 = MI->getOperand(3).getImm(); 182 BuildMI(*MBB, MII, MI->getDebugLoc(), 183 TII->get(Hexagon::TFRI_cPt), 184 DestReg).addReg(SrcReg1).addImm(Immed1); 185 BuildMI(*MBB, MII, MI->getDebugLoc(), 186 TII->get(Hexagon::TFRI_cNotPt), 187 DestReg).addReg(SrcReg1).addImm(Immed2); 188 } else if (MI->getOpcode() == Hexagon::TFR_condset_ii_f ) { 189 BuildMI(*MBB, MII, MI->getDebugLoc(), 190 TII->get(Hexagon::TFRI_cPt_f), DestReg). 191 addReg(SrcReg1). 192 addFPImm(MI->getOperand(2).getFPImm()); 193 BuildMI(*MBB, MII, MI->getDebugLoc(), 194 TII->get(Hexagon::TFRI_cNotPt_f), DestReg). 195 addReg(SrcReg1). 196 addFPImm(MI->getOperand(3).getFPImm()); 197 } 198 MII = MBB->erase(MI); 199 --MII; 200 break; 201 } 202 } 203 } 204 } 205 return true; 206} 207 208} 209 210//===----------------------------------------------------------------------===// 211// Public Constructor Functions 212//===----------------------------------------------------------------------===// 213 214FunctionPass *llvm::createHexagonSplitTFRCondSets(HexagonTargetMachine &TM) { 215 return new HexagonSplitTFRCondSets(TM); 216} 217