xref: /aosp_15_r20/external/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-------------- PPCMIPeephole.cpp - MI Peephole Cleanups -------------===//
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 pass performs peephole optimizations to clean up ugly code
11*9880d681SAndroid Build Coastguard Worker // sequences at the MachineInstruction layer.  It runs at the end of
12*9880d681SAndroid Build Coastguard Worker // the SSA phases, following VSX swap removal.  A pass of dead code
13*9880d681SAndroid Build Coastguard Worker // elimination follows this one for quick clean-up of any dead
14*9880d681SAndroid Build Coastguard Worker // instructions introduced here.  Although we could do this as callbacks
15*9880d681SAndroid Build Coastguard Worker // from the generic peephole pass, this would have a couple of bad
16*9880d681SAndroid Build Coastguard Worker // effects:  it might remove optimization opportunities for VSX swap
17*9880d681SAndroid Build Coastguard Worker // removal, and it would miss cleanups made possible following VSX
18*9880d681SAndroid Build Coastguard Worker // swap removal.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker #include "PPCInstrInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "PPC.h"
24*9880d681SAndroid Build Coastguard Worker #include "PPCInstrBuilder.h"
25*9880d681SAndroid Build Coastguard Worker #include "PPCTargetMachine.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker using namespace llvm;
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "ppc-mi-peepholes"
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker namespace llvm {
36*9880d681SAndroid Build Coastguard Worker   void initializePPCMIPeepholePass(PassRegistry&);
37*9880d681SAndroid Build Coastguard Worker }
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker namespace {
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker struct PPCMIPeephole : public MachineFunctionPass {
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   static char ID;
44*9880d681SAndroid Build Coastguard Worker   const PPCInstrInfo *TII;
45*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF;
46*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo *MRI;
47*9880d681SAndroid Build Coastguard Worker 
PPCMIPeephole__anonc1855df80111::PPCMIPeephole48*9880d681SAndroid Build Coastguard Worker   PPCMIPeephole() : MachineFunctionPass(ID) {
49*9880d681SAndroid Build Coastguard Worker     initializePPCMIPeepholePass(*PassRegistry::getPassRegistry());
50*9880d681SAndroid Build Coastguard Worker   }
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker private:
53*9880d681SAndroid Build Coastguard Worker   // Initialize class variables.
54*9880d681SAndroid Build Coastguard Worker   void initialize(MachineFunction &MFParm);
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   // Perform peepholes.
57*9880d681SAndroid Build Coastguard Worker   bool simplifyCode(void);
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   // Find the "true" register represented by SrcReg (following chains
60*9880d681SAndroid Build Coastguard Worker   // of copies and subreg_to_reg operations).
61*9880d681SAndroid Build Coastguard Worker   unsigned lookThruCopyLike(unsigned SrcReg);
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker public:
64*9880d681SAndroid Build Coastguard Worker   // Main entry point for this pass.
runOnMachineFunction__anonc1855df80111::PPCMIPeephole65*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override {
66*9880d681SAndroid Build Coastguard Worker     if (skipFunction(*MF.getFunction()))
67*9880d681SAndroid Build Coastguard Worker       return false;
68*9880d681SAndroid Build Coastguard Worker     initialize(MF);
69*9880d681SAndroid Build Coastguard Worker     return simplifyCode();
70*9880d681SAndroid Build Coastguard Worker   }
71*9880d681SAndroid Build Coastguard Worker };
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker // Initialize class variables.
initialize(MachineFunction & MFParm)74*9880d681SAndroid Build Coastguard Worker void PPCMIPeephole::initialize(MachineFunction &MFParm) {
75*9880d681SAndroid Build Coastguard Worker   MF = &MFParm;
76*9880d681SAndroid Build Coastguard Worker   MRI = &MF->getRegInfo();
77*9880d681SAndroid Build Coastguard Worker   TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo();
78*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "*** PowerPC MI peephole pass ***\n\n");
79*9880d681SAndroid Build Coastguard Worker   DEBUG(MF->dump());
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker // Perform peephole optimizations.
simplifyCode(void)83*9880d681SAndroid Build Coastguard Worker bool PPCMIPeephole::simplifyCode(void) {
84*9880d681SAndroid Build Coastguard Worker   bool Simplified = false;
85*9880d681SAndroid Build Coastguard Worker   MachineInstr* ToErase = nullptr;
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock &MBB : *MF) {
88*9880d681SAndroid Build Coastguard Worker     for (MachineInstr &MI : MBB) {
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker       // If the previous instruction was marked for elimination,
91*9880d681SAndroid Build Coastguard Worker       // remove it now.
92*9880d681SAndroid Build Coastguard Worker       if (ToErase) {
93*9880d681SAndroid Build Coastguard Worker         ToErase->eraseFromParent();
94*9880d681SAndroid Build Coastguard Worker         ToErase = nullptr;
95*9880d681SAndroid Build Coastguard Worker       }
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker       // Ignore debug instructions.
98*9880d681SAndroid Build Coastguard Worker       if (MI.isDebugValue())
99*9880d681SAndroid Build Coastguard Worker         continue;
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker       // Per-opcode peepholes.
102*9880d681SAndroid Build Coastguard Worker       switch (MI.getOpcode()) {
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker       default:
105*9880d681SAndroid Build Coastguard Worker         break;
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker       case PPC::XXPERMDI: {
108*9880d681SAndroid Build Coastguard Worker         // Perform simplifications of 2x64 vector swaps and splats.
109*9880d681SAndroid Build Coastguard Worker         // A swap is identified by an immediate value of 2, and a splat
110*9880d681SAndroid Build Coastguard Worker         // is identified by an immediate value of 0 or 3.
111*9880d681SAndroid Build Coastguard Worker         int Immed = MI.getOperand(3).getImm();
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker         if (Immed != 1) {
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker           // For each of these simplifications, we need the two source
116*9880d681SAndroid Build Coastguard Worker           // regs to match.  Unfortunately, MachineCSE ignores COPY and
117*9880d681SAndroid Build Coastguard Worker           // SUBREG_TO_REG, so for example we can see
118*9880d681SAndroid Build Coastguard Worker           //   XXPERMDI t, SUBREG_TO_REG(s), SUBREG_TO_REG(s), immed.
119*9880d681SAndroid Build Coastguard Worker           // We have to look through chains of COPY and SUBREG_TO_REG
120*9880d681SAndroid Build Coastguard Worker           // to find the real source values for comparison.
121*9880d681SAndroid Build Coastguard Worker           unsigned TrueReg1 = lookThruCopyLike(MI.getOperand(1).getReg());
122*9880d681SAndroid Build Coastguard Worker           unsigned TrueReg2 = lookThruCopyLike(MI.getOperand(2).getReg());
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker           if (TrueReg1 == TrueReg2
125*9880d681SAndroid Build Coastguard Worker               && TargetRegisterInfo::isVirtualRegister(TrueReg1)) {
126*9880d681SAndroid Build Coastguard Worker             MachineInstr *DefMI = MRI->getVRegDef(TrueReg1);
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker             // If this is a splat or a swap fed by another splat, we
129*9880d681SAndroid Build Coastguard Worker             // can replace it with a copy.
130*9880d681SAndroid Build Coastguard Worker             if (DefMI && DefMI->getOpcode() == PPC::XXPERMDI) {
131*9880d681SAndroid Build Coastguard Worker               unsigned FeedImmed = DefMI->getOperand(3).getImm();
132*9880d681SAndroid Build Coastguard Worker               unsigned FeedReg1
133*9880d681SAndroid Build Coastguard Worker                 = lookThruCopyLike(DefMI->getOperand(1).getReg());
134*9880d681SAndroid Build Coastguard Worker               unsigned FeedReg2
135*9880d681SAndroid Build Coastguard Worker                 = lookThruCopyLike(DefMI->getOperand(2).getReg());
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker               if ((FeedImmed == 0 || FeedImmed == 3) && FeedReg1 == FeedReg2) {
138*9880d681SAndroid Build Coastguard Worker                 DEBUG(dbgs()
139*9880d681SAndroid Build Coastguard Worker                       << "Optimizing splat/swap or splat/splat "
140*9880d681SAndroid Build Coastguard Worker                       "to splat/copy: ");
141*9880d681SAndroid Build Coastguard Worker                 DEBUG(MI.dump());
142*9880d681SAndroid Build Coastguard Worker                 BuildMI(MBB, &MI, MI.getDebugLoc(),
143*9880d681SAndroid Build Coastguard Worker                         TII->get(PPC::COPY), MI.getOperand(0).getReg())
144*9880d681SAndroid Build Coastguard Worker                   .addOperand(MI.getOperand(1));
145*9880d681SAndroid Build Coastguard Worker                 ToErase = &MI;
146*9880d681SAndroid Build Coastguard Worker                 Simplified = true;
147*9880d681SAndroid Build Coastguard Worker               }
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker               // If this is a splat fed by a swap, we can simplify modify
150*9880d681SAndroid Build Coastguard Worker               // the splat to splat the other value from the swap's input
151*9880d681SAndroid Build Coastguard Worker               // parameter.
152*9880d681SAndroid Build Coastguard Worker               else if ((Immed == 0 || Immed == 3)
153*9880d681SAndroid Build Coastguard Worker                        && FeedImmed == 2 && FeedReg1 == FeedReg2) {
154*9880d681SAndroid Build Coastguard Worker                 DEBUG(dbgs() << "Optimizing swap/splat => splat: ");
155*9880d681SAndroid Build Coastguard Worker                 DEBUG(MI.dump());
156*9880d681SAndroid Build Coastguard Worker                 MI.getOperand(1).setReg(DefMI->getOperand(1).getReg());
157*9880d681SAndroid Build Coastguard Worker                 MI.getOperand(2).setReg(DefMI->getOperand(2).getReg());
158*9880d681SAndroid Build Coastguard Worker                 MI.getOperand(3).setImm(3 - Immed);
159*9880d681SAndroid Build Coastguard Worker                 Simplified = true;
160*9880d681SAndroid Build Coastguard Worker               }
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker               // If this is a swap fed by a swap, we can replace it
163*9880d681SAndroid Build Coastguard Worker               // with a copy from the first swap's input.
164*9880d681SAndroid Build Coastguard Worker               else if (Immed == 2 && FeedImmed == 2 && FeedReg1 == FeedReg2) {
165*9880d681SAndroid Build Coastguard Worker                 DEBUG(dbgs() << "Optimizing swap/swap => copy: ");
166*9880d681SAndroid Build Coastguard Worker                 DEBUG(MI.dump());
167*9880d681SAndroid Build Coastguard Worker                 BuildMI(MBB, &MI, MI.getDebugLoc(),
168*9880d681SAndroid Build Coastguard Worker                         TII->get(PPC::COPY), MI.getOperand(0).getReg())
169*9880d681SAndroid Build Coastguard Worker                   .addOperand(DefMI->getOperand(1));
170*9880d681SAndroid Build Coastguard Worker                 ToErase = &MI;
171*9880d681SAndroid Build Coastguard Worker                 Simplified = true;
172*9880d681SAndroid Build Coastguard Worker               }
173*9880d681SAndroid Build Coastguard Worker             }
174*9880d681SAndroid Build Coastguard Worker           }
175*9880d681SAndroid Build Coastguard Worker         }
176*9880d681SAndroid Build Coastguard Worker         break;
177*9880d681SAndroid Build Coastguard Worker       }
178*9880d681SAndroid Build Coastguard Worker       }
179*9880d681SAndroid Build Coastguard Worker     }
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker     // If the last instruction was marked for elimination,
182*9880d681SAndroid Build Coastguard Worker     // remove it now.
183*9880d681SAndroid Build Coastguard Worker     if (ToErase) {
184*9880d681SAndroid Build Coastguard Worker       ToErase->eraseFromParent();
185*9880d681SAndroid Build Coastguard Worker       ToErase = nullptr;
186*9880d681SAndroid Build Coastguard Worker     }
187*9880d681SAndroid Build Coastguard Worker   }
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker   return Simplified;
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker // This is used to find the "true" source register for an
193*9880d681SAndroid Build Coastguard Worker // XXPERMDI instruction, since MachineCSE does not handle the
194*9880d681SAndroid Build Coastguard Worker // "copy-like" operations (Copy and SubregToReg).  Returns
195*9880d681SAndroid Build Coastguard Worker // the original SrcReg unless it is the target of a copy-like
196*9880d681SAndroid Build Coastguard Worker // operation, in which case we chain backwards through all
197*9880d681SAndroid Build Coastguard Worker // such operations to the ultimate source register.  If a
198*9880d681SAndroid Build Coastguard Worker // physical register is encountered, we stop the search.
lookThruCopyLike(unsigned SrcReg)199*9880d681SAndroid Build Coastguard Worker unsigned PPCMIPeephole::lookThruCopyLike(unsigned SrcReg) {
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker   while (true) {
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = MRI->getVRegDef(SrcReg);
204*9880d681SAndroid Build Coastguard Worker     if (!MI->isCopyLike())
205*9880d681SAndroid Build Coastguard Worker       return SrcReg;
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker     unsigned CopySrcReg;
208*9880d681SAndroid Build Coastguard Worker     if (MI->isCopy())
209*9880d681SAndroid Build Coastguard Worker       CopySrcReg = MI->getOperand(1).getReg();
210*9880d681SAndroid Build Coastguard Worker     else {
211*9880d681SAndroid Build Coastguard Worker       assert(MI->isSubregToReg() && "bad opcode for lookThruCopyLike");
212*9880d681SAndroid Build Coastguard Worker       CopySrcReg = MI->getOperand(2).getReg();
213*9880d681SAndroid Build Coastguard Worker     }
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker     if (!TargetRegisterInfo::isVirtualRegister(CopySrcReg))
216*9880d681SAndroid Build Coastguard Worker       return CopySrcReg;
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker     SrcReg = CopySrcReg;
219*9880d681SAndroid Build Coastguard Worker   }
220*9880d681SAndroid Build Coastguard Worker }
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker } // end default namespace
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(PPCMIPeephole, DEBUG_TYPE,
225*9880d681SAndroid Build Coastguard Worker                       "PowerPC MI Peephole Optimization", false, false)
226*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(PPCMIPeephole, DEBUG_TYPE,
227*9880d681SAndroid Build Coastguard Worker                     "PowerPC MI Peephole Optimization", false, false)
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker char PPCMIPeephole::ID = 0;
230*9880d681SAndroid Build Coastguard Worker FunctionPass*
createPPCMIPeepholePass()231*9880d681SAndroid Build Coastguard Worker llvm::createPPCMIPeepholePass() { return new PPCMIPeephole(); }
232*9880d681SAndroid Build Coastguard Worker 
233