| //===-- 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. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "xfer" |
| #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; |
| |
| namespace { |
| |
| class HexagonSplitTFRCondSets : public MachineFunctionPass { |
| HexagonTargetMachine& QTM; |
| const HexagonSubtarget &QST; |
| |
| public: |
| static char ID; |
| HexagonSplitTFRCondSets(HexagonTargetMachine& TM) : |
| MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} |
| |
| const char *getPassName() const { |
| return "Hexagon Split TFRCondSets"; |
| } |
| bool runOnMachineFunction(MachineFunction &Fn); |
| }; |
| |
| |
| 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 |
| //===----------------------------------------------------------------------===// |
| |
| FunctionPass *llvm::createHexagonSplitTFRCondSets(HexagonTargetMachine &TM) { |
| return new HexagonSplitTFRCondSets(TM); |
| } |