1 | //==---- SystemZPostRewrite.cpp - Select pseudos after RegAlloc ---*- C++ -*-=// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains a pass that is run immediately after VirtRegRewriter |
10 | // but before MachineCopyPropagation. The purpose is to lower pseudos to |
11 | // target instructions before any later pass might substitute a register for |
12 | // another. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #include "SystemZ.h" |
17 | #include "SystemZInstrInfo.h" |
18 | #include "SystemZSubtarget.h" |
19 | #include "llvm/ADT/Statistic.h" |
20 | #include "llvm/CodeGen/LivePhysRegs.h" |
21 | #include "llvm/CodeGen/MachineFunctionPass.h" |
22 | #include "llvm/CodeGen/MachineInstr.h" |
23 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
24 | using namespace llvm; |
25 | |
26 | #define DEBUG_TYPE "systemz-postrewrite" |
27 | STATISTIC(MemFoldCopies, "Number of copies inserted before folded mem ops." ); |
28 | STATISTIC(LOCRMuxJumps, "Number of LOCRMux jump-sequences (lower is better)" ); |
29 | |
30 | namespace { |
31 | |
32 | class SystemZPostRewrite : public MachineFunctionPass { |
33 | public: |
34 | static char ID; |
35 | SystemZPostRewrite() : MachineFunctionPass(ID) {} |
36 | |
37 | const SystemZInstrInfo *TII; |
38 | |
39 | bool runOnMachineFunction(MachineFunction &Fn) override; |
40 | |
41 | private: |
42 | void selectLOCRMux(MachineBasicBlock &MBB, |
43 | MachineBasicBlock::iterator MBBI, |
44 | MachineBasicBlock::iterator &NextMBBI, |
45 | unsigned LowOpcode, |
46 | unsigned HighOpcode); |
47 | void selectSELRMux(MachineBasicBlock &MBB, |
48 | MachineBasicBlock::iterator MBBI, |
49 | MachineBasicBlock::iterator &NextMBBI, |
50 | unsigned LowOpcode, |
51 | unsigned HighOpcode); |
52 | bool expandCondMove(MachineBasicBlock &MBB, |
53 | MachineBasicBlock::iterator MBBI, |
54 | MachineBasicBlock::iterator &NextMBBI); |
55 | bool selectMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
56 | MachineBasicBlock::iterator &NextMBBI); |
57 | bool selectMBB(MachineBasicBlock &MBB); |
58 | }; |
59 | |
60 | char SystemZPostRewrite::ID = 0; |
61 | |
62 | } // end anonymous namespace |
63 | |
64 | INITIALIZE_PASS(SystemZPostRewrite, "systemz-post-rewrite" , |
65 | "SystemZ Post Rewrite pass" , false, false) |
66 | |
67 | /// Returns an instance of the Post Rewrite pass. |
68 | FunctionPass *llvm::createSystemZPostRewritePass(SystemZTargetMachine &TM) { |
69 | return new SystemZPostRewrite(); |
70 | } |
71 | |
72 | // MI is a load-register-on-condition pseudo instruction. Replace it with |
73 | // LowOpcode if source and destination are both low GR32s and HighOpcode if |
74 | // source and destination are both high GR32s. Otherwise, a branch sequence |
75 | // is created. |
76 | void SystemZPostRewrite::selectLOCRMux(MachineBasicBlock &MBB, |
77 | MachineBasicBlock::iterator MBBI, |
78 | MachineBasicBlock::iterator &NextMBBI, |
79 | unsigned LowOpcode, |
80 | unsigned HighOpcode) { |
81 | Register DestReg = MBBI->getOperand(i: 0).getReg(); |
82 | Register SrcReg = MBBI->getOperand(i: 2).getReg(); |
83 | bool DestIsHigh = SystemZ::isHighReg(Reg: DestReg); |
84 | bool SrcIsHigh = SystemZ::isHighReg(Reg: SrcReg); |
85 | |
86 | if (!DestIsHigh && !SrcIsHigh) |
87 | MBBI->setDesc(TII->get(Opcode: LowOpcode)); |
88 | else if (DestIsHigh && SrcIsHigh) |
89 | MBBI->setDesc(TII->get(Opcode: HighOpcode)); |
90 | else |
91 | expandCondMove(MBB, MBBI, NextMBBI); |
92 | } |
93 | |
94 | // MI is a select pseudo instruction. Replace it with LowOpcode if source |
95 | // and destination are all low GR32s and HighOpcode if source and destination |
96 | // are all high GR32s. Otherwise, a branch sequence is created. |
97 | void SystemZPostRewrite::selectSELRMux(MachineBasicBlock &MBB, |
98 | MachineBasicBlock::iterator MBBI, |
99 | MachineBasicBlock::iterator &NextMBBI, |
100 | unsigned LowOpcode, |
101 | unsigned HighOpcode) { |
102 | Register DestReg = MBBI->getOperand(i: 0).getReg(); |
103 | MachineOperand &Src1MO = MBBI->getOperand(i: 1); |
104 | MachineOperand &Src2MO = MBBI->getOperand(i: 2); |
105 | Register Src1Reg = Src1MO.getReg(); |
106 | Register Src2Reg = Src2MO.getReg(); |
107 | bool DestIsHigh = SystemZ::isHighReg(Reg: DestReg); |
108 | bool Src1IsHigh = SystemZ::isHighReg(Reg: Src1Reg); |
109 | bool Src2IsHigh = SystemZ::isHighReg(Reg: Src2Reg); |
110 | // A copy instruction that we might create, held here for the purpose of |
111 | // debug instr value tracking. |
112 | MachineInstr *CopyInst = nullptr; |
113 | |
114 | // In rare cases both sources are the same register (after |
115 | // machine-cse). This must be handled as it may lead to wrong-code (after |
116 | // machine-cp) if the kill flag on Src1 isn't cleared (with |
117 | // expandCondMove()). |
118 | if (Src1Reg == Src2Reg) { |
119 | CopyInst = BuildMI(BB&: *MBBI->getParent(), I: MBBI, MIMD: MBBI->getDebugLoc(), |
120 | MCID: TII->get(Opcode: SystemZ::COPY), DestReg) |
121 | .addReg(RegNo: Src1Reg, flags: getRegState(RegOp: Src1MO) & getRegState(RegOp: Src2MO)); |
122 | MBB.getParent()->substituteDebugValuesForInst(Old: *MBBI, New&: *CopyInst, MaxOperand: 1); |
123 | MBBI->eraseFromParent(); |
124 | return; |
125 | } |
126 | |
127 | // If sources and destination aren't all high or all low, we may be able to |
128 | // simplify the operation by moving one of the sources to the destination |
129 | // first. But only if this doesn't clobber the other source. |
130 | if (DestReg != Src1Reg && DestReg != Src2Reg) { |
131 | if (DestIsHigh != Src1IsHigh) { |
132 | CopyInst = BuildMI(BB&: *MBBI->getParent(), I: MBBI, MIMD: MBBI->getDebugLoc(), |
133 | MCID: TII->get(Opcode: SystemZ::COPY), DestReg) |
134 | .addReg(RegNo: Src1Reg, flags: getRegState(RegOp: Src1MO)); |
135 | Src1MO.setReg(DestReg); |
136 | Src1Reg = DestReg; |
137 | Src1IsHigh = DestIsHigh; |
138 | } else if (DestIsHigh != Src2IsHigh) { |
139 | CopyInst = BuildMI(BB&: *MBBI->getParent(), I: MBBI, MIMD: MBBI->getDebugLoc(), |
140 | MCID: TII->get(Opcode: SystemZ::COPY), DestReg) |
141 | .addReg(RegNo: Src2Reg, flags: getRegState(RegOp: Src2MO)); |
142 | Src2MO.setReg(DestReg); |
143 | Src2Reg = DestReg; |
144 | Src2IsHigh = DestIsHigh; |
145 | } |
146 | } |
147 | // if a copy instruction was inserted, record the debug value substitution |
148 | if (CopyInst) |
149 | MBB.getParent()->substituteDebugValuesForInst(Old: *MBBI, New&: *CopyInst, MaxOperand: 1); |
150 | |
151 | // If the destination (now) matches one source, prefer this to be first. |
152 | if (DestReg != Src1Reg && DestReg == Src2Reg) { |
153 | TII->commuteInstruction(MI&: *MBBI, NewMI: false, OpIdx1: 1, OpIdx2: 2); |
154 | std::swap(a&: Src1Reg, b&: Src2Reg); |
155 | std::swap(a&: Src1IsHigh, b&: Src2IsHigh); |
156 | } |
157 | |
158 | if (!DestIsHigh && !Src1IsHigh && !Src2IsHigh) |
159 | MBBI->setDesc(TII->get(Opcode: LowOpcode)); |
160 | else if (DestIsHigh && Src1IsHigh && Src2IsHigh) |
161 | MBBI->setDesc(TII->get(Opcode: HighOpcode)); |
162 | else |
163 | // Given the simplification above, we must already have a two-operand case. |
164 | expandCondMove(MBB, MBBI, NextMBBI); |
165 | } |
166 | |
167 | // Replace MBBI by a branch sequence that performs a conditional move of |
168 | // operand 2 to the destination register. Operand 1 is expected to be the |
169 | // same register as the destination. |
170 | bool SystemZPostRewrite::expandCondMove(MachineBasicBlock &MBB, |
171 | MachineBasicBlock::iterator MBBI, |
172 | MachineBasicBlock::iterator &NextMBBI) { |
173 | MachineFunction &MF = *MBB.getParent(); |
174 | const BasicBlock *BB = MBB.getBasicBlock(); |
175 | MachineInstr &MI = *MBBI; |
176 | DebugLoc DL = MI.getDebugLoc(); |
177 | Register DestReg = MI.getOperand(i: 0).getReg(); |
178 | Register SrcReg = MI.getOperand(i: 2).getReg(); |
179 | unsigned CCValid = MI.getOperand(i: 3).getImm(); |
180 | unsigned CCMask = MI.getOperand(i: 4).getImm(); |
181 | assert(DestReg == MI.getOperand(1).getReg() && |
182 | "Expected destination and first source operand to be the same." ); |
183 | |
184 | LivePhysRegs LiveRegs(TII->getRegisterInfo()); |
185 | LiveRegs.addLiveOuts(MBB); |
186 | for (auto I = std::prev(x: MBB.end()); I != MBBI; --I) |
187 | LiveRegs.stepBackward(MI: *I); |
188 | |
189 | // Splice MBB at MI, moving the rest of the block into RestMBB. |
190 | MachineBasicBlock *RestMBB = MF.CreateMachineBasicBlock(BB); |
191 | MF.insert(MBBI: std::next(x: MachineFunction::iterator(MBB)), MBB: RestMBB); |
192 | RestMBB->splice(Where: RestMBB->begin(), Other: &MBB, From: MI, To: MBB.end()); |
193 | RestMBB->transferSuccessors(FromMBB: &MBB); |
194 | for (MCPhysReg R : LiveRegs) |
195 | RestMBB->addLiveIn(PhysReg: R); |
196 | |
197 | // Create a new block MoveMBB to hold the move instruction. |
198 | MachineBasicBlock *MoveMBB = MF.CreateMachineBasicBlock(BB); |
199 | MF.insert(MBBI: std::next(x: MachineFunction::iterator(MBB)), MBB: MoveMBB); |
200 | MoveMBB->addLiveIn(PhysReg: SrcReg); |
201 | for (MCPhysReg R : LiveRegs) |
202 | MoveMBB->addLiveIn(PhysReg: R); |
203 | |
204 | // At the end of MBB, create a conditional branch to RestMBB if the |
205 | // condition is false, otherwise fall through to MoveMBB. |
206 | BuildMI(BB: &MBB, MIMD: DL, MCID: TII->get(Opcode: SystemZ::BRC)) |
207 | .addImm(Val: CCValid).addImm(Val: CCMask ^ CCValid).addMBB(MBB: RestMBB); |
208 | MBB.addSuccessor(Succ: RestMBB); |
209 | MBB.addSuccessor(Succ: MoveMBB); |
210 | |
211 | // In MoveMBB, emit an instruction to move SrcReg into DestReg, |
212 | // then fall through to RestMBB. |
213 | MachineInstr *CopyInst = |
214 | BuildMI(BB&: *MoveMBB, I: MoveMBB->end(), MIMD: DL, MCID: TII->get(Opcode: SystemZ::COPY), DestReg) |
215 | .addReg(RegNo: MI.getOperand(i: 2).getReg(), flags: getRegState(RegOp: MI.getOperand(i: 2))); |
216 | // record the debug value substitution for CopyInst |
217 | MBB.getParent()->substituteDebugValuesForInst(Old: *MBBI, New&: *CopyInst, MaxOperand: 1); |
218 | MoveMBB->addSuccessor(Succ: RestMBB); |
219 | |
220 | NextMBBI = MBB.end(); |
221 | MI.eraseFromParent(); |
222 | LOCRMuxJumps++; |
223 | return true; |
224 | } |
225 | |
226 | /// If MBBI references a pseudo instruction that should be selected here, |
227 | /// do it and return true. Otherwise return false. |
228 | bool SystemZPostRewrite::selectMI(MachineBasicBlock &MBB, |
229 | MachineBasicBlock::iterator MBBI, |
230 | MachineBasicBlock::iterator &NextMBBI) { |
231 | MachineInstr &MI = *MBBI; |
232 | unsigned Opcode = MI.getOpcode(); |
233 | |
234 | // Note: If this could be done during regalloc in foldMemoryOperandImpl() |
235 | // while also updating the LiveIntervals, there would be no need for the |
236 | // MemFoldPseudo to begin with. |
237 | int TargetMemOpcode = SystemZ::getTargetMemOpcode(Opcode); |
238 | if (TargetMemOpcode != -1) { |
239 | MI.setDesc(TII->get(Opcode: TargetMemOpcode)); |
240 | MI.tieOperands(DefIdx: 0, UseIdx: 1); |
241 | Register DstReg = MI.getOperand(i: 0).getReg(); |
242 | MachineOperand &SrcMO = MI.getOperand(i: 1); |
243 | if (DstReg != SrcMO.getReg()) { |
244 | BuildMI(BB&: MBB, I: &MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: SystemZ::COPY), DestReg: DstReg) |
245 | .addReg(RegNo: SrcMO.getReg()); |
246 | SrcMO.setReg(DstReg); |
247 | MemFoldCopies++; |
248 | } |
249 | return true; |
250 | } |
251 | |
252 | switch (Opcode) { |
253 | case SystemZ::LOCRMux: |
254 | selectLOCRMux(MBB, MBBI, NextMBBI, LowOpcode: SystemZ::LOCR, HighOpcode: SystemZ::LOCFHR); |
255 | return true; |
256 | case SystemZ::SELRMux: |
257 | selectSELRMux(MBB, MBBI, NextMBBI, LowOpcode: SystemZ::SELR, HighOpcode: SystemZ::SELFHR); |
258 | return true; |
259 | } |
260 | |
261 | return false; |
262 | } |
263 | |
264 | /// Iterate over the instructions in basic block MBB and select any |
265 | /// pseudo instructions. Return true if anything was modified. |
266 | bool SystemZPostRewrite::selectMBB(MachineBasicBlock &MBB) { |
267 | bool Modified = false; |
268 | |
269 | MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
270 | while (MBBI != E) { |
271 | MachineBasicBlock::iterator NMBBI = std::next(x: MBBI); |
272 | Modified |= selectMI(MBB, MBBI, NextMBBI&: NMBBI); |
273 | MBBI = NMBBI; |
274 | } |
275 | |
276 | return Modified; |
277 | } |
278 | |
279 | bool SystemZPostRewrite::runOnMachineFunction(MachineFunction &MF) { |
280 | TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo(); |
281 | |
282 | bool Modified = false; |
283 | for (auto &MBB : MF) |
284 | Modified |= selectMBB(MBB); |
285 | |
286 | return Modified; |
287 | } |
288 | |
289 | |