1 //==---- SystemZPostRewrite.cpp - Select pseudos after RegAlloc ---*- C++ -*-=//
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
7 //===----------------------------------------------------------------------===//
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
14 //===----------------------------------------------------------------------===//
17 #include "SystemZInstrInfo.h"
18 #include "SystemZSubtarget.h"
19 #include "llvm/ADT/Statistic.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #define SYSTEMZ_POSTREWRITE_NAME "SystemZ Post Rewrite pass"
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)");
31 void initializeSystemZPostRewritePass(PassRegistry
&);
36 class SystemZPostRewrite
: public MachineFunctionPass
{
39 SystemZPostRewrite() : MachineFunctionPass(ID
) {
40 initializeSystemZPostRewritePass(*PassRegistry::getPassRegistry());
43 const SystemZInstrInfo
*TII
;
45 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
47 StringRef
getPassName() const override
{ return SYSTEMZ_POSTREWRITE_NAME
; }
50 void selectLOCRMux(MachineBasicBlock
&MBB
,
51 MachineBasicBlock::iterator MBBI
,
52 MachineBasicBlock::iterator
&NextMBBI
,
55 void selectSELRMux(MachineBasicBlock
&MBB
,
56 MachineBasicBlock::iterator MBBI
,
57 MachineBasicBlock::iterator
&NextMBBI
,
60 bool expandCondMove(MachineBasicBlock
&MBB
,
61 MachineBasicBlock::iterator MBBI
,
62 MachineBasicBlock::iterator
&NextMBBI
);
63 bool selectMI(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
64 MachineBasicBlock::iterator
&NextMBBI
);
65 bool selectMBB(MachineBasicBlock
&MBB
);
68 char SystemZPostRewrite::ID
= 0;
70 } // end anonymous namespace
72 INITIALIZE_PASS(SystemZPostRewrite
, "systemz-post-rewrite",
73 SYSTEMZ_POSTREWRITE_NAME
, false, false)
75 /// Returns an instance of the Post Rewrite pass.
76 FunctionPass
*llvm::createSystemZPostRewritePass(SystemZTargetMachine
&TM
) {
77 return new SystemZPostRewrite();
80 // MI is a load-register-on-condition pseudo instruction. Replace it with
81 // LowOpcode if source and destination are both low GR32s and HighOpcode if
82 // source and destination are both high GR32s. Otherwise, a branch sequence
84 void SystemZPostRewrite::selectLOCRMux(MachineBasicBlock
&MBB
,
85 MachineBasicBlock::iterator MBBI
,
86 MachineBasicBlock::iterator
&NextMBBI
,
88 unsigned HighOpcode
) {
89 Register DestReg
= MBBI
->getOperand(0).getReg();
90 Register SrcReg
= MBBI
->getOperand(2).getReg();
91 bool DestIsHigh
= SystemZ::isHighReg(DestReg
);
92 bool SrcIsHigh
= SystemZ::isHighReg(SrcReg
);
94 if (!DestIsHigh
&& !SrcIsHigh
)
95 MBBI
->setDesc(TII
->get(LowOpcode
));
96 else if (DestIsHigh
&& SrcIsHigh
)
97 MBBI
->setDesc(TII
->get(HighOpcode
));
99 expandCondMove(MBB
, MBBI
, NextMBBI
);
102 // MI is a select pseudo instruction. Replace it with LowOpcode if source
103 // and destination are all low GR32s and HighOpcode if source and destination
104 // are all high GR32s. Otherwise, a branch sequence is created.
105 void SystemZPostRewrite::selectSELRMux(MachineBasicBlock
&MBB
,
106 MachineBasicBlock::iterator MBBI
,
107 MachineBasicBlock::iterator
&NextMBBI
,
109 unsigned HighOpcode
) {
110 Register DestReg
= MBBI
->getOperand(0).getReg();
111 Register Src1Reg
= MBBI
->getOperand(1).getReg();
112 Register Src2Reg
= MBBI
->getOperand(2).getReg();
113 bool DestIsHigh
= SystemZ::isHighReg(DestReg
);
114 bool Src1IsHigh
= SystemZ::isHighReg(Src1Reg
);
115 bool Src2IsHigh
= SystemZ::isHighReg(Src2Reg
);
117 // If sources and destination aren't all high or all low, we may be able to
118 // simplify the operation by moving one of the sources to the destination
119 // first. But only if this doesn't clobber the other source.
120 if (DestReg
!= Src1Reg
&& DestReg
!= Src2Reg
) {
121 if (DestIsHigh
!= Src1IsHigh
) {
122 BuildMI(*MBBI
->getParent(), MBBI
, MBBI
->getDebugLoc(),
123 TII
->get(SystemZ::COPY
), DestReg
)
124 .addReg(MBBI
->getOperand(1).getReg(), getRegState(MBBI
->getOperand(1)));
125 MBBI
->getOperand(1).setReg(DestReg
);
127 Src1IsHigh
= DestIsHigh
;
128 } else if (DestIsHigh
!= Src2IsHigh
) {
129 BuildMI(*MBBI
->getParent(), MBBI
, MBBI
->getDebugLoc(),
130 TII
->get(SystemZ::COPY
), DestReg
)
131 .addReg(MBBI
->getOperand(2).getReg(), getRegState(MBBI
->getOperand(2)));
132 MBBI
->getOperand(2).setReg(DestReg
);
134 Src2IsHigh
= DestIsHigh
;
138 // If the destination (now) matches one source, prefer this to be first.
139 if (DestReg
!= Src1Reg
&& DestReg
== Src2Reg
) {
140 TII
->commuteInstruction(*MBBI
, false, 1, 2);
141 std::swap(Src1Reg
, Src2Reg
);
142 std::swap(Src1IsHigh
, Src2IsHigh
);
145 if (!DestIsHigh
&& !Src1IsHigh
&& !Src2IsHigh
)
146 MBBI
->setDesc(TII
->get(LowOpcode
));
147 else if (DestIsHigh
&& Src1IsHigh
&& Src2IsHigh
)
148 MBBI
->setDesc(TII
->get(HighOpcode
));
150 // Given the simplification above, we must already have a two-operand case.
151 expandCondMove(MBB
, MBBI
, NextMBBI
);
154 // Replace MBBI by a branch sequence that performs a conditional move of
155 // operand 2 to the destination register. Operand 1 is expected to be the
156 // same register as the destination.
157 bool SystemZPostRewrite::expandCondMove(MachineBasicBlock
&MBB
,
158 MachineBasicBlock::iterator MBBI
,
159 MachineBasicBlock::iterator
&NextMBBI
) {
160 MachineFunction
&MF
= *MBB
.getParent();
161 const BasicBlock
*BB
= MBB
.getBasicBlock();
162 MachineInstr
&MI
= *MBBI
;
163 DebugLoc DL
= MI
.getDebugLoc();
164 Register DestReg
= MI
.getOperand(0).getReg();
165 Register SrcReg
= MI
.getOperand(2).getReg();
166 unsigned CCValid
= MI
.getOperand(3).getImm();
167 unsigned CCMask
= MI
.getOperand(4).getImm();
168 assert(DestReg
== MI
.getOperand(1).getReg() &&
169 "Expected destination and first source operand to be the same.");
171 LivePhysRegs
LiveRegs(TII
->getRegisterInfo());
172 LiveRegs
.addLiveOuts(MBB
);
173 for (auto I
= std::prev(MBB
.end()); I
!= MBBI
; --I
)
174 LiveRegs
.stepBackward(*I
);
176 // Splice MBB at MI, moving the rest of the block into RestMBB.
177 MachineBasicBlock
*RestMBB
= MF
.CreateMachineBasicBlock(BB
);
178 MF
.insert(std::next(MachineFunction::iterator(MBB
)), RestMBB
);
179 RestMBB
->splice(RestMBB
->begin(), &MBB
, MI
, MBB
.end());
180 RestMBB
->transferSuccessors(&MBB
);
181 for (auto I
= LiveRegs
.begin(); I
!= LiveRegs
.end(); ++I
)
182 RestMBB
->addLiveIn(*I
);
184 // Create a new block MoveMBB to hold the move instruction.
185 MachineBasicBlock
*MoveMBB
= MF
.CreateMachineBasicBlock(BB
);
186 MF
.insert(std::next(MachineFunction::iterator(MBB
)), MoveMBB
);
187 MoveMBB
->addLiveIn(SrcReg
);
188 for (auto I
= LiveRegs
.begin(); I
!= LiveRegs
.end(); ++I
)
189 MoveMBB
->addLiveIn(*I
);
191 // At the end of MBB, create a conditional branch to RestMBB if the
192 // condition is false, otherwise fall through to MoveMBB.
193 BuildMI(&MBB
, DL
, TII
->get(SystemZ::BRC
))
194 .addImm(CCValid
).addImm(CCMask
^ CCValid
).addMBB(RestMBB
);
195 MBB
.addSuccessor(RestMBB
);
196 MBB
.addSuccessor(MoveMBB
);
198 // In MoveMBB, emit an instruction to move SrcReg into DestReg,
199 // then fall through to RestMBB.
200 BuildMI(*MoveMBB
, MoveMBB
->end(), DL
, TII
->get(SystemZ::COPY
), DestReg
)
201 .addReg(MI
.getOperand(2).getReg(), getRegState(MI
.getOperand(2)));
202 MoveMBB
->addSuccessor(RestMBB
);
204 NextMBBI
= MBB
.end();
205 MI
.eraseFromParent();
210 /// If MBBI references a pseudo instruction that should be selected here,
211 /// do it and return true. Otherwise return false.
212 bool SystemZPostRewrite::selectMI(MachineBasicBlock
&MBB
,
213 MachineBasicBlock::iterator MBBI
,
214 MachineBasicBlock::iterator
&NextMBBI
) {
215 MachineInstr
&MI
= *MBBI
;
216 unsigned Opcode
= MI
.getOpcode();
218 // Note: If this could be done during regalloc in foldMemoryOperandImpl()
219 // while also updating the LiveIntervals, there would be no need for the
220 // MemFoldPseudo to begin with.
221 int TargetMemOpcode
= SystemZ::getTargetMemOpcode(Opcode
);
222 if (TargetMemOpcode
!= -1) {
223 MI
.setDesc(TII
->get(TargetMemOpcode
));
224 MI
.tieOperands(0, 1);
225 Register DstReg
= MI
.getOperand(0).getReg();
226 MachineOperand
&SrcMO
= MI
.getOperand(1);
227 if (DstReg
!= SrcMO
.getReg()) {
228 BuildMI(MBB
, &MI
, MI
.getDebugLoc(), TII
->get(SystemZ::COPY
), DstReg
)
229 .addReg(SrcMO
.getReg());
230 SrcMO
.setReg(DstReg
);
237 case SystemZ::LOCRMux
:
238 selectLOCRMux(MBB
, MBBI
, NextMBBI
, SystemZ::LOCR
, SystemZ::LOCFHR
);
240 case SystemZ::SELRMux
:
241 selectSELRMux(MBB
, MBBI
, NextMBBI
, SystemZ::SELR
, SystemZ::SELFHR
);
248 /// Iterate over the instructions in basic block MBB and select any
249 /// pseudo instructions. Return true if anything was modified.
250 bool SystemZPostRewrite::selectMBB(MachineBasicBlock
&MBB
) {
251 bool Modified
= false;
253 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
255 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
256 Modified
|= selectMI(MBB
, MBBI
, NMBBI
);
263 bool SystemZPostRewrite::runOnMachineFunction(MachineFunction
&MF
) {
264 TII
= static_cast<const SystemZInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
266 bool Modified
= false;
268 Modified
|= selectMBB(MBB
);