1ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//===-- HexagonPeephole.cpp - Hexagon Peephole Optimiztions ---------------===//
2ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
3ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//                     The LLVM Compiler Infrastructure
4ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
5ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// This file is distributed under the University of Illinois Open Source
6ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// License. See LICENSE.TXT for details.
7ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
8ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// This peephole pass optimizes in the following cases.
9ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// 1. Optimizes redundant sign extends for the following case
10ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//    Transform the following pattern
11ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//    %vreg170<def> = SXTW %vreg166
12ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//    ...
13ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//    %vreg176<def> = COPY %vreg170:subreg_loreg
14ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
15ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//    Into
16ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//    %vreg176<def> = COPY vreg166
17ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
18ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//  2. Optimizes redundant negation of predicates.
19ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     %vreg15<def> = CMPGTrr %vreg6, %vreg2
20ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     ...
21ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     %vreg16<def> = NOT_p %vreg15<kill>
22ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     ...
23ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     JMP_c %vreg16<kill>, <BB#1>, %PC<imp-def,dead>
24ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
25ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     Into
26ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     %vreg15<def> = CMPGTrr %vreg6, %vreg2;
27ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     ...
28ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//     JMP_cNot %vreg15<kill>, <BB#1>, %PC<imp-def,dead>;
29ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//
30ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// Note: The peephole pass makes the instrucstions like
31ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// %vreg170<def> = SXTW %vreg166 or %vreg16<def> = NOT_p %vreg15<kill>
32ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// redundant and relies on some form of dead removal instrucions, like
33ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande// DCE or DIE to actually eliminate them.
34ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
35ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
36ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande//===----------------------------------------------------------------------===//
37ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
38ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#define DEBUG_TYPE "hexagon-peephole"
3979aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#include "Hexagon.h"
4079aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#include "HexagonTargetMachine.h"
41ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/ADT/DenseMap.h"
42ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/ADT/Statistic.h"
43ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/CodeGen/MachineFunction.h"
44ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/CodeGen/MachineFunctionPass.h"
45ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/CodeGen/MachineInstrBuilder.h"
46ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/CodeGen/MachineRegisterInfo.h"
47d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/CodeGen/Passes.h"
480b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
49d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/PassSupport.h"
5079aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#include "llvm/Support/CommandLine.h"
51ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/Support/Debug.h"
52ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/Support/raw_ostream.h"
53d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetInstrInfo.h"
54ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/Target/TargetMachine.h"
55ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include "llvm/Target/TargetRegisterInfo.h"
56ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande#include <algorithm>
57ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
58ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandeusing namespace llvm;
59ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
60ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandestatic cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole",
61ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    cl::Hidden, cl::ZeroOrMore, cl::init(false),
62ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    cl::desc("Disable Peephole Optimization"));
63ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
64ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandestatic cl::opt<bool> DisablePNotP("disable-hexagon-pnotp",
65ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    cl::Hidden, cl::ZeroOrMore, cl::init(false),
66ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    cl::desc("Disable Optimization of PNotP"));
67ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
68ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandestatic cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext",
69ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    cl::Hidden, cl::ZeroOrMore, cl::init(false),
70ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    cl::desc("Disable Optimization of Sign/Zero Extends"));
71ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
7202d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkarstatic cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64",
7302d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar    cl::Hidden, cl::ZeroOrMore, cl::init(false),
7402d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar    cl::desc("Disable Optimization of extensions to i64."));
7502d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar
76942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszeknamespace llvm {
77942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek  void initializeHexagonPeepholePass(PassRegistry&);
78942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek}
79942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek
80ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandenamespace {
81ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  struct HexagonPeephole : public MachineFunctionPass {
82ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    const HexagonInstrInfo    *QII;
83ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    const HexagonRegisterInfo *QRI;
84ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    const MachineRegisterInfo *MRI;
85ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
86ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  public:
87ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    static char ID;
88942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek    HexagonPeephole() : MachineFunctionPass(ID) {
89942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek      initializeHexagonPeepholePass(*PassRegistry::getPassRegistry());
90942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek    }
91ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
92ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    bool runOnMachineFunction(MachineFunction &MF);
93ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
94ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    const char *getPassName() const {
95ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      return "Hexagon optimize redundant zero and size extends";
96ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    }
97ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
98ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    void getAnalysisUsage(AnalysisUsage &AU) const {
99ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      MachineFunctionPass::getAnalysisUsage(AU);
100ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    }
101ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
102ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  private:
103ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    void ChangeOpInto(MachineOperand &Dst, MachineOperand &Src);
104ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  };
105ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande}
106ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
107ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandechar HexagonPeephole::ID = 0;
108ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
109942940a3262242ac55efea88f818959f28d18bbaKrzysztof ParzyszekINITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole",
110942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszek                false, false)
111ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
112942940a3262242ac55efea88f818959f28d18bbaKrzysztof Parzyszekbool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
113ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  QII = static_cast<const HexagonInstrInfo *>(MF.getTarget().
114ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                                        getInstrInfo());
115ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  QRI = static_cast<const HexagonRegisterInfo *>(MF.getTarget().
116ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                                       getRegisterInfo());
117ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  MRI = &MF.getRegInfo();
118ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
119ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  DenseMap<unsigned, unsigned> PeepholeMap;
1204c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar  DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap;
121ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
122ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  if (DisableHexagonPeephole) return false;
123ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
124ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  // Loop over all of the basic blocks.
125ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end();
126ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande       MBBb != MBBe; ++MBBb) {
127ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    MachineBasicBlock* MBB = MBBb;
128ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    PeepholeMap.clear();
1294c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar    PeepholeDoubleRegsMap.clear();
130ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
131ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    // Traverse the basic block.
132ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
133ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                                     ++MII) {
134ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      MachineInstr *MI = MII;
135ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      // Look for sign extends:
136ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      // %vreg170<def> = SXTW %vreg166
137ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      if (!DisableOptSZExt && MI->getOpcode() == Hexagon::SXTW) {
138ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        assert (MI->getNumOperands() == 2);
139ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        MachineOperand &Dst = MI->getOperand(0);
140ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        MachineOperand &Src  = MI->getOperand(1);
141ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        unsigned DstReg = Dst.getReg();
142ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        unsigned SrcReg = Src.getReg();
143ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        // Just handle virtual registers.
144ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
145ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            TargetRegisterInfo::isVirtualRegister(SrcReg)) {
146ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // Map the following:
147ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // %vreg170<def> = SXTW %vreg166
148ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // PeepholeMap[170] = vreg166
149ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          PeepholeMap[DstReg] = SrcReg;
150ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        }
151ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      }
152ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
15302d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar      // Look for  %vreg170<def> = COMBINE_ir_V4 (0, %vreg169)
15402d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar      // %vreg170:DoublRegs, %vreg169:IntRegs
15502d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar      if (!DisableOptExtTo64 &&
15602d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar          MI->getOpcode () == Hexagon::COMBINE_Ir_V4) {
15702d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        assert (MI->getNumOperands() == 3);
15802d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        MachineOperand &Dst = MI->getOperand(0);
15902d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        MachineOperand &Src1 = MI->getOperand(1);
16002d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        MachineOperand &Src2 = MI->getOperand(2);
16102d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        if (Src1.getImm() != 0)
16202d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar          continue;
16302d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        unsigned DstReg = Dst.getReg();
16402d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        unsigned SrcReg = Src2.getReg();
16502d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar        PeepholeMap[DstReg] = SrcReg;
16602d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar      }
16702d937d86420409210291accd9aa023d97b4a8b5Pranav Bhandarkar
1684c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      // Look for this sequence below
1694c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      // %vregDoubleReg1 = LSRd_ri %vregDoubleReg0, 32
1704c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      // %vregIntReg = COPY %vregDoubleReg1:subreg_loreg.
1714c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      // and convert into
1724c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      // %vregIntReg = COPY %vregDoubleReg0:subreg_hireg.
1734c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      if (MI->getOpcode() == Hexagon::LSRd_ri) {
1744c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        assert(MI->getNumOperands() == 3);
1754c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        MachineOperand &Dst = MI->getOperand(0);
1764c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        MachineOperand &Src1 = MI->getOperand(1);
1774c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        MachineOperand &Src2 = MI->getOperand(2);
1784c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        if (Src2.getImm() != 32)
1794c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar          continue;
1804c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        unsigned DstReg = Dst.getReg();
1814c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        unsigned SrcReg = Src1.getReg();
1824c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar        PeepholeDoubleRegsMap[DstReg] =
1834c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar          std::make_pair(*&SrcReg, 1/*Hexagon::subreg_hireg*/);
1844c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar      }
1854c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar
186ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      // Look for P=NOT(P).
187ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      if (!DisablePNotP &&
188ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          (MI->getOpcode() == Hexagon::NOT_p)) {
189ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        assert (MI->getNumOperands() == 2);
190ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        MachineOperand &Dst = MI->getOperand(0);
191ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        MachineOperand &Src  = MI->getOperand(1);
192ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        unsigned DstReg = Dst.getReg();
193ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        unsigned SrcReg = Src.getReg();
194ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        // Just handle virtual registers.
195ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
196ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            TargetRegisterInfo::isVirtualRegister(SrcReg)) {
197ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // Map the following:
198ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // %vreg170<def> = NOT_xx %vreg166
199ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // PeepholeMap[170] = vreg166
200ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          PeepholeMap[DstReg] = SrcReg;
201ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        }
202ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      }
203ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
204ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      // Look for copy:
205ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      // %vreg176<def> = COPY %vreg170:subreg_loreg
206ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      if (!DisableOptSZExt && MI->isCopy()) {
207ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        assert (MI->getNumOperands() == 2);
208ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        MachineOperand &Dst = MI->getOperand(0);
209ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        MachineOperand &Src  = MI->getOperand(1);
210ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
211ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        // Make sure we are copying the lower 32 bits.
212ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        if (Src.getSubReg() != Hexagon::subreg_loreg)
213ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          continue;
214ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
215ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        unsigned DstReg = Dst.getReg();
216ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        unsigned SrcReg = Src.getReg();
217ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
218ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            TargetRegisterInfo::isVirtualRegister(SrcReg)) {
219ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // Try to find in the map.
220ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) {
221ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            // Change the 1st operand.
222ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            MI->RemoveOperand(1);
223ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            MI->addOperand(MachineOperand::CreateReg(PeepholeSrc, false));
2244c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar          } else  {
2254c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar            DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI =
2264c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar              PeepholeDoubleRegsMap.find(SrcReg);
2274c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar            if (DI != PeepholeDoubleRegsMap.end()) {
2284c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar              std::pair<unsigned,unsigned> PeepholeSrc = DI->second;
2294c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar              MI->RemoveOperand(1);
2304c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar              MI->addOperand(MachineOperand::CreateReg(PeepholeSrc.first,
2314c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       false /*isDef*/,
2324c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       false /*isImp*/,
2334c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       false /*isKill*/,
2344c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       false /*isDead*/,
2354c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       false /*isUndef*/,
2364c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       false /*isEarlyClobber*/,
2374c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar                                                       PeepholeSrc.second));
2384c3d3ecdf83cc85e81f2146f2942cf6931e9ce18Pranav Bhandarkar            }
239ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          }
240ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        }
241ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      }
242ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
243ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      // Look for Predicated instructions.
244ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      if (!DisablePNotP) {
245ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        bool Done = false;
246ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        if (QII->isPredicated(MI)) {
247ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          MachineOperand &Op0 = MI->getOperand(0);
248ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          unsigned Reg0 = Op0.getReg();
249ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0);
250ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          if (RC0->getID() == Hexagon::PredRegsRegClassID) {
251ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            // Handle instructions that have a prediate register in op0
252ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            // (most cases of predicable instructions).
253ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            if (TargetRegisterInfo::isVirtualRegister(Reg0)) {
254ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              // Try to find in the map.
255ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) {
256ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                // Change the 1st operand and, flip the opcode.
257ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                MI->getOperand(0).setReg(PeepholeSrc);
258ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                int NewOp = QII->getInvertedPredicatedOpcode(MI->getOpcode());
259ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                MI->setDesc(QII->get(NewOp));
260ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                Done = true;
261ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              }
262ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            }
263ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          }
264ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        }
265ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
266ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        if (!Done) {
267ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          // Handle special instructions.
268ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          unsigned Op = MI->getOpcode();
269ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          unsigned NewOp = 0;
270ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          unsigned PR = 1, S1 = 2, S2 = 3;   // Operand indices.
271ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
272ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          switch (Op) {
273ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::TFR_condset_rr:
274ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::TFR_condset_ii:
275ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::MUX_ii:
276ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::MUX_rr:
277ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              NewOp = Op;
278ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              break;
279ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::TFR_condset_ri:
280ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              NewOp = Hexagon::TFR_condset_ir;
281ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              break;
282ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::TFR_condset_ir:
283ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              NewOp = Hexagon::TFR_condset_ri;
284ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              break;
285ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::MUX_ri:
286ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              NewOp = Hexagon::MUX_ir;
287ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              break;
288ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            case Hexagon::MUX_ir:
289ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              NewOp = Hexagon::MUX_ri;
290ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              break;
291ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          }
292ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          if (NewOp) {
293ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            unsigned PSrc = MI->getOperand(PR).getReg();
294ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            if (unsigned POrig = PeepholeMap.lookup(PSrc)) {
295ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              MI->getOperand(PR).setReg(POrig);
296ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              MI->setDesc(QII->get(NewOp));
297ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              // Swap operands S1 and S2.
298ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              MachineOperand Op1 = MI->getOperand(S1);
299ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              MachineOperand Op2 = MI->getOperand(S2);
300ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              ChangeOpInto(MI->getOperand(S1), Op2);
301ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande              ChangeOpInto(MI->getOperand(S2), Op1);
302ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande            }
303ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande          } // if (NewOp)
304ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        } // if (!Done)
305ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
306ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      } // if (!DisablePNotP)
307ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
308ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    } // Instruction
309ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  } // Basic Block
310ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  return true;
311ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande}
312ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
313ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pandevoid HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) {
314ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  assert (&Dst != &Src && "Cannot duplicate into itself");
315ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  switch (Dst.getType()) {
316ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    case MachineOperand::MO_Register:
317ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      if (Src.isReg()) {
318ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        Dst.setReg(Src.getReg());
319ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      } else if (Src.isImm()) {
320ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        Dst.ChangeToImmediate(Src.getImm());
321ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      } else {
322ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        llvm_unreachable("Unexpected src operand type");
323ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      }
324ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      break;
325ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
326ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    case MachineOperand::MO_Immediate:
327ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      if (Src.isImm()) {
328ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        Dst.setImm(Src.getImm());
329ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      } else if (Src.isReg()) {
330ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(),
331ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                             Src.isKill(), Src.isDead(), Src.isUndef(),
332ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande                             Src.isDebug());
333ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      } else {
334ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande        llvm_unreachable("Unexpected src operand type");
335ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      }
336ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      break;
337ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
338ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande    default:
339ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      llvm_unreachable("Unexpected dst operand type");
340ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande      break;
341ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  }
342ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande}
343ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande
344ab7955b9ce3197215406bc9fc97b22074127d035Sirish PandeFunctionPass *llvm::createHexagonPeephole() {
345ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande  return new HexagonPeephole();
346ab7955b9ce3197215406bc9fc97b22074127d035Sirish Pande}
347