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/MachineFunctionPass.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 using namespace llvm; 23 24 #define SYSTEMZ_POSTREWRITE_NAME "SystemZ Post Rewrite pass" 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 llvm { 31 void initializeSystemZPostRewritePass(PassRegistry&); 32 } 33 34 namespace { 35 36 class SystemZPostRewrite : public MachineFunctionPass { 37 public: 38 static char ID; 39 SystemZPostRewrite() : MachineFunctionPass(ID) { 40 initializeSystemZPostRewritePass(*PassRegistry::getPassRegistry()); 41 } 42 43 const SystemZInstrInfo *TII; 44 45 bool runOnMachineFunction(MachineFunction &Fn) override; 46 47 StringRef getPassName() const override { return SYSTEMZ_POSTREWRITE_NAME; } 48 49 private: 50 void selectLOCRMux(MachineBasicBlock &MBB, 51 MachineBasicBlock::iterator MBBI, 52 MachineBasicBlock::iterator &NextMBBI, 53 unsigned LowOpcode, 54 unsigned HighOpcode); 55 void selectSELRMux(MachineBasicBlock &MBB, 56 MachineBasicBlock::iterator MBBI, 57 MachineBasicBlock::iterator &NextMBBI, 58 unsigned LowOpcode, 59 unsigned HighOpcode); 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); 66 }; 67 68 char SystemZPostRewrite::ID = 0; 69 70 } // end anonymous namespace 71 72 INITIALIZE_PASS(SystemZPostRewrite, "systemz-post-rewrite", 73 SYSTEMZ_POSTREWRITE_NAME, false, false) 74 75 /// Returns an instance of the Post Rewrite pass. 76 FunctionPass *llvm::createSystemZPostRewritePass(SystemZTargetMachine &TM) { 77 return new SystemZPostRewrite(); 78 } 79 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 83 // is created. 84 void SystemZPostRewrite::selectLOCRMux(MachineBasicBlock &MBB, 85 MachineBasicBlock::iterator MBBI, 86 MachineBasicBlock::iterator &NextMBBI, 87 unsigned LowOpcode, 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); 93 94 if (!DestIsHigh && !SrcIsHigh) 95 MBBI->setDesc(TII->get(LowOpcode)); 96 else if (DestIsHigh && SrcIsHigh) 97 MBBI->setDesc(TII->get(HighOpcode)); 98 else 99 expandCondMove(MBB, MBBI, NextMBBI); 100 } 101 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, 108 unsigned LowOpcode, 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); 116 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); 126 Src1Reg = 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); 133 Src2Reg = DestReg; 134 Src2IsHigh = DestIsHigh; 135 } 136 } 137 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); 143 } 144 145 if (!DestIsHigh && !Src1IsHigh && !Src2IsHigh) 146 MBBI->setDesc(TII->get(LowOpcode)); 147 else if (DestIsHigh && Src1IsHigh && Src2IsHigh) 148 MBBI->setDesc(TII->get(HighOpcode)); 149 else 150 // Given the simplification above, we must already have a two-operand case. 151 expandCondMove(MBB, MBBI, NextMBBI); 152 } 153 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."); 170 171 LivePhysRegs LiveRegs(TII->getRegisterInfo()); 172 LiveRegs.addLiveOuts(MBB); 173 for (auto I = std::prev(MBB.end()); I != MBBI; --I) 174 LiveRegs.stepBackward(*I); 175 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); 183 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); 190 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); 197 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); 203 204 NextMBBI = MBB.end(); 205 MI.eraseFromParent(); 206 LOCRMuxJumps++; 207 return true; 208 } 209 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(); 217 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); 231 MemFoldCopies++; 232 } 233 return true; 234 } 235 236 switch (Opcode) { 237 case SystemZ::LOCRMux: 238 selectLOCRMux(MBB, MBBI, NextMBBI, SystemZ::LOCR, SystemZ::LOCFHR); 239 return true; 240 case SystemZ::SELRMux: 241 selectSELRMux(MBB, MBBI, NextMBBI, SystemZ::SELR, SystemZ::SELFHR); 242 return true; 243 } 244 245 return false; 246 } 247 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; 252 253 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 254 while (MBBI != E) { 255 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 256 Modified |= selectMI(MBB, MBBI, NMBBI); 257 MBBI = NMBBI; 258 } 259 260 return Modified; 261 } 262 263 bool SystemZPostRewrite::runOnMachineFunction(MachineFunction &MF) { 264 TII = static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 265 266 bool Modified = false; 267 for (auto &MBB : MF) 268 Modified |= selectMBB(MBB); 269 270 return Modified; 271 } 272 273