llvm.org GIT mirror llvm / fe61fb1
Add a new pass on machine instructions to optimize away PHI cycles that reduce down to a single value. InstCombine already does this transformation but DAG legalization may introduce new opportunities. This has turned out to be important for ARM where 64-bit values are split up during type legalization: InstCombine is not able to remove the PHI cycles on the 64-bit values but the separate 32-bit values can be optimized. I measured the compile time impact of this (running llc on 176.gcc) and it was not significant. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95951 91177308-0d34-0410-b5e6-96231b3b80d8 Bob Wilson 10 years ago
5 changed file(s) with 181 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
173173 /// optimization by increasing uses of extended values.
174174 FunctionPass *createOptimizeExtsPass();
175175
176 /// createOptimizePHIsPass - This pass optimizes machine instruction PHIs
177 /// to take advantage of opportunities created during DAG legalization.
178 FunctionPass *createOptimizePHIsPass();
179
176180 /// createStackSlotColoringPass - This pass performs stack slot coloring.
177181 FunctionPass *createStackSlotColoringPass(bool);
178182
3838 ObjectCodeEmitter.cpp
3939 OcamlGC.cpp
4040 OptimizeExts.cpp
41 OptimizePHIs.cpp
4142 PHIElimination.cpp
4243 Passes.cpp
4344 PostRASchedulerList.cpp
298298
299299 if (OptLevel != CodeGenOpt::None) {
300300 PM.add(createOptimizeExtsPass());
301 PM.add(createOptimizePHIsPass());
301302 if (!DisableMachineLICM)
302303 PM.add(createMachineLICMPass());
303304 if (!DisableMachineSink)
0 //===-- OptimizePHIs.cpp - Optimize machine instruction PHIs --------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass optimizes machine instruction PHIs to take advantage of
10 // opportunities created during DAG legalization.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "phi-opt"
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/CodeGen/MachineFunctionPass.h"
17 #include "llvm/CodeGen/MachineInstr.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/Target/TargetInstrInfo.h"
20 #include "llvm/Function.h"
21 #include "llvm/ADT/SmallSet.h"
22 #include "llvm/ADT/Statistic.h"
23 using namespace llvm;
24
25 STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
26
27 namespace {
28 class OptimizePHIs : public MachineFunctionPass {
29 MachineRegisterInfo *MRI;
30 const TargetInstrInfo *TII;
31
32 public:
33 static char ID; // Pass identification
34 OptimizePHIs() : MachineFunctionPass(&ID) {}
35
36 virtual bool runOnMachineFunction(MachineFunction &MF);
37
38 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
39 AU.setPreservesCFG();
40 MachineFunctionPass::getAnalysisUsage(AU);
41 }
42
43 private:
44 bool IsSingleValuePHICycle(const MachineInstr *MI, unsigned &SingleValReg,
45 SmallSet &RegsInCycle);
46 bool ReplacePHICycles(MachineBasicBlock &MBB);
47 };
48 }
49
50 char OptimizePHIs::ID = 0;
51 static RegisterPass
52 X("opt-phis", "Optimize machine instruction PHIs");
53
54 FunctionPass *llvm::createOptimizePHIsPass() { return new OptimizePHIs(); }
55
56 bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
57 MRI = &Fn.getRegInfo();
58 TII = Fn.getTarget().getInstrInfo();
59
60 // Find PHI cycles that can be replaced by a single value. InstCombine
61 // does this, but DAG legalization may introduce new opportunities, e.g.,
62 // when i64 values are split up for 32-bit targets.
63 bool Changed = false;
64 for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
65 Changed |= ReplacePHICycles(*I);
66
67 return Changed;
68 }
69
70 /// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
71 /// are copies of SingleValReg, possibly via copies through other PHIs. If
72 /// SingleValReg is zero on entry, it is set to the register with the single
73 /// non-copy value. RegsInCycle is a set used to keep track of the PHIs that
74 /// have been scanned.
75 bool OptimizePHIs::IsSingleValuePHICycle(const MachineInstr *MI,
76 unsigned &SingleValReg,
77 SmallSet &RegsInCycle) {
78 assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
79 unsigned DstReg = MI->getOperand(0).getReg();
80
81 // See if we already saw this register.
82 if (!RegsInCycle.insert(DstReg))
83 return true;
84
85 // Don't scan crazily complex things.
86 if (RegsInCycle.size() == 16)
87 return false;
88
89 // Scan the PHI operands.
90 for (unsigned i = 1; i != MI->getNumOperands(); i += 2) {
91 unsigned SrcReg = MI->getOperand(i).getReg();
92 if (SrcReg == DstReg)
93 continue;
94 const MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
95
96 // Skip over register-to-register moves.
97 unsigned MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx;
98 if (SrcMI &&
99 TII->isMoveInstr(*SrcMI, MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx) &&
100 SrcSubIdx == 0 && DstSubIdx == 0 &&
101 TargetRegisterInfo::isVirtualRegister(MvSrcReg))
102 SrcMI = MRI->getVRegDef(MvSrcReg);
103 if (!SrcMI)
104 return false;
105
106 if (SrcMI->isPHI()) {
107 if (!IsSingleValuePHICycle(SrcMI, SingleValReg, RegsInCycle))
108 return false;
109 } else {
110 // Fail if there is more than one non-phi/non-move register.
111 if (SingleValReg != 0)
112 return false;
113 SingleValReg = SrcReg;
114 }
115 }
116 return true;
117 }
118
119 /// ReplacePHICycles - Find PHI cycles that can be replaced by a single
120 /// value and remove them.
121 bool OptimizePHIs::ReplacePHICycles(MachineBasicBlock &MBB) {
122 bool Changed = false;
123 for (MachineBasicBlock::iterator
124 MII = MBB.begin(), E = MBB.end(); MII != E; ) {
125 MachineInstr *MI = &*MII++;
126 if (!MI->isPHI())
127 break;
128
129 unsigned SingleValReg = 0;
130 SmallSet RegsInCycle;
131 if (IsSingleValuePHICycle(MI, SingleValReg, RegsInCycle) &&
132 SingleValReg != 0) {
133 MRI->replaceRegWith(MI->getOperand(0).getReg(), SingleValReg);
134 MI->eraseFromParent();
135 ++NumPHICycles;
136 Changed = true;
137 }
138 }
139 return Changed;
140 }
0 ; RUN: llc < %s -mtriple=thumbv7-apple-darwin | FileCheck %s
1 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32"
2
3 define arm_apcscc i32 @test(i32 %n) nounwind {
4 ; CHECK: test:
5 ; CHECK-NOT: mov
6 ; CHECK: return
7 entry:
8 %0 = icmp eq i32 %n, 1 ; [#uses=1]
9 br i1 %0, label %return, label %bb.nph
10
11 bb.nph: ; preds = %entry
12 %tmp = add i32 %n, -1 ; [#uses=1]
13 br label %bb
14
15 bb: ; preds = %bb.nph, %bb
16 %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=1]
17 %u.05 = phi i64 [ undef, %bb.nph ], [ %ins, %bb ] ; [#uses=1]
18 %1 = tail call arm_apcscc i32 @f() nounwind ; [#uses=1]
19 %tmp4 = zext i32 %1 to i64 ; [#uses=1]
20 %mask = and i64 %u.05, -4294967296 ; [#uses=1]
21 %ins = or i64 %tmp4, %mask ; [#uses=2]
22 tail call arm_apcscc void @g(i64 %ins) nounwind
23 %indvar.next = add i32 %indvar, 1 ; [#uses=2]
24 %exitcond = icmp eq i32 %indvar.next, %tmp ; [#uses=1]
25 br i1 %exitcond, label %return, label %bb
26
27 return: ; preds = %bb, %entry
28 ret i32 undef
29 }
30
31 declare arm_apcscc i32 @f()
32
33 declare arm_apcscc void @g(i64)