//===-- HexagonSplitTFRCondSets.cpp - split TFR condsets into xfers -------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // //===----------------------------------------------------------------------===// // This pass tries to provide opportunities for better optimization of muxes. // The default code generated for something like: flag = (a == b) ? 1 : 3; // would be: // // {p0 = cmp.eq(r0,r1)} // {r3 = mux(p0,#1,#3)} // // This requires two packets. If we use .new predicated immediate transfers, // then we can do this in a single packet, e.g.: // // {p0 = cmp.eq(r0,r1) // if (p0.new) r3 = #1 // if (!p0.new) r3 = #3} // // Note that the conditional assignments are not generated in .new form here. // We assume opptimisically that they will be formed later. // //===----------------------------------------------------------------------===// #include "Hexagon.h" #include "HexagonMachineFunctionInfo.h" #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" #include "llvm/CodeGen/LatencyPriorityQueue.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/ScheduleHazardRecognizer.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; #define DEBUG_TYPE "xfer" namespace llvm { void initializeHexagonSplitTFRCondSetsPass(PassRegistry&); } namespace { class HexagonSplitTFRCondSets : public MachineFunctionPass { const HexagonTargetMachine &QTM; const HexagonSubtarget &QST; public: static char ID; HexagonSplitTFRCondSets(const HexagonTargetMachine& TM) : MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { initializeHexagonSplitTFRCondSetsPass(*PassRegistry::getPassRegistry()); } const char *getPassName() const override { return "Hexagon Split TFRCondSets"; } bool runOnMachineFunction(MachineFunction &Fn) override; }; char HexagonSplitTFRCondSets::ID = 0; bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { const TargetInstrInfo *TII = QTM.getInstrInfo(); // Loop over all of the basic blocks. for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); MBBb != MBBe; ++MBBb) { MachineBasicBlock* MBB = MBBb; // Traverse the basic block. for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); ++MII) { MachineInstr *MI = MII; int Opc1, Opc2; switch(MI->getOpcode()) { case Hexagon::TFR_condset_rr: case Hexagon::TFR_condset_rr_f: case Hexagon::TFR_condset_rr64_f: { int DestReg = MI->getOperand(0).getReg(); int SrcReg1 = MI->getOperand(2).getReg(); int SrcReg2 = MI->getOperand(3).getReg(); if (MI->getOpcode() == Hexagon::TFR_condset_rr || MI->getOpcode() == Hexagon::TFR_condset_rr_f) { Opc1 = Hexagon::TFR_cPt; Opc2 = Hexagon::TFR_cNotPt; } else if (MI->getOpcode() == Hexagon::TFR_condset_rr64_f) { Opc1 = Hexagon::TFR64_cPt; Opc2 = Hexagon::TFR64_cNotPt; } // Minor optimization: do not emit the predicated copy if the source // and the destination is the same register. if (DestReg != SrcReg1) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc1), DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); } if (DestReg != SrcReg2) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc2), DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); } MII = MBB->erase(MI); --MII; break; } case Hexagon::TFR_condset_ri: case Hexagon::TFR_condset_ri_f: { int DestReg = MI->getOperand(0).getReg(); int SrcReg1 = MI->getOperand(2).getReg(); // Do not emit the predicated copy if the source and the destination // is the same register. if (DestReg != SrcReg1) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cPt), DestReg). addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); } if (MI->getOpcode() == Hexagon::TFR_condset_ri ) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt), DestReg). addReg(MI->getOperand(1).getReg()). addImm(MI->getOperand(3).getImm()); } else if (MI->getOpcode() == Hexagon::TFR_condset_ri_f ) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt_f), DestReg). addReg(MI->getOperand(1).getReg()). addFPImm(MI->getOperand(3).getFPImm()); } MII = MBB->erase(MI); --MII; break; } case Hexagon::TFR_condset_ir: case Hexagon::TFR_condset_ir_f: { int DestReg = MI->getOperand(0).getReg(); int SrcReg2 = MI->getOperand(3).getReg(); if (MI->getOpcode() == Hexagon::TFR_condset_ir ) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt), DestReg). addReg(MI->getOperand(1).getReg()). addImm(MI->getOperand(2).getImm()); } else if (MI->getOpcode() == Hexagon::TFR_condset_ir_f ) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt_f), DestReg). addReg(MI->getOperand(1).getReg()). addFPImm(MI->getOperand(2).getFPImm()); } // Do not emit the predicated copy if the source and // the destination is the same register. if (DestReg != SrcReg2) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cNotPt), DestReg). addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); } MII = MBB->erase(MI); --MII; break; } case Hexagon::TFR_condset_ii: case Hexagon::TFR_condset_ii_f: { int DestReg = MI->getOperand(0).getReg(); int SrcReg1 = MI->getOperand(1).getReg(); if (MI->getOpcode() == Hexagon::TFR_condset_ii ) { int Immed1 = MI->getOperand(2).getImm(); int Immed2 = MI->getOperand(3).getImm(); BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt), DestReg).addReg(SrcReg1).addImm(Immed1); BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt), DestReg).addReg(SrcReg1).addImm(Immed2); } else if (MI->getOpcode() == Hexagon::TFR_condset_ii_f ) { BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt_f), DestReg). addReg(SrcReg1). addFPImm(MI->getOperand(2).getFPImm()); BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt_f), DestReg). addReg(SrcReg1). addFPImm(MI->getOperand(3).getFPImm()); } MII = MBB->erase(MI); --MII; break; } } } } return true; } } //===----------------------------------------------------------------------===// // Public Constructor Functions //===----------------------------------------------------------------------===// static void initializePassOnce(PassRegistry &Registry) { const char *Name = "Hexagon Split TFRCondSets"; PassInfo *PI = new PassInfo(Name, "hexagon-split-tfr", &HexagonSplitTFRCondSets::ID, nullptr, false, false); Registry.registerPass(*PI, true); } void llvm::initializeHexagonSplitTFRCondSetsPass(PassRegistry &Registry) { CALL_ONCE_INITIALIZATION(initializePassOnce) } FunctionPass* llvm::createHexagonSplitTFRCondSets(const HexagonTargetMachine &TM) { return new HexagonSplitTFRCondSets(TM); }