121
|
1 //===- ShrinkWrap.cpp - Compute safe point for prolog/epilog insertion ----===//
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
2 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3 // The LLVM Compiler Infrastructure
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
4 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5 // This file is distributed under the University of Illinois Open Source
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 // License. See LICENSE.TXT for details.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 //===----------------------------------------------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10 // This pass looks for safe point where the prologue and epilogue can be
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 // inserted.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 // The safe point for the prologue (resp. epilogue) is called Save
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 // (resp. Restore).
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14 // A point is safe for prologue (resp. epilogue) if and only if
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15 // it 1) dominates (resp. post-dominates) all the frame related operations and
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16 // between 2) two executions of the Save (resp. Restore) point there is an
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17 // execution of the Restore (resp. Save) point.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19 // For instance, the following points are safe:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
20 // for (int i = 0; i < 10; ++i) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21 // Save
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
22 // ...
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
23 // Restore
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
24 // }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
25 // Indeed, the execution looks like Save -> Restore -> Save -> Restore ...
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
26 // And the following points are not:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
27 // for (int i = 0; i < 10; ++i) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
28 // Save
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
29 // ...
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
30 // }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
31 // for (int i = 0; i < 10; ++i) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
32 // ...
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
33 // Restore
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
34 // }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
35 // Indeed, the execution looks like Save -> Save -> ... -> Restore -> Restore.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
36 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
37 // This pass also ensures that the safe points are 3) cheaper than the regular
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38 // entry and exits blocks.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
39 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
40 // Property #1 is ensured via the use of MachineDominatorTree and
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
41 // MachinePostDominatorTree.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
42 // Property #2 is ensured via property #1 and MachineLoopInfo, i.e., both
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
43 // points must be in the same loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
44 // Property #3 is ensured via the MachineBlockFrequencyInfo.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
45 //
|
100
|
46 // If this pass found points matching all these properties, then
|
|
47 // MachineFrameInfo is updated with this information.
|
121
|
48 //
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
49 //===----------------------------------------------------------------------===//
|
121
|
50
|
100
|
51 #include "llvm/ADT/BitVector.h"
|
|
52 #include "llvm/ADT/PostOrderIterator.h"
|
|
53 #include "llvm/ADT/SetVector.h"
|
121
|
54 #include "llvm/ADT/SmallVector.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
55 #include "llvm/ADT/Statistic.h"
|
121
|
56 #include "llvm/CodeGen/MachineBasicBlock.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
57 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
58 #include "llvm/CodeGen/MachineDominators.h"
|
121
|
59 #include "llvm/CodeGen/MachineFunction.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
60 #include "llvm/CodeGen/MachineFunctionPass.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
61 #include "llvm/CodeGen/MachineFrameInfo.h"
|
121
|
62 #include "llvm/CodeGen/MachineInstr.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
63 #include "llvm/CodeGen/MachineLoopInfo.h"
|
121
|
64 #include "llvm/CodeGen/MachineOperand.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
65 #include "llvm/CodeGen/MachinePostDominators.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
66 #include "llvm/CodeGen/RegisterClassInfo.h"
|
100
|
67 #include "llvm/CodeGen/RegisterScavenging.h"
|
121
|
68 #include "llvm/IR/Attributes.h"
|
|
69 #include "llvm/IR/Function.h"
|
100
|
70 #include "llvm/MC/MCAsmInfo.h"
|
121
|
71 #include "llvm/Pass.h"
|
|
72 #include "llvm/Support/CommandLine.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
73 #include "llvm/Support/Debug.h"
|
121
|
74 #include "llvm/Support/ErrorHandling.h"
|
|
75 #include "llvm/Support/raw_ostream.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
76 #include "llvm/Target/TargetFrameLowering.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
77 #include "llvm/Target/TargetInstrInfo.h"
|
100
|
78 #include "llvm/Target/TargetMachine.h"
|
121
|
79 #include "llvm/Target/TargetRegisterInfo.h"
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
80 #include "llvm/Target/TargetSubtargetInfo.h"
|
121
|
81 #include <cassert>
|
|
82 #include <cstdint>
|
|
83 #include <memory>
|
|
84
|
|
85 using namespace llvm;
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
86
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
87 #define DEBUG_TYPE "shrink-wrap"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
88
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89 STATISTIC(NumFunc, "Number of functions");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
90 STATISTIC(NumCandidates, "Number of shrink-wrapping candidates");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
91 STATISTIC(NumCandidatesDropped,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
92 "Number of shrink-wrapping candidates dropped because of frequency");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
93
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
94 static cl::opt<cl::boolOrDefault>
|
121
|
95 EnableShrinkWrapOpt("enable-shrink-wrap", cl::Hidden,
|
|
96 cl::desc("enable the shrink-wrapping pass"));
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
97
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
98 namespace {
|
121
|
99
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
100 /// \brief Class to determine where the safe point to insert the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
101 /// prologue and epilogue are.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
102 /// Unlike the paper from Fred C. Chow, PLDI'88, that introduces the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
103 /// shrink-wrapping term for prologue/epilogue placement, this pass
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
104 /// does not rely on expensive data-flow analysis. Instead we use the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
105 /// dominance properties and loop information to decide which point
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
106 /// are safe for such insertion.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
107 class ShrinkWrap : public MachineFunctionPass {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
108 /// Hold callee-saved information.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
109 RegisterClassInfo RCI;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
110 MachineDominatorTree *MDT;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
111 MachinePostDominatorTree *MPDT;
|
121
|
112
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
113 /// Current safe point found for the prologue.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
114 /// The prologue will be inserted before the first instruction
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
115 /// in this basic block.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
116 MachineBasicBlock *Save;
|
121
|
117
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
118 /// Current safe point found for the epilogue.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
119 /// The epilogue will be inserted before the first terminator instruction
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
120 /// in this basic block.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
121 MachineBasicBlock *Restore;
|
121
|
122
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
123 /// Hold the information of the basic block frequency.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
124 /// Use to check the profitability of the new points.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
125 MachineBlockFrequencyInfo *MBFI;
|
121
|
126
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
127 /// Hold the loop information. Used to determine if Save and Restore
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
128 /// are in the same loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
129 MachineLoopInfo *MLI;
|
121
|
130
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
131 /// Frequency of the Entry block.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
132 uint64_t EntryFreq;
|
121
|
133
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
134 /// Current opcode for frame setup.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
135 unsigned FrameSetupOpcode;
|
121
|
136
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
137 /// Current opcode for frame destroy.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
138 unsigned FrameDestroyOpcode;
|
121
|
139
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
140 /// Entry block.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
141 const MachineBasicBlock *Entry;
|
121
|
142
|
|
143 using SetOfRegs = SmallSetVector<unsigned, 16>;
|
|
144
|
100
|
145 /// Registers that need to be saved for the current function.
|
|
146 mutable SetOfRegs CurrentCSRs;
|
121
|
147
|
100
|
148 /// Current MachineFunction.
|
|
149 MachineFunction *MachineFunc;
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
150
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
151 /// \brief Check if \p MI uses or defines a callee-saved register or
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
152 /// a frame index. If this is the case, this means \p MI must happen
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
153 /// after Save and before Restore.
|
100
|
154 bool useOrDefCSROrFI(const MachineInstr &MI, RegScavenger *RS) const;
|
|
155
|
|
156 const SetOfRegs &getCurrentCSRs(RegScavenger *RS) const {
|
|
157 if (CurrentCSRs.empty()) {
|
|
158 BitVector SavedRegs;
|
|
159 const TargetFrameLowering *TFI =
|
|
160 MachineFunc->getSubtarget().getFrameLowering();
|
|
161
|
|
162 TFI->determineCalleeSaves(*MachineFunc, SavedRegs, RS);
|
|
163
|
|
164 for (int Reg = SavedRegs.find_first(); Reg != -1;
|
|
165 Reg = SavedRegs.find_next(Reg))
|
|
166 CurrentCSRs.insert((unsigned)Reg);
|
|
167 }
|
|
168 return CurrentCSRs;
|
|
169 }
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
170
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
171 /// \brief Update the Save and Restore points such that \p MBB is in
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
172 /// the region that is dominated by Save and post-dominated by Restore
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
173 /// and Save and Restore still match the safe point definition.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
174 /// Such point may not exist and Save and/or Restore may be null after
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
175 /// this call.
|
100
|
176 void updateSaveRestorePoints(MachineBasicBlock &MBB, RegScavenger *RS);
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
177
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
178 /// \brief Initialize the pass for \p MF.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
179 void init(MachineFunction &MF) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
180 RCI.runOnMachineFunction(MF);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
181 MDT = &getAnalysis<MachineDominatorTree>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
182 MPDT = &getAnalysis<MachinePostDominatorTree>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
183 Save = nullptr;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
184 Restore = nullptr;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
185 MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
186 MLI = &getAnalysis<MachineLoopInfo>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
187 EntryFreq = MBFI->getEntryFreq();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
188 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
189 FrameSetupOpcode = TII.getCallFrameSetupOpcode();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
190 FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
191 Entry = &MF.front();
|
100
|
192 CurrentCSRs.clear();
|
|
193 MachineFunc = &MF;
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
194
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
195 ++NumFunc;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
196 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
197
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
198 /// Check whether or not Save and Restore points are still interesting for
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
199 /// shrink-wrapping.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
200 bool ArePointsInteresting() const { return Save != Entry && Save && Restore; }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
201
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
202 /// \brief Check if shrink wrapping is enabled for this target and function.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
203 static bool isShrinkWrapEnabled(const MachineFunction &MF);
|
100
|
204
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
205 public:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
206 static char ID;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
207
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
208 ShrinkWrap() : MachineFunctionPass(ID) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
209 initializeShrinkWrapPass(*PassRegistry::getPassRegistry());
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
210 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
211
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
212 void getAnalysisUsage(AnalysisUsage &AU) const override {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
213 AU.setPreservesAll();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
214 AU.addRequired<MachineBlockFrequencyInfo>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
215 AU.addRequired<MachineDominatorTree>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
216 AU.addRequired<MachinePostDominatorTree>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
217 AU.addRequired<MachineLoopInfo>();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
218 MachineFunctionPass::getAnalysisUsage(AU);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
219 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
220
|
120
|
221 StringRef getPassName() const override { return "Shrink Wrapping analysis"; }
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
222
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
223 /// \brief Perform the shrink-wrapping analysis and update
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
224 /// the MachineFrameInfo attached to \p MF with the results.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
225 bool runOnMachineFunction(MachineFunction &MF) override;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
226 };
|
121
|
227
|
|
228 } // end anonymous namespace
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
229
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
230 char ShrinkWrap::ID = 0;
|
121
|
231
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
232 char &llvm::ShrinkWrapID = ShrinkWrap::ID;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
233
|
121
|
234 INITIALIZE_PASS_BEGIN(ShrinkWrap, DEBUG_TYPE, "Shrink Wrap Pass", false, false)
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
235 INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
236 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
237 INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
238 INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
|
121
|
239 INITIALIZE_PASS_END(ShrinkWrap, DEBUG_TYPE, "Shrink Wrap Pass", false, false)
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
240
|
100
|
241 bool ShrinkWrap::useOrDefCSROrFI(const MachineInstr &MI,
|
|
242 RegScavenger *RS) const {
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
243 if (MI.getOpcode() == FrameSetupOpcode ||
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
244 MI.getOpcode() == FrameDestroyOpcode) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
245 DEBUG(dbgs() << "Frame instruction: " << MI << '\n');
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
246 return true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
247 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
248 for (const MachineOperand &MO : MI.operands()) {
|
100
|
249 bool UseOrDefCSR = false;
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
250 if (MO.isReg()) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
251 unsigned PhysReg = MO.getReg();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
252 if (!PhysReg)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
253 continue;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
254 assert(TargetRegisterInfo::isPhysicalRegister(PhysReg) &&
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
255 "Unallocated register?!");
|
100
|
256 UseOrDefCSR = RCI.getLastCalleeSavedAlias(PhysReg);
|
|
257 } else if (MO.isRegMask()) {
|
|
258 // Check if this regmask clobbers any of the CSRs.
|
|
259 for (unsigned Reg : getCurrentCSRs(RS)) {
|
|
260 if (MO.clobbersPhysReg(Reg)) {
|
|
261 UseOrDefCSR = true;
|
|
262 break;
|
|
263 }
|
|
264 }
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
265 }
|
100
|
266 if (UseOrDefCSR || MO.isFI()) {
|
|
267 DEBUG(dbgs() << "Use or define CSR(" << UseOrDefCSR << ") or FI("
|
|
268 << MO.isFI() << "): " << MI << '\n');
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
269 return true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
270 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
271 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
272 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
273 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
274
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
275 /// \brief Helper function to find the immediate (post) dominator.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
276 template <typename ListOfBBs, typename DominanceAnalysis>
|
120
|
277 static MachineBasicBlock *FindIDom(MachineBasicBlock &Block, ListOfBBs BBs,
|
|
278 DominanceAnalysis &Dom) {
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
279 MachineBasicBlock *IDom = &Block;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
280 for (MachineBasicBlock *BB : BBs) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
281 IDom = Dom.findNearestCommonDominator(IDom, BB);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
282 if (!IDom)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
283 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
284 }
|
100
|
285 if (IDom == &Block)
|
|
286 return nullptr;
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
287 return IDom;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
288 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
289
|
100
|
290 void ShrinkWrap::updateSaveRestorePoints(MachineBasicBlock &MBB,
|
|
291 RegScavenger *RS) {
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
292 // Get rid of the easy cases first.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
293 if (!Save)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
294 Save = &MBB;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
295 else
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
296 Save = MDT->findNearestCommonDominator(Save, &MBB);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
297
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
298 if (!Save) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
299 DEBUG(dbgs() << "Found a block that is not reachable from Entry\n");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
300 return;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
301 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
302
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
303 if (!Restore)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
304 Restore = &MBB;
|
121
|
305 else if (MPDT->getNode(&MBB)) // If the block is not in the post dom tree, it
|
|
306 // means the block never returns. If that's the
|
|
307 // case, we don't want to call
|
|
308 // `findNearestCommonDominator`, which will
|
|
309 // return `Restore`.
|
|
310 Restore = MPDT->findNearestCommonDominator(Restore, &MBB);
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
311 else
|
121
|
312 Restore = nullptr; // Abort, we can't find a restore point in this case.
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
313
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
314 // Make sure we would be able to insert the restore code before the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
315 // terminator.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
316 if (Restore == &MBB) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
317 for (const MachineInstr &Terminator : MBB.terminators()) {
|
100
|
318 if (!useOrDefCSROrFI(Terminator, RS))
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
319 continue;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
320 // One of the terminator needs to happen before the restore point.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
321 if (MBB.succ_empty()) {
|
121
|
322 Restore = nullptr; // Abort, we can't find a restore point in this case.
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
323 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
324 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
325 // Look for a restore point that post-dominates all the successors.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
326 // The immediate post-dominator is what we are looking for.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
327 Restore = FindIDom<>(*Restore, Restore->successors(), *MPDT);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
328 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
329 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
330 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
331
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
332 if (!Restore) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
333 DEBUG(dbgs() << "Restore point needs to be spanned on several blocks\n");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
334 return;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
335 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
336
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
337 // Make sure Save and Restore are suitable for shrink-wrapping:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
338 // 1. all path from Save needs to lead to Restore before exiting.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
339 // 2. all path to Restore needs to go through Save from Entry.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
340 // We achieve that by making sure that:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
341 // A. Save dominates Restore.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
342 // B. Restore post-dominates Save.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
343 // C. Save and Restore are in the same loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
344 bool SaveDominatesRestore = false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
345 bool RestorePostDominatesSave = false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
346 while (Save && Restore &&
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
347 (!(SaveDominatesRestore = MDT->dominates(Save, Restore)) ||
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
348 !(RestorePostDominatesSave = MPDT->dominates(Restore, Save)) ||
|
100
|
349 // Post-dominance is not enough in loops to ensure that all uses/defs
|
|
350 // are after the prologue and before the epilogue at runtime.
|
|
351 // E.g.,
|
|
352 // while(1) {
|
|
353 // Save
|
|
354 // Restore
|
|
355 // if (...)
|
|
356 // break;
|
|
357 // use/def CSRs
|
|
358 // }
|
|
359 // All the uses/defs of CSRs are dominated by Save and post-dominated
|
|
360 // by Restore. However, the CSRs uses are still reachable after
|
|
361 // Restore and before Save are executed.
|
|
362 //
|
|
363 // For now, just push the restore/save points outside of loops.
|
|
364 // FIXME: Refine the criteria to still find interesting cases
|
|
365 // for loops.
|
|
366 MLI->getLoopFor(Save) || MLI->getLoopFor(Restore))) {
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
367 // Fix (A).
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
368 if (!SaveDominatesRestore) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
369 Save = MDT->findNearestCommonDominator(Save, Restore);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
370 continue;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
371 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
372 // Fix (B).
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
373 if (!RestorePostDominatesSave)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
374 Restore = MPDT->findNearestCommonDominator(Restore, Save);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
375
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
376 // Fix (C).
|
100
|
377 if (Save && Restore &&
|
|
378 (MLI->getLoopFor(Save) || MLI->getLoopFor(Restore))) {
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
379 if (MLI->getLoopDepth(Save) > MLI->getLoopDepth(Restore)) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
380 // Push Save outside of this loop if immediate dominator is different
|
100
|
381 // from save block. If immediate dominator is not different, bail out.
|
|
382 Save = FindIDom<>(*Save, Save->predecessors(), *MDT);
|
|
383 if (!Save)
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
384 break;
|
100
|
385 } else {
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
386 // If the loop does not exit, there is no point in looking
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
387 // for a post-dominator outside the loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
388 SmallVector<MachineBasicBlock*, 4> ExitBlocks;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
389 MLI->getLoopFor(Restore)->getExitingBlocks(ExitBlocks);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
390 // Push Restore outside of this loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
391 // Look for the immediate post-dominator of the loop exits.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
392 MachineBasicBlock *IPdom = Restore;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
393 for (MachineBasicBlock *LoopExitBB: ExitBlocks) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
394 IPdom = FindIDom<>(*IPdom, LoopExitBB->successors(), *MPDT);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
395 if (!IPdom)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
396 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
397 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
398 // If the immediate post-dominator is not in a less nested loop,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
399 // then we are stuck in a program with an infinite loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
400 // In that case, we will not find a safe point, hence, bail out.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
401 if (IPdom && MLI->getLoopDepth(IPdom) < MLI->getLoopDepth(Restore))
|
100
|
402 Restore = IPdom;
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
403 else {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
404 Restore = nullptr;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
405 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
406 }
|
100
|
407 }
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
408 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
409 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
410 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
411
|
100
|
412 /// Check whether the edge (\p SrcBB, \p DestBB) is a backedge according to MLI.
|
|
413 /// I.e., check if it exists a loop that contains SrcBB and where DestBB is the
|
|
414 /// loop header.
|
|
415 static bool isProperBackedge(const MachineLoopInfo &MLI,
|
|
416 const MachineBasicBlock *SrcBB,
|
|
417 const MachineBasicBlock *DestBB) {
|
|
418 for (const MachineLoop *Loop = MLI.getLoopFor(SrcBB); Loop;
|
|
419 Loop = Loop->getParentLoop()) {
|
|
420 if (Loop->getHeader() == DestBB)
|
|
421 return true;
|
|
422 }
|
|
423 return false;
|
|
424 }
|
|
425
|
|
426 /// Check if the CFG of \p MF is irreducible.
|
|
427 static bool isIrreducibleCFG(const MachineFunction &MF,
|
|
428 const MachineLoopInfo &MLI) {
|
|
429 const MachineBasicBlock *Entry = &*MF.begin();
|
|
430 ReversePostOrderTraversal<const MachineBasicBlock *> RPOT(Entry);
|
|
431 BitVector VisitedBB(MF.getNumBlockIDs());
|
|
432 for (const MachineBasicBlock *MBB : RPOT) {
|
|
433 VisitedBB.set(MBB->getNumber());
|
|
434 for (const MachineBasicBlock *SuccBB : MBB->successors()) {
|
|
435 if (!VisitedBB.test(SuccBB->getNumber()))
|
|
436 continue;
|
|
437 // We already visited SuccBB, thus MBB->SuccBB must be a backedge.
|
|
438 // Check that the head matches what we have in the loop information.
|
|
439 // Otherwise, we have an irreducible graph.
|
|
440 if (!isProperBackedge(MLI, MBB, SuccBB))
|
|
441 return true;
|
|
442 }
|
|
443 }
|
|
444 return false;
|
|
445 }
|
|
446
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
447 bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) {
|
121
|
448 if (skipFunction(*MF.getFunction()) || MF.empty() || !isShrinkWrapEnabled(MF))
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
449 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
450
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
451 DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n');
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
452
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
453 init(MF);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
454
|
100
|
455 if (isIrreducibleCFG(MF, *MLI)) {
|
|
456 // If MF is irreducible, a block may be in a loop without
|
|
457 // MachineLoopInfo reporting it. I.e., we may use the
|
|
458 // post-dominance property in loops, which lead to incorrect
|
|
459 // results. Moreover, we may miss that the prologue and
|
|
460 // epilogue are not in the same loop, leading to unbalanced
|
|
461 // construction/deconstruction of the stack frame.
|
|
462 DEBUG(dbgs() << "Irreducible CFGs are not supported yet\n");
|
|
463 return false;
|
|
464 }
|
|
465
|
|
466 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
|
|
467 std::unique_ptr<RegScavenger> RS(
|
|
468 TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : nullptr);
|
|
469
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
470 for (MachineBasicBlock &MBB : MF) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
471 DEBUG(dbgs() << "Look into: " << MBB.getNumber() << ' ' << MBB.getName()
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
472 << '\n');
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
473
|
100
|
474 if (MBB.isEHFuncletEntry()) {
|
|
475 DEBUG(dbgs() << "EH Funclets are not supported yet.\n");
|
|
476 return false;
|
|
477 }
|
|
478
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
479 for (const MachineInstr &MI : MBB) {
|
100
|
480 if (!useOrDefCSROrFI(MI, RS.get()))
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
481 continue;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
482 // Save (resp. restore) point must dominate (resp. post dominate)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
483 // MI. Look for the proper basic block for those.
|
100
|
484 updateSaveRestorePoints(MBB, RS.get());
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
485 // If we are at a point where we cannot improve the placement of
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
486 // save/restore instructions, just give up.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
487 if (!ArePointsInteresting()) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
488 DEBUG(dbgs() << "No Shrink wrap candidate found\n");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
489 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
490 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
491 // No need to look for other instructions, this basic block
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
492 // will already be part of the handled region.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
493 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
494 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
495 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
496 if (!ArePointsInteresting()) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
497 // If the points are not interesting at this point, then they must be null
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
498 // because it means we did not encounter any frame/CSR related code.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
499 // Otherwise, we would have returned from the previous loop.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
500 assert(!Save && !Restore && "We miss a shrink-wrap opportunity?!");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
501 DEBUG(dbgs() << "Nothing to shrink-wrap\n");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
502 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
503 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
504
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
505 DEBUG(dbgs() << "\n ** Results **\nFrequency of the Entry: " << EntryFreq
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
506 << '\n');
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
507
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
508 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
509 do {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
510 DEBUG(dbgs() << "Shrink wrap candidates (#, Name, Freq):\nSave: "
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
511 << Save->getNumber() << ' ' << Save->getName() << ' '
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
512 << MBFI->getBlockFreq(Save).getFrequency() << "\nRestore: "
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
513 << Restore->getNumber() << ' ' << Restore->getName() << ' '
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
514 << MBFI->getBlockFreq(Restore).getFrequency() << '\n');
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
515
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
516 bool IsSaveCheap, TargetCanUseSaveAsPrologue = false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
517 if (((IsSaveCheap = EntryFreq >= MBFI->getBlockFreq(Save).getFrequency()) &&
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
518 EntryFreq >= MBFI->getBlockFreq(Restore).getFrequency()) &&
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
519 ((TargetCanUseSaveAsPrologue = TFI->canUseAsPrologue(*Save)) &&
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
520 TFI->canUseAsEpilogue(*Restore)))
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
521 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
522 DEBUG(dbgs() << "New points are too expensive or invalid for the target\n");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
523 MachineBasicBlock *NewBB;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
524 if (!IsSaveCheap || !TargetCanUseSaveAsPrologue) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
525 Save = FindIDom<>(*Save, Save->predecessors(), *MDT);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
526 if (!Save)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
527 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
528 NewBB = Save;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
529 } else {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
530 // Restore is expensive.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
531 Restore = FindIDom<>(*Restore, Restore->successors(), *MPDT);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
532 if (!Restore)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
533 break;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
534 NewBB = Restore;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
535 }
|
100
|
536 updateSaveRestorePoints(*NewBB, RS.get());
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
537 } while (Save && Restore);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
538
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
539 if (!ArePointsInteresting()) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
540 ++NumCandidatesDropped;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
541 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
542 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
543
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
544 DEBUG(dbgs() << "Final shrink wrap candidates:\nSave: " << Save->getNumber()
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
545 << ' ' << Save->getName() << "\nRestore: "
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
546 << Restore->getNumber() << ' ' << Restore->getName() << '\n');
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
547
|
120
|
548 MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
549 MFI.setSavePoint(Save);
|
|
550 MFI.setRestorePoint(Restore);
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
551 ++NumCandidates;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
552 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
553 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
554
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
555 bool ShrinkWrap::isShrinkWrapEnabled(const MachineFunction &MF) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
556 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
557
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
558 switch (EnableShrinkWrapOpt) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
559 case cl::BOU_UNSET:
|
100
|
560 return TFI->enableShrinkWrapping(MF) &&
|
|
561 // Windows with CFI has some limitations that make it impossible
|
|
562 // to use shrink-wrapping.
|
|
563 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
|
|
564 // Sanitizers look at the value of the stack at the location
|
|
565 // of the crash. Since a crash can happen anywhere, the
|
|
566 // frame must be lowered before anything else happen for the
|
|
567 // sanitizers to be able to get a correct stack frame.
|
|
568 !(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
|
|
569 MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
|
|
570 MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory));
|
95
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
571 // If EnableShrinkWrap is set, it takes precedence on whatever the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
572 // target sets. The rational is that we assume we want to test
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
573 // something related to shrink-wrapping.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
574 case cl::BOU_TRUE:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
575 return true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
576 case cl::BOU_FALSE:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
577 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
578 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
579 llvm_unreachable("Invalid shrink-wrapping state");
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
580 }
|