diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonPeephole.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonPeephole.cpp | 300 | 
1 files changed, 300 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonPeephole.cpp b/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonPeephole.cpp new file mode 100644 index 000000000000..d0b02f035d1e --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonPeephole.cpp @@ -0,0 +1,300 @@ +//===-- HexagonPeephole.cpp - Hexagon Peephole Optimiztions ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This peephole pass optimizes in the following cases. +// 1. Optimizes redundant sign extends for the following case +//    Transform the following pattern +//    %170 = SXTW %166 +//    ... +//    %176 = COPY %170:isub_lo +// +//    Into +//    %176 = COPY %166 +// +//  2. Optimizes redundant negation of predicates. +//     %15 = CMPGTrr %6, %2 +//     ... +//     %16 = NOT_p killed %15 +//     ... +//     JMP_c killed %16, <%bb.1>, implicit dead %pc +// +//     Into +//     %15 = CMPGTrr %6, %2; +//     ... +//     JMP_cNot killed %15, <%bb.1>, implicit dead %pc; +// +// Note: The peephole pass makes the instrucstions like +// %170 = SXTW %166 or %16 = NOT_p killed %15 +// redundant and relies on some form of dead removal instructions, like +// DCE or DIE to actually eliminate them. + +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "HexagonTargetMachine.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> + +using namespace llvm; + +#define DEBUG_TYPE "hexagon-peephole" + +static cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole", +    cl::Hidden, cl::ZeroOrMore, cl::init(false), +    cl::desc("Disable Peephole Optimization")); + +static cl::opt<bool> DisablePNotP("disable-hexagon-pnotp", +    cl::Hidden, cl::ZeroOrMore, cl::init(false), +    cl::desc("Disable Optimization of PNotP")); + +static cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext", +    cl::Hidden, cl::ZeroOrMore, cl::init(true), +    cl::desc("Disable Optimization of Sign/Zero Extends")); + +static cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64", +    cl::Hidden, cl::ZeroOrMore, cl::init(true), +    cl::desc("Disable Optimization of extensions to i64.")); + +namespace llvm { +  FunctionPass *createHexagonPeephole(); +  void initializeHexagonPeepholePass(PassRegistry&); +} + +namespace { +  struct HexagonPeephole : public MachineFunctionPass { +    const HexagonInstrInfo    *QII; +    const HexagonRegisterInfo *QRI; +    const MachineRegisterInfo *MRI; + +  public: +    static char ID; +    HexagonPeephole() : MachineFunctionPass(ID) { +      initializeHexagonPeepholePass(*PassRegistry::getPassRegistry()); +    } + +    bool runOnMachineFunction(MachineFunction &MF) override; + +    StringRef getPassName() const override { +      return "Hexagon optimize redundant zero and size extends"; +    } + +    void getAnalysisUsage(AnalysisUsage &AU) const override { +      MachineFunctionPass::getAnalysisUsage(AU); +    } +  }; +} + +char HexagonPeephole::ID = 0; + +INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole", +                false, false) + +bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { +  if (skipFunction(MF.getFunction())) +    return false; + +  QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); +  QRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); +  MRI = &MF.getRegInfo(); + +  DenseMap<unsigned, unsigned> PeepholeMap; +  DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap; + +  if (DisableHexagonPeephole) return false; + +  // Loop over all of the basic blocks. +  for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end(); +       MBBb != MBBe; ++MBBb) { +    MachineBasicBlock *MBB = &*MBBb; +    PeepholeMap.clear(); +    PeepholeDoubleRegsMap.clear(); + +    // Traverse the basic block. +    for (auto I = MBB->begin(), E = MBB->end(), NextI = I; I != E; I = NextI) { +      NextI = std::next(I); +      MachineInstr &MI = *I; +      // Look for sign extends: +      // %170 = SXTW %166 +      if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) { +        assert(MI.getNumOperands() == 2); +        MachineOperand &Dst = MI.getOperand(0); +        MachineOperand &Src = MI.getOperand(1); +        Register DstReg = Dst.getReg(); +        Register SrcReg = Src.getReg(); +        // Just handle virtual registers. +        if (Register::isVirtualRegister(DstReg) && +            Register::isVirtualRegister(SrcReg)) { +          // Map the following: +          // %170 = SXTW %166 +          // PeepholeMap[170] = %166 +          PeepholeMap[DstReg] = SrcReg; +        } +      } + +      // Look for  %170 = COMBINE_ir_V4 (0, %169) +      // %170:DoublRegs, %169:IntRegs +      if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) { +        assert(MI.getNumOperands() == 3); +        MachineOperand &Dst = MI.getOperand(0); +        MachineOperand &Src1 = MI.getOperand(1); +        MachineOperand &Src2 = MI.getOperand(2); +        if (Src1.getImm() != 0) +          continue; +        Register DstReg = Dst.getReg(); +        Register SrcReg = Src2.getReg(); +        PeepholeMap[DstReg] = SrcReg; +      } + +      // Look for this sequence below +      // %DoubleReg1 = LSRd_ri %DoubleReg0, 32 +      // %IntReg = COPY %DoubleReg1:isub_lo. +      // and convert into +      // %IntReg = COPY %DoubleReg0:isub_hi. +      if (MI.getOpcode() == Hexagon::S2_lsr_i_p) { +        assert(MI.getNumOperands() == 3); +        MachineOperand &Dst = MI.getOperand(0); +        MachineOperand &Src1 = MI.getOperand(1); +        MachineOperand &Src2 = MI.getOperand(2); +        if (Src2.getImm() != 32) +          continue; +        Register DstReg = Dst.getReg(); +        Register SrcReg = Src1.getReg(); +        PeepholeDoubleRegsMap[DstReg] = +          std::make_pair(*&SrcReg, Hexagon::isub_hi); +      } + +      // Look for P=NOT(P). +      if (!DisablePNotP && MI.getOpcode() == Hexagon::C2_not) { +        assert(MI.getNumOperands() == 2); +        MachineOperand &Dst = MI.getOperand(0); +        MachineOperand &Src = MI.getOperand(1); +        Register DstReg = Dst.getReg(); +        Register SrcReg = Src.getReg(); +        // Just handle virtual registers. +        if (Register::isVirtualRegister(DstReg) && +            Register::isVirtualRegister(SrcReg)) { +          // Map the following: +          // %170 = NOT_xx %166 +          // PeepholeMap[170] = %166 +          PeepholeMap[DstReg] = SrcReg; +        } +      } + +      // Look for copy: +      // %176 = COPY %170:isub_lo +      if (!DisableOptSZExt && MI.isCopy()) { +        assert(MI.getNumOperands() == 2); +        MachineOperand &Dst = MI.getOperand(0); +        MachineOperand &Src = MI.getOperand(1); + +        // Make sure we are copying the lower 32 bits. +        if (Src.getSubReg() != Hexagon::isub_lo) +          continue; + +        Register DstReg = Dst.getReg(); +        Register SrcReg = Src.getReg(); +        if (Register::isVirtualRegister(DstReg) && +            Register::isVirtualRegister(SrcReg)) { +          // Try to find in the map. +          if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) { +            // Change the 1st operand. +            MI.RemoveOperand(1); +            MI.addOperand(MachineOperand::CreateReg(PeepholeSrc, false)); +          } else  { +            DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI = +              PeepholeDoubleRegsMap.find(SrcReg); +            if (DI != PeepholeDoubleRegsMap.end()) { +              std::pair<unsigned,unsigned> PeepholeSrc = DI->second; +              MI.RemoveOperand(1); +              MI.addOperand(MachineOperand::CreateReg( +                  PeepholeSrc.first, false /*isDef*/, false /*isImp*/, +                  false /*isKill*/, false /*isDead*/, false /*isUndef*/, +                  false /*isEarlyClobber*/, PeepholeSrc.second)); +            } +          } +        } +      } + +      // Look for Predicated instructions. +      if (!DisablePNotP) { +        bool Done = false; +        if (QII->isPredicated(MI)) { +          MachineOperand &Op0 = MI.getOperand(0); +          Register Reg0 = Op0.getReg(); +          const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0); +          if (RC0->getID() == Hexagon::PredRegsRegClassID) { +            // Handle instructions that have a prediate register in op0 +            // (most cases of predicable instructions). +            if (Register::isVirtualRegister(Reg0)) { +              // Try to find in the map. +              if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) { +                // Change the 1st operand and, flip the opcode. +                MI.getOperand(0).setReg(PeepholeSrc); +                MRI->clearKillFlags(PeepholeSrc); +                int NewOp = QII->getInvertedPredicatedOpcode(MI.getOpcode()); +                MI.setDesc(QII->get(NewOp)); +                Done = true; +              } +            } +          } +        } + +        if (!Done) { +          // Handle special instructions. +          unsigned Op = MI.getOpcode(); +          unsigned NewOp = 0; +          unsigned PR = 1, S1 = 2, S2 = 3;   // Operand indices. + +          switch (Op) { +            case Hexagon::C2_mux: +            case Hexagon::C2_muxii: +              NewOp = Op; +              break; +            case Hexagon::C2_muxri: +              NewOp = Hexagon::C2_muxir; +              break; +            case Hexagon::C2_muxir: +              NewOp = Hexagon::C2_muxri; +              break; +          } +          if (NewOp) { +            Register PSrc = MI.getOperand(PR).getReg(); +            if (unsigned POrig = PeepholeMap.lookup(PSrc)) { +              BuildMI(*MBB, MI.getIterator(), MI.getDebugLoc(), +                      QII->get(NewOp), MI.getOperand(0).getReg()) +                .addReg(POrig) +                .add(MI.getOperand(S2)) +                .add(MI.getOperand(S1)); +              MRI->clearKillFlags(POrig); +              MI.eraseFromParent(); +            } +          } // if (NewOp) +        } // if (!Done) + +      } // if (!DisablePNotP) + +    } // Instruction +  } // Basic Block +  return true; +} + +FunctionPass *llvm::createHexagonPeephole() { +  return new HexagonPeephole(); +}  | 
