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