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(0).getReg(); 82 Register SrcReg = MBBI->getOperand(2).getReg(); 83 bool DestIsHigh = SystemZ::isHighReg(DestReg); 84 bool SrcIsHigh = SystemZ::isHighReg(SrcReg); 85 86 if (!DestIsHigh && !SrcIsHigh) 87 MBBI->setDesc(TII->get(LowOpcode)); 88 else if (DestIsHigh && SrcIsHigh) 89 MBBI->setDesc(TII->get(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(0).getReg(); 103 MachineOperand &Src1MO = MBBI->getOperand(1); 104 MachineOperand &Src2MO = MBBI->getOperand(2); 105 Register Src1Reg = Src1MO.getReg(); 106 Register Src2Reg = Src2MO.getReg(); 107 bool DestIsHigh = SystemZ::isHighReg(DestReg); 108 bool Src1IsHigh = SystemZ::isHighReg(Src1Reg); 109 bool Src2IsHigh = SystemZ::isHighReg(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(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(), 120 TII->get(SystemZ::COPY), DestReg) 121 .addReg(Src1Reg, getRegState(Src1MO) & getRegState(Src2MO)); 122 MBB.getParent()->substituteDebugValuesForInst(*MBBI, *CopyInst, 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(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(), 133 TII->get(SystemZ::COPY), DestReg) 134 .addReg(Src1Reg, getRegState(Src1MO)); 135 Src1MO.setReg(DestReg); 136 Src1Reg = DestReg; 137 Src1IsHigh = DestIsHigh; 138 } else if (DestIsHigh != Src2IsHigh) { 139 CopyInst = BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(), 140 TII->get(SystemZ::COPY), DestReg) 141 .addReg(Src2Reg, getRegState(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(*MBBI, *CopyInst, 1); 150 151 // If the destination (now) matches one source, prefer this to be first. 152 if (DestReg != Src1Reg && DestReg == Src2Reg) { 153 TII->commuteInstruction(*MBBI, false, 1, 2); 154 std::swap(Src1Reg, Src2Reg); 155 std::swap(Src1IsHigh, Src2IsHigh); 156 } 157 158 if (!DestIsHigh && !Src1IsHigh && !Src2IsHigh) 159 MBBI->setDesc(TII->get(LowOpcode)); 160 else if (DestIsHigh && Src1IsHigh && Src2IsHigh) 161 MBBI->setDesc(TII->get(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(0).getReg(); 178 Register SrcReg = MI.getOperand(2).getReg(); 179 unsigned CCValid = MI.getOperand(3).getImm(); 180 unsigned CCMask = MI.getOperand(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(MBB.end()); I != MBBI; --I) 187 LiveRegs.stepBackward(*I); 188 189 // Splice MBB at MI, moving the rest of the block into RestMBB. 190 MachineBasicBlock *RestMBB = MF.CreateMachineBasicBlock(BB); 191 MF.insert(std::next(MachineFunction::iterator(MBB)), RestMBB); 192 RestMBB->splice(RestMBB->begin(), &MBB, MI, MBB.end()); 193 RestMBB->transferSuccessors(&MBB); 194 for (MCPhysReg R : LiveRegs) 195 RestMBB->addLiveIn(R); 196 197 // Create a new block MoveMBB to hold the move instruction. 198 MachineBasicBlock *MoveMBB = MF.CreateMachineBasicBlock(BB); 199 MF.insert(std::next(MachineFunction::iterator(MBB)), MoveMBB); 200 MoveMBB->addLiveIn(SrcReg); 201 for (MCPhysReg R : LiveRegs) 202 MoveMBB->addLiveIn(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(&MBB, DL, TII->get(SystemZ::BRC)) 207 .addImm(CCValid).addImm(CCMask ^ CCValid).addMBB(RestMBB); 208 MBB.addSuccessor(RestMBB); 209 MBB.addSuccessor(MoveMBB); 210 211 // In MoveMBB, emit an instruction to move SrcReg into DestReg, 212 // then fall through to RestMBB. 213 MachineInstr *CopyInst = 214 BuildMI(*MoveMBB, MoveMBB->end(), DL, TII->get(SystemZ::COPY), DestReg) 215 .addReg(MI.getOperand(2).getReg(), getRegState(MI.getOperand(2))); 216 // record the debug value substitution for CopyInst 217 MBB.getParent()->substituteDebugValuesForInst(*MBBI, *CopyInst, 1); 218 MoveMBB->addSuccessor(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(TargetMemOpcode)); 240 MI.tieOperands(0, 1); 241 Register DstReg = MI.getOperand(0).getReg(); 242 MachineOperand &SrcMO = MI.getOperand(1); 243 if (DstReg != SrcMO.getReg()) { 244 BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(SystemZ::COPY), DstReg) 245 .addReg(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, SystemZ::LOCR, SystemZ::LOCFHR); 255 return true; 256 case SystemZ::SELRMux: 257 selectSELRMux(MBB, MBBI, NextMBBI, SystemZ::SELR, 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(MBBI); 272 Modified |= selectMI(MBB, MBBI, 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