xref: /aosp_15_r20/external/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===----- HexagonNewValueJump.cpp - Hexagon Backend New Value Jump -------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This implements NewValueJump pass in Hexagon.
11*9880d681SAndroid Build Coastguard Worker // Ideally, we should merge this as a Peephole pass prior to register
12*9880d681SAndroid Build Coastguard Worker // allocation, but because we have a spill in between the feeder and new value
13*9880d681SAndroid Build Coastguard Worker // jump instructions, we are forced to write after register allocation.
14*9880d681SAndroid Build Coastguard Worker // Having said that, we should re-attempt to pull this earlier at some point
15*9880d681SAndroid Build Coastguard Worker // in future.
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker // The basic approach looks for sequence of predicated jump, compare instruciton
18*9880d681SAndroid Build Coastguard Worker // that genereates the predicate and, the feeder to the predicate. Once it finds
19*9880d681SAndroid Build Coastguard Worker // all, it collapses compare and jump instruction into a new valu jump
20*9880d681SAndroid Build Coastguard Worker // intstructions.
21*9880d681SAndroid Build Coastguard Worker //
22*9880d681SAndroid Build Coastguard Worker //
23*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
24*9880d681SAndroid Build Coastguard Worker #include "Hexagon.h"
25*9880d681SAndroid Build Coastguard Worker #include "HexagonInstrInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "HexagonMachineFunctionInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "HexagonRegisterInfo.h"
28*9880d681SAndroid Build Coastguard Worker #include "HexagonSubtarget.h"
29*9880d681SAndroid Build Coastguard Worker #include "HexagonTargetMachine.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/LiveVariables.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionAnalysis.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAGInstrs.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/PassSupport.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
45*9880d681SAndroid Build Coastguard Worker using namespace llvm;
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "hexagon-nvj"
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNVJGenerated, "Number of New Value Jump Instructions created");
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker static cl::opt<int>
52*9880d681SAndroid Build Coastguard Worker DbgNVJCount("nvj-count", cl::init(-1), cl::Hidden, cl::desc(
53*9880d681SAndroid Build Coastguard Worker   "Maximum number of predicated jumps to be converted to New Value Jump"));
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableNewValueJumps("disable-nvjump", cl::Hidden,
56*9880d681SAndroid Build Coastguard Worker     cl::ZeroOrMore, cl::init(false),
57*9880d681SAndroid Build Coastguard Worker     cl::desc("Disable New Value Jumps"));
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker namespace llvm {
60*9880d681SAndroid Build Coastguard Worker   FunctionPass *createHexagonNewValueJump();
61*9880d681SAndroid Build Coastguard Worker   void initializeHexagonNewValueJumpPass(PassRegistry&);
62*9880d681SAndroid Build Coastguard Worker }
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker namespace {
66*9880d681SAndroid Build Coastguard Worker   struct HexagonNewValueJump : public MachineFunctionPass {
67*9880d681SAndroid Build Coastguard Worker     const HexagonInstrInfo    *QII;
68*9880d681SAndroid Build Coastguard Worker     const HexagonRegisterInfo *QRI;
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   public:
71*9880d681SAndroid Build Coastguard Worker     static char ID;
72*9880d681SAndroid Build Coastguard Worker 
HexagonNewValueJump__anonf5871c040111::HexagonNewValueJump73*9880d681SAndroid Build Coastguard Worker     HexagonNewValueJump() : MachineFunctionPass(ID) {
74*9880d681SAndroid Build Coastguard Worker       initializeHexagonNewValueJumpPass(*PassRegistry::getPassRegistry());
75*9880d681SAndroid Build Coastguard Worker     }
76*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage__anonf5871c040111::HexagonNewValueJump77*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
78*9880d681SAndroid Build Coastguard Worker       AU.addRequired<MachineBranchProbabilityInfo>();
79*9880d681SAndroid Build Coastguard Worker       MachineFunctionPass::getAnalysisUsage(AU);
80*9880d681SAndroid Build Coastguard Worker     }
81*9880d681SAndroid Build Coastguard Worker 
getPassName__anonf5871c040111::HexagonNewValueJump82*9880d681SAndroid Build Coastguard Worker     const char *getPassName() const override {
83*9880d681SAndroid Build Coastguard Worker       return "Hexagon NewValueJump";
84*9880d681SAndroid Build Coastguard Worker     }
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker     bool runOnMachineFunction(MachineFunction &Fn) override;
getRequiredProperties__anonf5871c040111::HexagonNewValueJump87*9880d681SAndroid Build Coastguard Worker     MachineFunctionProperties getRequiredProperties() const override {
88*9880d681SAndroid Build Coastguard Worker       return MachineFunctionProperties().set(
89*9880d681SAndroid Build Coastguard Worker           MachineFunctionProperties::Property::AllVRegsAllocated);
90*9880d681SAndroid Build Coastguard Worker     }
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker   private:
93*9880d681SAndroid Build Coastguard Worker     /// \brief A handle to the branch probability pass.
94*9880d681SAndroid Build Coastguard Worker     const MachineBranchProbabilityInfo *MBPI;
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker     bool isNewValueJumpCandidate(const MachineInstr &MI) const;
97*9880d681SAndroid Build Coastguard Worker   };
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker } // end of anonymous namespace
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker char HexagonNewValueJump::ID = 0;
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(HexagonNewValueJump, "hexagon-nvj",
104*9880d681SAndroid Build Coastguard Worker                       "Hexagon NewValueJump", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)105*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
106*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(HexagonNewValueJump, "hexagon-nvj",
107*9880d681SAndroid Build Coastguard Worker                     "Hexagon NewValueJump", false, false)
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker // We have identified this II could be feeder to NVJ,
111*9880d681SAndroid Build Coastguard Worker // verify that it can be.
112*9880d681SAndroid Build Coastguard Worker static bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII,
113*9880d681SAndroid Build Coastguard Worker                                       const TargetRegisterInfo *TRI,
114*9880d681SAndroid Build Coastguard Worker                                       MachineBasicBlock::iterator II,
115*9880d681SAndroid Build Coastguard Worker                                       MachineBasicBlock::iterator end,
116*9880d681SAndroid Build Coastguard Worker                                       MachineBasicBlock::iterator skip,
117*9880d681SAndroid Build Coastguard Worker                                       MachineFunction &MF) {
118*9880d681SAndroid Build Coastguard Worker 
119*9880d681SAndroid Build Coastguard Worker   // Predicated instruction can not be feeder to NVJ.
120*9880d681SAndroid Build Coastguard Worker   if (QII->isPredicated(*II))
121*9880d681SAndroid Build Coastguard Worker     return false;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker   // Bail out if feederReg is a paired register (double regs in
124*9880d681SAndroid Build Coastguard Worker   // our case). One would think that we can check to see if a given
125*9880d681SAndroid Build Coastguard Worker   // register cmpReg1 or cmpReg2 is a sub register of feederReg
126*9880d681SAndroid Build Coastguard Worker   // using -- if (QRI->isSubRegister(feederReg, cmpReg1) logic
127*9880d681SAndroid Build Coastguard Worker   // before the callsite of this function
128*9880d681SAndroid Build Coastguard Worker   // But we can not as it comes in the following fashion.
129*9880d681SAndroid Build Coastguard Worker   //    %D0<def> = Hexagon_S2_lsr_r_p %D0<kill>, %R2<kill>
130*9880d681SAndroid Build Coastguard Worker   //    %R0<def> = KILL %R0, %D0<imp-use,kill>
131*9880d681SAndroid Build Coastguard Worker   //    %P0<def> = CMPEQri %R0<kill>, 0
132*9880d681SAndroid Build Coastguard Worker   // Hence, we need to check if it's a KILL instruction.
133*9880d681SAndroid Build Coastguard Worker   if (II->getOpcode() == TargetOpcode::KILL)
134*9880d681SAndroid Build Coastguard Worker     return false;
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker   // Make sure there there is no 'def' or 'use' of any of the uses of
138*9880d681SAndroid Build Coastguard Worker   // feeder insn between it's definition, this MI and jump, jmpInst
139*9880d681SAndroid Build Coastguard Worker   // skipping compare, cmpInst.
140*9880d681SAndroid Build Coastguard Worker   // Here's the example.
141*9880d681SAndroid Build Coastguard Worker   //    r21=memub(r22+r24<<#0)
142*9880d681SAndroid Build Coastguard Worker   //    p0 = cmp.eq(r21, #0)
143*9880d681SAndroid Build Coastguard Worker   //    r4=memub(r3+r21<<#0)
144*9880d681SAndroid Build Coastguard Worker   //    if (p0.new) jump:t .LBB29_45
145*9880d681SAndroid Build Coastguard Worker   // Without this check, it will be converted into
146*9880d681SAndroid Build Coastguard Worker   //    r4=memub(r3+r21<<#0)
147*9880d681SAndroid Build Coastguard Worker   //    r21=memub(r22+r24<<#0)
148*9880d681SAndroid Build Coastguard Worker   //    p0 = cmp.eq(r21, #0)
149*9880d681SAndroid Build Coastguard Worker   //    if (p0.new) jump:t .LBB29_45
150*9880d681SAndroid Build Coastguard Worker   // and result WAR hazards if converted to New Value Jump.
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < II->getNumOperands(); ++i) {
153*9880d681SAndroid Build Coastguard Worker     if (II->getOperand(i).isReg() &&
154*9880d681SAndroid Build Coastguard Worker         (II->getOperand(i).isUse() || II->getOperand(i).isDef())) {
155*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock::iterator localII = II;
156*9880d681SAndroid Build Coastguard Worker       ++localII;
157*9880d681SAndroid Build Coastguard Worker       unsigned Reg = II->getOperand(i).getReg();
158*9880d681SAndroid Build Coastguard Worker       for (MachineBasicBlock::iterator localBegin = localII;
159*9880d681SAndroid Build Coastguard Worker                         localBegin != end; ++localBegin) {
160*9880d681SAndroid Build Coastguard Worker         if (localBegin == skip ) continue;
161*9880d681SAndroid Build Coastguard Worker         // Check for Subregisters too.
162*9880d681SAndroid Build Coastguard Worker         if (localBegin->modifiesRegister(Reg, TRI) ||
163*9880d681SAndroid Build Coastguard Worker             localBegin->readsRegister(Reg, TRI))
164*9880d681SAndroid Build Coastguard Worker           return false;
165*9880d681SAndroid Build Coastguard Worker       }
166*9880d681SAndroid Build Coastguard Worker     }
167*9880d681SAndroid Build Coastguard Worker   }
168*9880d681SAndroid Build Coastguard Worker   return true;
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker // These are the common checks that need to performed
172*9880d681SAndroid Build Coastguard Worker // to determine if
173*9880d681SAndroid Build Coastguard Worker // 1. compare instruction can be moved before jump.
174*9880d681SAndroid Build Coastguard Worker // 2. feeder to the compare instruction can be moved before jump.
commonChecksToProhibitNewValueJump(bool afterRA,MachineBasicBlock::iterator MII)175*9880d681SAndroid Build Coastguard Worker static bool commonChecksToProhibitNewValueJump(bool afterRA,
176*9880d681SAndroid Build Coastguard Worker                           MachineBasicBlock::iterator MII) {
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker   // If store in path, bail out.
179*9880d681SAndroid Build Coastguard Worker   if (MII->getDesc().mayStore())
180*9880d681SAndroid Build Coastguard Worker     return false;
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker   // if call in path, bail out.
183*9880d681SAndroid Build Coastguard Worker   if (MII->getOpcode() == Hexagon::J2_call)
184*9880d681SAndroid Build Coastguard Worker     return false;
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker   // if NVJ is running prior to RA, do the following checks.
187*9880d681SAndroid Build Coastguard Worker   if (!afterRA) {
188*9880d681SAndroid Build Coastguard Worker     // The following Target Opcode instructions are spurious
189*9880d681SAndroid Build Coastguard Worker     // to new value jump. If they are in the path, bail out.
190*9880d681SAndroid Build Coastguard Worker     // KILL sets kill flag on the opcode. It also sets up a
191*9880d681SAndroid Build Coastguard Worker     // single register, out of pair.
192*9880d681SAndroid Build Coastguard Worker     //    %D0<def> = Hexagon_S2_lsr_r_p %D0<kill>, %R2<kill>
193*9880d681SAndroid Build Coastguard Worker     //    %R0<def> = KILL %R0, %D0<imp-use,kill>
194*9880d681SAndroid Build Coastguard Worker     //    %P0<def> = CMPEQri %R0<kill>, 0
195*9880d681SAndroid Build Coastguard Worker     // PHI can be anything after RA.
196*9880d681SAndroid Build Coastguard Worker     // COPY can remateriaze things in between feeder, compare and nvj.
197*9880d681SAndroid Build Coastguard Worker     if (MII->getOpcode() == TargetOpcode::KILL ||
198*9880d681SAndroid Build Coastguard Worker         MII->getOpcode() == TargetOpcode::PHI  ||
199*9880d681SAndroid Build Coastguard Worker         MII->getOpcode() == TargetOpcode::COPY)
200*9880d681SAndroid Build Coastguard Worker       return false;
201*9880d681SAndroid Build Coastguard Worker 
202*9880d681SAndroid Build Coastguard Worker     // The following pseudo Hexagon instructions sets "use" and "def"
203*9880d681SAndroid Build Coastguard Worker     // of registers by individual passes in the backend. At this time,
204*9880d681SAndroid Build Coastguard Worker     // we don't know the scope of usage and definitions of these
205*9880d681SAndroid Build Coastguard Worker     // instructions.
206*9880d681SAndroid Build Coastguard Worker     if (MII->getOpcode() == Hexagon::LDriw_pred     ||
207*9880d681SAndroid Build Coastguard Worker         MII->getOpcode() == Hexagon::STriw_pred)
208*9880d681SAndroid Build Coastguard Worker       return false;
209*9880d681SAndroid Build Coastguard Worker   }
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker   return true;
212*9880d681SAndroid Build Coastguard Worker }
213*9880d681SAndroid Build Coastguard Worker 
canCompareBeNewValueJump(const HexagonInstrInfo * QII,const TargetRegisterInfo * TRI,MachineBasicBlock::iterator II,unsigned pReg,bool secondReg,bool optLocation,MachineBasicBlock::iterator end,MachineFunction & MF)214*9880d681SAndroid Build Coastguard Worker static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII,
215*9880d681SAndroid Build Coastguard Worker                                      const TargetRegisterInfo *TRI,
216*9880d681SAndroid Build Coastguard Worker                                      MachineBasicBlock::iterator II,
217*9880d681SAndroid Build Coastguard Worker                                      unsigned pReg,
218*9880d681SAndroid Build Coastguard Worker                                      bool secondReg,
219*9880d681SAndroid Build Coastguard Worker                                      bool optLocation,
220*9880d681SAndroid Build Coastguard Worker                                      MachineBasicBlock::iterator end,
221*9880d681SAndroid Build Coastguard Worker                                      MachineFunction &MF) {
222*9880d681SAndroid Build Coastguard Worker 
223*9880d681SAndroid Build Coastguard Worker   MachineInstr &MI = *II;
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker   // If the second operand of the compare is an imm, make sure it's in the
226*9880d681SAndroid Build Coastguard Worker   // range specified by the arch.
227*9880d681SAndroid Build Coastguard Worker   if (!secondReg) {
228*9880d681SAndroid Build Coastguard Worker     int64_t v = MI.getOperand(2).getImm();
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker     if (!(isUInt<5>(v) || ((MI.getOpcode() == Hexagon::C2_cmpeqi ||
231*9880d681SAndroid Build Coastguard Worker                             MI.getOpcode() == Hexagon::C2_cmpgti) &&
232*9880d681SAndroid Build Coastguard Worker                            (v == -1))))
233*9880d681SAndroid Build Coastguard Worker       return false;
234*9880d681SAndroid Build Coastguard Worker   }
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker   unsigned cmpReg1, cmpOp2 = 0; // cmpOp2 assignment silences compiler warning.
237*9880d681SAndroid Build Coastguard Worker   cmpReg1 = MI.getOperand(1).getReg();
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker   if (secondReg) {
240*9880d681SAndroid Build Coastguard Worker     cmpOp2 = MI.getOperand(2).getReg();
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker     // Make sure that that second register is not from COPY
243*9880d681SAndroid Build Coastguard Worker     // At machine code level, we don't need this, but if we decide
244*9880d681SAndroid Build Coastguard Worker     // to move new value jump prior to RA, we would be needing this.
245*9880d681SAndroid Build Coastguard Worker     MachineRegisterInfo &MRI = MF.getRegInfo();
246*9880d681SAndroid Build Coastguard Worker     if (secondReg && !TargetRegisterInfo::isPhysicalRegister(cmpOp2)) {
247*9880d681SAndroid Build Coastguard Worker       MachineInstr *def = MRI.getVRegDef(cmpOp2);
248*9880d681SAndroid Build Coastguard Worker       if (def->getOpcode() == TargetOpcode::COPY)
249*9880d681SAndroid Build Coastguard Worker         return false;
250*9880d681SAndroid Build Coastguard Worker     }
251*9880d681SAndroid Build Coastguard Worker   }
252*9880d681SAndroid Build Coastguard Worker 
253*9880d681SAndroid Build Coastguard Worker   // Walk the instructions after the compare (predicate def) to the jump,
254*9880d681SAndroid Build Coastguard Worker   // and satisfy the following conditions.
255*9880d681SAndroid Build Coastguard Worker   ++II ;
256*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::iterator localII = II; localII != end;
257*9880d681SAndroid Build Coastguard Worker        ++localII) {
258*9880d681SAndroid Build Coastguard Worker 
259*9880d681SAndroid Build Coastguard Worker     // Check 1.
260*9880d681SAndroid Build Coastguard Worker     // If "common" checks fail, bail out.
261*9880d681SAndroid Build Coastguard Worker     if (!commonChecksToProhibitNewValueJump(optLocation, localII))
262*9880d681SAndroid Build Coastguard Worker       return false;
263*9880d681SAndroid Build Coastguard Worker 
264*9880d681SAndroid Build Coastguard Worker     // Check 2.
265*9880d681SAndroid Build Coastguard Worker     // If there is a def or use of predicate (result of compare), bail out.
266*9880d681SAndroid Build Coastguard Worker     if (localII->modifiesRegister(pReg, TRI) ||
267*9880d681SAndroid Build Coastguard Worker         localII->readsRegister(pReg, TRI))
268*9880d681SAndroid Build Coastguard Worker       return false;
269*9880d681SAndroid Build Coastguard Worker 
270*9880d681SAndroid Build Coastguard Worker     // Check 3.
271*9880d681SAndroid Build Coastguard Worker     // If there is a def of any of the use of the compare (operands of compare),
272*9880d681SAndroid Build Coastguard Worker     // bail out.
273*9880d681SAndroid Build Coastguard Worker     // Eg.
274*9880d681SAndroid Build Coastguard Worker     //    p0 = cmp.eq(r2, r0)
275*9880d681SAndroid Build Coastguard Worker     //    r2 = r4
276*9880d681SAndroid Build Coastguard Worker     //    if (p0.new) jump:t .LBB28_3
277*9880d681SAndroid Build Coastguard Worker     if (localII->modifiesRegister(cmpReg1, TRI) ||
278*9880d681SAndroid Build Coastguard Worker         (secondReg && localII->modifiesRegister(cmpOp2, TRI)))
279*9880d681SAndroid Build Coastguard Worker       return false;
280*9880d681SAndroid Build Coastguard Worker   }
281*9880d681SAndroid Build Coastguard Worker   return true;
282*9880d681SAndroid Build Coastguard Worker }
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker // Given a compare operator, return a matching New Value Jump compare operator.
286*9880d681SAndroid Build Coastguard Worker // Make sure that MI here is included in isNewValueJumpCandidate.
getNewValueJumpOpcode(MachineInstr * MI,int reg,bool secondRegNewified,MachineBasicBlock * jmpTarget,const MachineBranchProbabilityInfo * MBPI)287*9880d681SAndroid Build Coastguard Worker static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg,
288*9880d681SAndroid Build Coastguard Worker                                       bool secondRegNewified,
289*9880d681SAndroid Build Coastguard Worker                                       MachineBasicBlock *jmpTarget,
290*9880d681SAndroid Build Coastguard Worker                                       const MachineBranchProbabilityInfo
291*9880d681SAndroid Build Coastguard Worker                                       *MBPI) {
292*9880d681SAndroid Build Coastguard Worker   bool taken = false;
293*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *Src = MI->getParent();
294*9880d681SAndroid Build Coastguard Worker   const BranchProbability Prediction =
295*9880d681SAndroid Build Coastguard Worker     MBPI->getEdgeProbability(Src, jmpTarget);
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker   if (Prediction >= BranchProbability(1,2))
298*9880d681SAndroid Build Coastguard Worker     taken = true;
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   switch (MI->getOpcode()) {
301*9880d681SAndroid Build Coastguard Worker     case Hexagon::C2_cmpeq:
302*9880d681SAndroid Build Coastguard Worker       return taken ? Hexagon::J4_cmpeq_t_jumpnv_t
303*9880d681SAndroid Build Coastguard Worker                    : Hexagon::J4_cmpeq_t_jumpnv_nt;
304*9880d681SAndroid Build Coastguard Worker 
305*9880d681SAndroid Build Coastguard Worker     case Hexagon::C2_cmpeqi: {
306*9880d681SAndroid Build Coastguard Worker       if (reg >= 0)
307*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t
308*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpeqi_t_jumpnv_nt;
309*9880d681SAndroid Build Coastguard Worker       else
310*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t
311*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpeqn1_t_jumpnv_nt;
312*9880d681SAndroid Build Coastguard Worker     }
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker     case Hexagon::C2_cmpgt: {
315*9880d681SAndroid Build Coastguard Worker       if (secondRegNewified)
316*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmplt_t_jumpnv_t
317*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmplt_t_jumpnv_nt;
318*9880d681SAndroid Build Coastguard Worker       else
319*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpgt_t_jumpnv_t
320*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpgt_t_jumpnv_nt;
321*9880d681SAndroid Build Coastguard Worker     }
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker     case Hexagon::C2_cmpgti: {
324*9880d681SAndroid Build Coastguard Worker       if (reg >= 0)
325*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpgti_t_jumpnv_t
326*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpgti_t_jumpnv_nt;
327*9880d681SAndroid Build Coastguard Worker       else
328*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t
329*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpgtn1_t_jumpnv_nt;
330*9880d681SAndroid Build Coastguard Worker     }
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker     case Hexagon::C2_cmpgtu: {
333*9880d681SAndroid Build Coastguard Worker       if (secondRegNewified)
334*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpltu_t_jumpnv_t
335*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpltu_t_jumpnv_nt;
336*9880d681SAndroid Build Coastguard Worker       else
337*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t
338*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpgtu_t_jumpnv_nt;
339*9880d681SAndroid Build Coastguard Worker     }
340*9880d681SAndroid Build Coastguard Worker 
341*9880d681SAndroid Build Coastguard Worker     case Hexagon::C2_cmpgtui:
342*9880d681SAndroid Build Coastguard Worker       return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t
343*9880d681SAndroid Build Coastguard Worker                    : Hexagon::J4_cmpgtui_t_jumpnv_nt;
344*9880d681SAndroid Build Coastguard Worker 
345*9880d681SAndroid Build Coastguard Worker     case Hexagon::C4_cmpneq:
346*9880d681SAndroid Build Coastguard Worker       return taken ? Hexagon::J4_cmpeq_f_jumpnv_t
347*9880d681SAndroid Build Coastguard Worker                    : Hexagon::J4_cmpeq_f_jumpnv_nt;
348*9880d681SAndroid Build Coastguard Worker 
349*9880d681SAndroid Build Coastguard Worker     case Hexagon::C4_cmplte:
350*9880d681SAndroid Build Coastguard Worker       if (secondRegNewified)
351*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmplt_f_jumpnv_t
352*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmplt_f_jumpnv_nt;
353*9880d681SAndroid Build Coastguard Worker       return taken ? Hexagon::J4_cmpgt_f_jumpnv_t
354*9880d681SAndroid Build Coastguard Worker                    : Hexagon::J4_cmpgt_f_jumpnv_nt;
355*9880d681SAndroid Build Coastguard Worker 
356*9880d681SAndroid Build Coastguard Worker     case Hexagon::C4_cmplteu:
357*9880d681SAndroid Build Coastguard Worker       if (secondRegNewified)
358*9880d681SAndroid Build Coastguard Worker         return taken ? Hexagon::J4_cmpltu_f_jumpnv_t
359*9880d681SAndroid Build Coastguard Worker                      : Hexagon::J4_cmpltu_f_jumpnv_nt;
360*9880d681SAndroid Build Coastguard Worker       return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t
361*9880d681SAndroid Build Coastguard Worker                    : Hexagon::J4_cmpgtu_f_jumpnv_nt;
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker     default:
364*9880d681SAndroid Build Coastguard Worker        llvm_unreachable("Could not find matching New Value Jump instruction.");
365*9880d681SAndroid Build Coastguard Worker   }
366*9880d681SAndroid Build Coastguard Worker   // return *some value* to avoid compiler warning
367*9880d681SAndroid Build Coastguard Worker   return 0;
368*9880d681SAndroid Build Coastguard Worker }
369*9880d681SAndroid Build Coastguard Worker 
isNewValueJumpCandidate(const MachineInstr & MI) const370*9880d681SAndroid Build Coastguard Worker bool HexagonNewValueJump::isNewValueJumpCandidate(
371*9880d681SAndroid Build Coastguard Worker     const MachineInstr &MI) const {
372*9880d681SAndroid Build Coastguard Worker   switch (MI.getOpcode()) {
373*9880d681SAndroid Build Coastguard Worker   case Hexagon::C2_cmpeq:
374*9880d681SAndroid Build Coastguard Worker   case Hexagon::C2_cmpeqi:
375*9880d681SAndroid Build Coastguard Worker   case Hexagon::C2_cmpgt:
376*9880d681SAndroid Build Coastguard Worker   case Hexagon::C2_cmpgti:
377*9880d681SAndroid Build Coastguard Worker   case Hexagon::C2_cmpgtu:
378*9880d681SAndroid Build Coastguard Worker   case Hexagon::C2_cmpgtui:
379*9880d681SAndroid Build Coastguard Worker   case Hexagon::C4_cmpneq:
380*9880d681SAndroid Build Coastguard Worker   case Hexagon::C4_cmplte:
381*9880d681SAndroid Build Coastguard Worker   case Hexagon::C4_cmplteu:
382*9880d681SAndroid Build Coastguard Worker     return true;
383*9880d681SAndroid Build Coastguard Worker 
384*9880d681SAndroid Build Coastguard Worker   default:
385*9880d681SAndroid Build Coastguard Worker     return false;
386*9880d681SAndroid Build Coastguard Worker   }
387*9880d681SAndroid Build Coastguard Worker }
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MF)390*9880d681SAndroid Build Coastguard Worker bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "********** Hexagon New Value Jump **********\n"
393*9880d681SAndroid Build Coastguard Worker                << "********** Function: "
394*9880d681SAndroid Build Coastguard Worker                << MF.getName() << "\n");
395*9880d681SAndroid Build Coastguard Worker 
396*9880d681SAndroid Build Coastguard Worker   if (skipFunction(*MF.getFunction()))
397*9880d681SAndroid Build Coastguard Worker     return false;
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker   // If we move NewValueJump before register allocation we'll need live variable
400*9880d681SAndroid Build Coastguard Worker   // analysis here too.
401*9880d681SAndroid Build Coastguard Worker 
402*9880d681SAndroid Build Coastguard Worker   QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
403*9880d681SAndroid Build Coastguard Worker   QRI = static_cast<const HexagonRegisterInfo *>(
404*9880d681SAndroid Build Coastguard Worker       MF.getSubtarget().getRegisterInfo());
405*9880d681SAndroid Build Coastguard Worker   MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
406*9880d681SAndroid Build Coastguard Worker 
407*9880d681SAndroid Build Coastguard Worker   if (DisableNewValueJumps) {
408*9880d681SAndroid Build Coastguard Worker     return false;
409*9880d681SAndroid Build Coastguard Worker   }
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker   int nvjCount = DbgNVJCount;
412*9880d681SAndroid Build Coastguard Worker   int nvjGenerated = 0;
413*9880d681SAndroid Build Coastguard Worker 
414*9880d681SAndroid Build Coastguard Worker   // Loop through all the bb's of the function
415*9880d681SAndroid Build Coastguard Worker   for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end();
416*9880d681SAndroid Build Coastguard Worker         MBBb != MBBe; ++MBBb) {
417*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB = &*MBBb;
418*9880d681SAndroid Build Coastguard Worker 
419*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "** dumping bb ** "
420*9880d681SAndroid Build Coastguard Worker                  << MBB->getNumber() << "\n");
421*9880d681SAndroid Build Coastguard Worker     DEBUG(MBB->dump());
422*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "\n" << "********** dumping instr bottom up **********\n");
423*9880d681SAndroid Build Coastguard Worker     bool foundJump    = false;
424*9880d681SAndroid Build Coastguard Worker     bool foundCompare = false;
425*9880d681SAndroid Build Coastguard Worker     bool invertPredicate = false;
426*9880d681SAndroid Build Coastguard Worker     unsigned predReg = 0; // predicate reg of the jump.
427*9880d681SAndroid Build Coastguard Worker     unsigned cmpReg1 = 0;
428*9880d681SAndroid Build Coastguard Worker     int cmpOp2 = 0;
429*9880d681SAndroid Build Coastguard Worker     bool MO1IsKill = false;
430*9880d681SAndroid Build Coastguard Worker     bool MO2IsKill = false;
431*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator jmpPos;
432*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator cmpPos;
433*9880d681SAndroid Build Coastguard Worker     MachineInstr *cmpInstr = nullptr, *jmpInstr = nullptr;
434*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *jmpTarget = nullptr;
435*9880d681SAndroid Build Coastguard Worker     bool afterRA = false;
436*9880d681SAndroid Build Coastguard Worker     bool isSecondOpReg = false;
437*9880d681SAndroid Build Coastguard Worker     bool isSecondOpNewified = false;
438*9880d681SAndroid Build Coastguard Worker     // Traverse the basic block - bottom up
439*9880d681SAndroid Build Coastguard Worker     for (MachineBasicBlock::iterator MII = MBB->end(), E = MBB->begin();
440*9880d681SAndroid Build Coastguard Worker              MII != E;) {
441*9880d681SAndroid Build Coastguard Worker       MachineInstr &MI = *--MII;
442*9880d681SAndroid Build Coastguard Worker       if (MI.isDebugValue()) {
443*9880d681SAndroid Build Coastguard Worker         continue;
444*9880d681SAndroid Build Coastguard Worker       }
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker       if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated))
447*9880d681SAndroid Build Coastguard Worker         break;
448*9880d681SAndroid Build Coastguard Worker 
449*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "Instr: "; MI.dump(); dbgs() << "\n");
450*9880d681SAndroid Build Coastguard Worker 
451*9880d681SAndroid Build Coastguard Worker       if (!foundJump && (MI.getOpcode() == Hexagon::J2_jumpt ||
452*9880d681SAndroid Build Coastguard Worker                          MI.getOpcode() == Hexagon::J2_jumpf ||
453*9880d681SAndroid Build Coastguard Worker                          MI.getOpcode() == Hexagon::J2_jumptnewpt ||
454*9880d681SAndroid Build Coastguard Worker                          MI.getOpcode() == Hexagon::J2_jumptnew ||
455*9880d681SAndroid Build Coastguard Worker                          MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
456*9880d681SAndroid Build Coastguard Worker                          MI.getOpcode() == Hexagon::J2_jumpfnew)) {
457*9880d681SAndroid Build Coastguard Worker         // This is where you would insert your compare and
458*9880d681SAndroid Build Coastguard Worker         // instr that feeds compare
459*9880d681SAndroid Build Coastguard Worker         jmpPos = MII;
460*9880d681SAndroid Build Coastguard Worker         jmpInstr = &MI;
461*9880d681SAndroid Build Coastguard Worker         predReg = MI.getOperand(0).getReg();
462*9880d681SAndroid Build Coastguard Worker         afterRA = TargetRegisterInfo::isPhysicalRegister(predReg);
463*9880d681SAndroid Build Coastguard Worker 
464*9880d681SAndroid Build Coastguard Worker         // If ifconverter had not messed up with the kill flags of the
465*9880d681SAndroid Build Coastguard Worker         // operands, the following check on the kill flag would suffice.
466*9880d681SAndroid Build Coastguard Worker         // if(!jmpInstr->getOperand(0).isKill()) break;
467*9880d681SAndroid Build Coastguard Worker 
468*9880d681SAndroid Build Coastguard Worker         // This predicate register is live out out of BB
469*9880d681SAndroid Build Coastguard Worker         // this would only work if we can actually use Live
470*9880d681SAndroid Build Coastguard Worker         // variable analysis on phy regs - but LLVM does not
471*9880d681SAndroid Build Coastguard Worker         // provide LV analysis on phys regs.
472*9880d681SAndroid Build Coastguard Worker         //if(LVs.isLiveOut(predReg, *MBB)) break;
473*9880d681SAndroid Build Coastguard Worker 
474*9880d681SAndroid Build Coastguard Worker         // Get all the successors of this block - which will always
475*9880d681SAndroid Build Coastguard Worker         // be 2. Check if the predicate register is live in in those
476*9880d681SAndroid Build Coastguard Worker         // successor. If yes, we can not delete the predicate -
477*9880d681SAndroid Build Coastguard Worker         // I am doing this only because LLVM does not provide LiveOut
478*9880d681SAndroid Build Coastguard Worker         // at the BB level.
479*9880d681SAndroid Build Coastguard Worker         bool predLive = false;
480*9880d681SAndroid Build Coastguard Worker         for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(),
481*9880d681SAndroid Build Coastguard Worker                             SIE = MBB->succ_end(); SI != SIE; ++SI) {
482*9880d681SAndroid Build Coastguard Worker           MachineBasicBlock* succMBB = *SI;
483*9880d681SAndroid Build Coastguard Worker          if (succMBB->isLiveIn(predReg)) {
484*9880d681SAndroid Build Coastguard Worker             predLive = true;
485*9880d681SAndroid Build Coastguard Worker           }
486*9880d681SAndroid Build Coastguard Worker         }
487*9880d681SAndroid Build Coastguard Worker         if (predLive)
488*9880d681SAndroid Build Coastguard Worker           break;
489*9880d681SAndroid Build Coastguard Worker 
490*9880d681SAndroid Build Coastguard Worker         if (!MI.getOperand(1).isMBB())
491*9880d681SAndroid Build Coastguard Worker           continue;
492*9880d681SAndroid Build Coastguard Worker         jmpTarget = MI.getOperand(1).getMBB();
493*9880d681SAndroid Build Coastguard Worker         foundJump = true;
494*9880d681SAndroid Build Coastguard Worker         if (MI.getOpcode() == Hexagon::J2_jumpf ||
495*9880d681SAndroid Build Coastguard Worker             MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
496*9880d681SAndroid Build Coastguard Worker             MI.getOpcode() == Hexagon::J2_jumpfnew) {
497*9880d681SAndroid Build Coastguard Worker           invertPredicate = true;
498*9880d681SAndroid Build Coastguard Worker         }
499*9880d681SAndroid Build Coastguard Worker         continue;
500*9880d681SAndroid Build Coastguard Worker       }
501*9880d681SAndroid Build Coastguard Worker 
502*9880d681SAndroid Build Coastguard Worker       // No new value jump if there is a barrier. A barrier has to be in its
503*9880d681SAndroid Build Coastguard Worker       // own packet. A barrier has zero operands. We conservatively bail out
504*9880d681SAndroid Build Coastguard Worker       // here if we see any instruction with zero operands.
505*9880d681SAndroid Build Coastguard Worker       if (foundJump && MI.getNumOperands() == 0)
506*9880d681SAndroid Build Coastguard Worker         break;
507*9880d681SAndroid Build Coastguard Worker 
508*9880d681SAndroid Build Coastguard Worker       if (foundJump && !foundCompare && MI.getOperand(0).isReg() &&
509*9880d681SAndroid Build Coastguard Worker           MI.getOperand(0).getReg() == predReg) {
510*9880d681SAndroid Build Coastguard Worker 
511*9880d681SAndroid Build Coastguard Worker         // Not all compares can be new value compare. Arch Spec: 7.6.1.1
512*9880d681SAndroid Build Coastguard Worker         if (isNewValueJumpCandidate(MI)) {
513*9880d681SAndroid Build Coastguard Worker 
514*9880d681SAndroid Build Coastguard Worker           assert(
515*9880d681SAndroid Build Coastguard Worker               (MI.getDesc().isCompare()) &&
516*9880d681SAndroid Build Coastguard Worker               "Only compare instruction can be collapsed into New Value Jump");
517*9880d681SAndroid Build Coastguard Worker           isSecondOpReg = MI.getOperand(2).isReg();
518*9880d681SAndroid Build Coastguard Worker 
519*9880d681SAndroid Build Coastguard Worker           if (!canCompareBeNewValueJump(QII, QRI, MII, predReg, isSecondOpReg,
520*9880d681SAndroid Build Coastguard Worker                                         afterRA, jmpPos, MF))
521*9880d681SAndroid Build Coastguard Worker             break;
522*9880d681SAndroid Build Coastguard Worker 
523*9880d681SAndroid Build Coastguard Worker           cmpInstr = &MI;
524*9880d681SAndroid Build Coastguard Worker           cmpPos = MII;
525*9880d681SAndroid Build Coastguard Worker           foundCompare = true;
526*9880d681SAndroid Build Coastguard Worker 
527*9880d681SAndroid Build Coastguard Worker           // We need cmpReg1 and cmpOp2(imm or reg) while building
528*9880d681SAndroid Build Coastguard Worker           // new value jump instruction.
529*9880d681SAndroid Build Coastguard Worker           cmpReg1 = MI.getOperand(1).getReg();
530*9880d681SAndroid Build Coastguard Worker           if (MI.getOperand(1).isKill())
531*9880d681SAndroid Build Coastguard Worker             MO1IsKill = true;
532*9880d681SAndroid Build Coastguard Worker 
533*9880d681SAndroid Build Coastguard Worker           if (isSecondOpReg) {
534*9880d681SAndroid Build Coastguard Worker             cmpOp2 = MI.getOperand(2).getReg();
535*9880d681SAndroid Build Coastguard Worker             if (MI.getOperand(2).isKill())
536*9880d681SAndroid Build Coastguard Worker               MO2IsKill = true;
537*9880d681SAndroid Build Coastguard Worker           } else
538*9880d681SAndroid Build Coastguard Worker             cmpOp2 = MI.getOperand(2).getImm();
539*9880d681SAndroid Build Coastguard Worker           continue;
540*9880d681SAndroid Build Coastguard Worker         }
541*9880d681SAndroid Build Coastguard Worker       }
542*9880d681SAndroid Build Coastguard Worker 
543*9880d681SAndroid Build Coastguard Worker       if (foundCompare && foundJump) {
544*9880d681SAndroid Build Coastguard Worker 
545*9880d681SAndroid Build Coastguard Worker         // If "common" checks fail, bail out on this BB.
546*9880d681SAndroid Build Coastguard Worker         if (!commonChecksToProhibitNewValueJump(afterRA, MII))
547*9880d681SAndroid Build Coastguard Worker           break;
548*9880d681SAndroid Build Coastguard Worker 
549*9880d681SAndroid Build Coastguard Worker         bool foundFeeder = false;
550*9880d681SAndroid Build Coastguard Worker         MachineBasicBlock::iterator feederPos = MII;
551*9880d681SAndroid Build Coastguard Worker         if (MI.getOperand(0).isReg() && MI.getOperand(0).isDef() &&
552*9880d681SAndroid Build Coastguard Worker             (MI.getOperand(0).getReg() == cmpReg1 ||
553*9880d681SAndroid Build Coastguard Worker              (isSecondOpReg &&
554*9880d681SAndroid Build Coastguard Worker               MI.getOperand(0).getReg() == (unsigned)cmpOp2))) {
555*9880d681SAndroid Build Coastguard Worker 
556*9880d681SAndroid Build Coastguard Worker           unsigned feederReg = MI.getOperand(0).getReg();
557*9880d681SAndroid Build Coastguard Worker 
558*9880d681SAndroid Build Coastguard Worker           // First try to see if we can get the feeder from the first operand
559*9880d681SAndroid Build Coastguard Worker           // of the compare. If we can not, and if secondOpReg is true
560*9880d681SAndroid Build Coastguard Worker           // (second operand of the compare is also register), try that one.
561*9880d681SAndroid Build Coastguard Worker           // TODO: Try to come up with some heuristic to figure out which
562*9880d681SAndroid Build Coastguard Worker           // feeder would benefit.
563*9880d681SAndroid Build Coastguard Worker 
564*9880d681SAndroid Build Coastguard Worker           if (feederReg == cmpReg1) {
565*9880d681SAndroid Build Coastguard Worker             if (!canBeFeederToNewValueJump(QII, QRI, MII, jmpPos, cmpPos, MF)) {
566*9880d681SAndroid Build Coastguard Worker               if (!isSecondOpReg)
567*9880d681SAndroid Build Coastguard Worker                 break;
568*9880d681SAndroid Build Coastguard Worker               else
569*9880d681SAndroid Build Coastguard Worker                 continue;
570*9880d681SAndroid Build Coastguard Worker             } else
571*9880d681SAndroid Build Coastguard Worker               foundFeeder = true;
572*9880d681SAndroid Build Coastguard Worker           }
573*9880d681SAndroid Build Coastguard Worker 
574*9880d681SAndroid Build Coastguard Worker           if (!foundFeeder &&
575*9880d681SAndroid Build Coastguard Worker                isSecondOpReg &&
576*9880d681SAndroid Build Coastguard Worker                feederReg == (unsigned) cmpOp2)
577*9880d681SAndroid Build Coastguard Worker             if (!canBeFeederToNewValueJump(QII, QRI, MII, jmpPos, cmpPos, MF))
578*9880d681SAndroid Build Coastguard Worker               break;
579*9880d681SAndroid Build Coastguard Worker 
580*9880d681SAndroid Build Coastguard Worker           if (isSecondOpReg) {
581*9880d681SAndroid Build Coastguard Worker             // In case of CMPLT, or CMPLTU, or EQ with the second register
582*9880d681SAndroid Build Coastguard Worker             // to newify, swap the operands.
583*9880d681SAndroid Build Coastguard Worker             if (cmpInstr->getOpcode() == Hexagon::C2_cmpeq &&
584*9880d681SAndroid Build Coastguard Worker                                      feederReg == (unsigned) cmpOp2) {
585*9880d681SAndroid Build Coastguard Worker               unsigned tmp = cmpReg1;
586*9880d681SAndroid Build Coastguard Worker               bool tmpIsKill = MO1IsKill;
587*9880d681SAndroid Build Coastguard Worker               cmpReg1 = cmpOp2;
588*9880d681SAndroid Build Coastguard Worker               MO1IsKill = MO2IsKill;
589*9880d681SAndroid Build Coastguard Worker               cmpOp2 = tmp;
590*9880d681SAndroid Build Coastguard Worker               MO2IsKill = tmpIsKill;
591*9880d681SAndroid Build Coastguard Worker             }
592*9880d681SAndroid Build Coastguard Worker 
593*9880d681SAndroid Build Coastguard Worker             // Now we have swapped the operands, all we need to check is,
594*9880d681SAndroid Build Coastguard Worker             // if the second operand (after swap) is the feeder.
595*9880d681SAndroid Build Coastguard Worker             // And if it is, make a note.
596*9880d681SAndroid Build Coastguard Worker             if (feederReg == (unsigned)cmpOp2)
597*9880d681SAndroid Build Coastguard Worker               isSecondOpNewified = true;
598*9880d681SAndroid Build Coastguard Worker           }
599*9880d681SAndroid Build Coastguard Worker 
600*9880d681SAndroid Build Coastguard Worker           // Now that we are moving feeder close the jump,
601*9880d681SAndroid Build Coastguard Worker           // make sure we are respecting the kill values of
602*9880d681SAndroid Build Coastguard Worker           // the operands of the feeder.
603*9880d681SAndroid Build Coastguard Worker 
604*9880d681SAndroid Build Coastguard Worker           bool updatedIsKill = false;
605*9880d681SAndroid Build Coastguard Worker           for (unsigned i = 0; i < MI.getNumOperands(); i++) {
606*9880d681SAndroid Build Coastguard Worker             MachineOperand &MO = MI.getOperand(i);
607*9880d681SAndroid Build Coastguard Worker             if (MO.isReg() && MO.isUse()) {
608*9880d681SAndroid Build Coastguard Worker               unsigned feederReg = MO.getReg();
609*9880d681SAndroid Build Coastguard Worker               for (MachineBasicBlock::iterator localII = feederPos,
610*9880d681SAndroid Build Coastguard Worker                    end = jmpPos; localII != end; localII++) {
611*9880d681SAndroid Build Coastguard Worker                 MachineInstr &localMI = *localII;
612*9880d681SAndroid Build Coastguard Worker                 for (unsigned j = 0; j < localMI.getNumOperands(); j++) {
613*9880d681SAndroid Build Coastguard Worker                   MachineOperand &localMO = localMI.getOperand(j);
614*9880d681SAndroid Build Coastguard Worker                   if (localMO.isReg() && localMO.isUse() &&
615*9880d681SAndroid Build Coastguard Worker                       localMO.isKill() && feederReg == localMO.getReg()) {
616*9880d681SAndroid Build Coastguard Worker                     // We found that there is kill of a use register
617*9880d681SAndroid Build Coastguard Worker                     // Set up a kill flag on the register
618*9880d681SAndroid Build Coastguard Worker                     localMO.setIsKill(false);
619*9880d681SAndroid Build Coastguard Worker                     MO.setIsKill();
620*9880d681SAndroid Build Coastguard Worker                     updatedIsKill = true;
621*9880d681SAndroid Build Coastguard Worker                     break;
622*9880d681SAndroid Build Coastguard Worker                   }
623*9880d681SAndroid Build Coastguard Worker                 }
624*9880d681SAndroid Build Coastguard Worker                 if (updatedIsKill) break;
625*9880d681SAndroid Build Coastguard Worker               }
626*9880d681SAndroid Build Coastguard Worker             }
627*9880d681SAndroid Build Coastguard Worker             if (updatedIsKill) break;
628*9880d681SAndroid Build Coastguard Worker           }
629*9880d681SAndroid Build Coastguard Worker 
630*9880d681SAndroid Build Coastguard Worker           MBB->splice(jmpPos, MI.getParent(), MI);
631*9880d681SAndroid Build Coastguard Worker           MBB->splice(jmpPos, MI.getParent(), cmpInstr);
632*9880d681SAndroid Build Coastguard Worker           DebugLoc dl = MI.getDebugLoc();
633*9880d681SAndroid Build Coastguard Worker           MachineInstr *NewMI;
634*9880d681SAndroid Build Coastguard Worker 
635*9880d681SAndroid Build Coastguard Worker           assert((isNewValueJumpCandidate(*cmpInstr)) &&
636*9880d681SAndroid Build Coastguard Worker                  "This compare is not a New Value Jump candidate.");
637*9880d681SAndroid Build Coastguard Worker           unsigned opc = getNewValueJumpOpcode(cmpInstr, cmpOp2,
638*9880d681SAndroid Build Coastguard Worker                                                isSecondOpNewified,
639*9880d681SAndroid Build Coastguard Worker                                                jmpTarget, MBPI);
640*9880d681SAndroid Build Coastguard Worker           if (invertPredicate)
641*9880d681SAndroid Build Coastguard Worker             opc = QII->getInvertedPredicatedOpcode(opc);
642*9880d681SAndroid Build Coastguard Worker 
643*9880d681SAndroid Build Coastguard Worker           if (isSecondOpReg)
644*9880d681SAndroid Build Coastguard Worker             NewMI = BuildMI(*MBB, jmpPos, dl,
645*9880d681SAndroid Build Coastguard Worker                                   QII->get(opc))
646*9880d681SAndroid Build Coastguard Worker                                     .addReg(cmpReg1, getKillRegState(MO1IsKill))
647*9880d681SAndroid Build Coastguard Worker                                     .addReg(cmpOp2, getKillRegState(MO2IsKill))
648*9880d681SAndroid Build Coastguard Worker                                     .addMBB(jmpTarget);
649*9880d681SAndroid Build Coastguard Worker 
650*9880d681SAndroid Build Coastguard Worker           else if ((cmpInstr->getOpcode() == Hexagon::C2_cmpeqi ||
651*9880d681SAndroid Build Coastguard Worker                     cmpInstr->getOpcode() == Hexagon::C2_cmpgti) &&
652*9880d681SAndroid Build Coastguard Worker                     cmpOp2 == -1 )
653*9880d681SAndroid Build Coastguard Worker             // Corresponding new-value compare jump instructions don't have the
654*9880d681SAndroid Build Coastguard Worker             // operand for -1 immediate value.
655*9880d681SAndroid Build Coastguard Worker             NewMI = BuildMI(*MBB, jmpPos, dl,
656*9880d681SAndroid Build Coastguard Worker                                   QII->get(opc))
657*9880d681SAndroid Build Coastguard Worker                                     .addReg(cmpReg1, getKillRegState(MO1IsKill))
658*9880d681SAndroid Build Coastguard Worker                                     .addMBB(jmpTarget);
659*9880d681SAndroid Build Coastguard Worker 
660*9880d681SAndroid Build Coastguard Worker           else
661*9880d681SAndroid Build Coastguard Worker             NewMI = BuildMI(*MBB, jmpPos, dl,
662*9880d681SAndroid Build Coastguard Worker                                   QII->get(opc))
663*9880d681SAndroid Build Coastguard Worker                                     .addReg(cmpReg1, getKillRegState(MO1IsKill))
664*9880d681SAndroid Build Coastguard Worker                                     .addImm(cmpOp2)
665*9880d681SAndroid Build Coastguard Worker                                     .addMBB(jmpTarget);
666*9880d681SAndroid Build Coastguard Worker 
667*9880d681SAndroid Build Coastguard Worker           assert(NewMI && "New Value Jump Instruction Not created!");
668*9880d681SAndroid Build Coastguard Worker           (void)NewMI;
669*9880d681SAndroid Build Coastguard Worker           if (cmpInstr->getOperand(0).isReg() &&
670*9880d681SAndroid Build Coastguard Worker               cmpInstr->getOperand(0).isKill())
671*9880d681SAndroid Build Coastguard Worker             cmpInstr->getOperand(0).setIsKill(false);
672*9880d681SAndroid Build Coastguard Worker           if (cmpInstr->getOperand(1).isReg() &&
673*9880d681SAndroid Build Coastguard Worker               cmpInstr->getOperand(1).isKill())
674*9880d681SAndroid Build Coastguard Worker             cmpInstr->getOperand(1).setIsKill(false);
675*9880d681SAndroid Build Coastguard Worker           cmpInstr->eraseFromParent();
676*9880d681SAndroid Build Coastguard Worker           jmpInstr->eraseFromParent();
677*9880d681SAndroid Build Coastguard Worker           ++nvjGenerated;
678*9880d681SAndroid Build Coastguard Worker           ++NumNVJGenerated;
679*9880d681SAndroid Build Coastguard Worker           break;
680*9880d681SAndroid Build Coastguard Worker         }
681*9880d681SAndroid Build Coastguard Worker       }
682*9880d681SAndroid Build Coastguard Worker     }
683*9880d681SAndroid Build Coastguard Worker   }
684*9880d681SAndroid Build Coastguard Worker 
685*9880d681SAndroid Build Coastguard Worker   return true;
686*9880d681SAndroid Build Coastguard Worker 
687*9880d681SAndroid Build Coastguard Worker }
688*9880d681SAndroid Build Coastguard Worker 
createHexagonNewValueJump()689*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createHexagonNewValueJump() {
690*9880d681SAndroid Build Coastguard Worker   return new HexagonNewValueJump();
691*9880d681SAndroid Build Coastguard Worker }
692