1 //===-- SystemZShortenInst.cpp - Instruction-shortening pass --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass tries to replace instructions with shorter forms. For example, 11 // IILF can be replaced with LLILL or LLILH if the constant fits and if the 12 // other 32 bits of the GR64 destination are not live. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "SystemZTargetMachine.h" 17 #include "llvm/CodeGen/MachineFunctionPass.h" 18 #include "llvm/CodeGen/MachineInstrBuilder.h" 19 #include "llvm/CodeGen/LivePhysRegs.h" 20 #include "llvm/Target/TargetRegisterInfo.h" 21 22 using namespace llvm; 23 24 #define DEBUG_TYPE "systemz-shorten-inst" 25 26 namespace { 27 class SystemZShortenInst : public MachineFunctionPass { 28 public: 29 static char ID; 30 SystemZShortenInst(const SystemZTargetMachine &tm); 31 32 const char *getPassName() const override { 33 return "SystemZ Instruction Shortening"; 34 } 35 36 bool processBlock(MachineBasicBlock &MBB); 37 bool runOnMachineFunction(MachineFunction &F) override; 38 39 private: 40 bool shortenIIF(MachineInstr &MI, unsigned LLIxL, unsigned LLIxH); 41 bool shortenOn0(MachineInstr &MI, unsigned Opcode); 42 bool shortenOn01(MachineInstr &MI, unsigned Opcode); 43 bool shortenOn001(MachineInstr &MI, unsigned Opcode); 44 bool shortenOn001AddCC(MachineInstr &MI, unsigned Opcode); 45 bool shortenFPConv(MachineInstr &MI, unsigned Opcode); 46 47 const SystemZInstrInfo *TII; 48 const TargetRegisterInfo *TRI; 49 LivePhysRegs LiveRegs; 50 }; 51 52 char SystemZShortenInst::ID = 0; 53 } // end anonymous namespace 54 55 FunctionPass *llvm::createSystemZShortenInstPass(SystemZTargetMachine &TM) { 56 return new SystemZShortenInst(TM); 57 } 58 59 SystemZShortenInst::SystemZShortenInst(const SystemZTargetMachine &tm) 60 : MachineFunctionPass(ID), TII(nullptr) {} 61 62 // MI loads one word of a GPR using an IIxF instruction and LLIxL and LLIxH 63 // are the halfword immediate loads for the same word. Try to use one of them 64 // instead of IIxF. 65 bool SystemZShortenInst::shortenIIF(MachineInstr &MI, 66 unsigned LLIxL, unsigned LLIxH) { 67 unsigned Reg = MI.getOperand(0).getReg(); 68 // The new opcode will clear the other half of the GR64 reg, so 69 // cancel if that is live. 70 unsigned thisSubRegIdx = (SystemZ::GRH32BitRegClass.contains(Reg) ? 71 SystemZ::subreg_h32 : SystemZ::subreg_l32); 72 unsigned otherSubRegIdx = (thisSubRegIdx == SystemZ::subreg_l32 ? 73 SystemZ::subreg_h32 : SystemZ::subreg_l32); 74 unsigned GR64BitReg = TRI->getMatchingSuperReg(Reg, thisSubRegIdx, 75 &SystemZ::GR64BitRegClass); 76 unsigned OtherReg = TRI->getSubReg(GR64BitReg, otherSubRegIdx); 77 if (LiveRegs.contains(OtherReg)) 78 return false; 79 80 uint64_t Imm = MI.getOperand(1).getImm(); 81 if (SystemZ::isImmLL(Imm)) { 82 MI.setDesc(TII->get(LLIxL)); 83 MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg)); 84 return true; 85 } 86 if (SystemZ::isImmLH(Imm)) { 87 MI.setDesc(TII->get(LLIxH)); 88 MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg)); 89 MI.getOperand(1).setImm(Imm >> 16); 90 return true; 91 } 92 return false; 93 } 94 95 // Change MI's opcode to Opcode if register operand 0 has a 4-bit encoding. 96 bool SystemZShortenInst::shortenOn0(MachineInstr &MI, unsigned Opcode) { 97 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16) { 98 MI.setDesc(TII->get(Opcode)); 99 return true; 100 } 101 return false; 102 } 103 104 // Change MI's opcode to Opcode if register operands 0 and 1 have a 105 // 4-bit encoding. 106 bool SystemZShortenInst::shortenOn01(MachineInstr &MI, unsigned Opcode) { 107 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 && 108 SystemZMC::getFirstReg(MI.getOperand(1).getReg()) < 16) { 109 MI.setDesc(TII->get(Opcode)); 110 return true; 111 } 112 return false; 113 } 114 115 // Change MI's opcode to Opcode if register operands 0, 1 and 2 have a 116 // 4-bit encoding and if operands 0 and 1 are tied. 117 bool SystemZShortenInst::shortenOn001(MachineInstr &MI, unsigned Opcode) { 118 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 && 119 MI.getOperand(1).getReg() == MI.getOperand(0).getReg() && 120 SystemZMC::getFirstReg(MI.getOperand(2).getReg()) < 16) { 121 MI.setDesc(TII->get(Opcode)); 122 return true; 123 } 124 return false; 125 } 126 127 // Calls shortenOn001 if CCLive is false. CC def operand is added in 128 // case of success. 129 bool SystemZShortenInst::shortenOn001AddCC(MachineInstr &MI, 130 unsigned Opcode) { 131 if (!LiveRegs.contains(SystemZ::CC) && shortenOn001(MI, Opcode)) { 132 MachineInstrBuilder(*MI.getParent()->getParent(), &MI) 133 .addReg(SystemZ::CC, RegState::ImplicitDefine); 134 return true; 135 } 136 return false; 137 } 138 139 // MI is a vector-style conversion instruction with the operand order: 140 // destination, source, exact-suppress, rounding-mode. If both registers 141 // have a 4-bit encoding then change it to Opcode, which has operand order: 142 // destination, rouding-mode, source, exact-suppress. 143 bool SystemZShortenInst::shortenFPConv(MachineInstr &MI, unsigned Opcode) { 144 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 && 145 SystemZMC::getFirstReg(MI.getOperand(1).getReg()) < 16) { 146 MachineOperand Dest(MI.getOperand(0)); 147 MachineOperand Src(MI.getOperand(1)); 148 MachineOperand Suppress(MI.getOperand(2)); 149 MachineOperand Mode(MI.getOperand(3)); 150 MI.RemoveOperand(3); 151 MI.RemoveOperand(2); 152 MI.RemoveOperand(1); 153 MI.RemoveOperand(0); 154 MI.setDesc(TII->get(Opcode)); 155 MachineInstrBuilder(*MI.getParent()->getParent(), &MI) 156 .addOperand(Dest) 157 .addOperand(Mode) 158 .addOperand(Src) 159 .addOperand(Suppress); 160 return true; 161 } 162 return false; 163 } 164 165 // Process all instructions in MBB. Return true if something changed. 166 bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) { 167 bool Changed = false; 168 169 // Set up the set of live registers at the end of MBB (live out) 170 LiveRegs.clear(); 171 LiveRegs.addLiveOuts(&MBB); 172 173 // Iterate backwards through the block looking for instructions to change. 174 for (auto MBBI = MBB.rbegin(), MBBE = MBB.rend(); MBBI != MBBE; ++MBBI) { 175 MachineInstr &MI = *MBBI; 176 switch (MI.getOpcode()) { 177 case SystemZ::IILF: 178 Changed |= shortenIIF(MI, SystemZ::LLILL, SystemZ::LLILH); 179 break; 180 181 case SystemZ::IIHF: 182 Changed |= shortenIIF(MI, SystemZ::LLIHL, SystemZ::LLIHH); 183 break; 184 185 case SystemZ::WFADB: 186 Changed |= shortenOn001AddCC(MI, SystemZ::ADBR); 187 break; 188 189 case SystemZ::WFDDB: 190 Changed |= shortenOn001(MI, SystemZ::DDBR); 191 break; 192 193 case SystemZ::WFIDB: 194 Changed |= shortenFPConv(MI, SystemZ::FIDBRA); 195 break; 196 197 case SystemZ::WLDEB: 198 Changed |= shortenOn01(MI, SystemZ::LDEBR); 199 break; 200 201 case SystemZ::WLEDB: 202 Changed |= shortenFPConv(MI, SystemZ::LEDBRA); 203 break; 204 205 case SystemZ::WFMDB: 206 Changed |= shortenOn001(MI, SystemZ::MDBR); 207 break; 208 209 case SystemZ::WFLCDB: 210 Changed |= shortenOn01(MI, SystemZ::LCDFR); 211 break; 212 213 case SystemZ::WFLNDB: 214 Changed |= shortenOn01(MI, SystemZ::LNDFR); 215 break; 216 217 case SystemZ::WFLPDB: 218 Changed |= shortenOn01(MI, SystemZ::LPDFR); 219 break; 220 221 case SystemZ::WFSQDB: 222 Changed |= shortenOn01(MI, SystemZ::SQDBR); 223 break; 224 225 case SystemZ::WFSDB: 226 Changed |= shortenOn001AddCC(MI, SystemZ::SDBR); 227 break; 228 229 case SystemZ::WFCDB: 230 Changed |= shortenOn01(MI, SystemZ::CDBR); 231 break; 232 233 case SystemZ::VL32: 234 // For z13 we prefer LDE over LE to avoid partial register dependencies. 235 Changed |= shortenOn0(MI, SystemZ::LDE32); 236 break; 237 238 case SystemZ::VST32: 239 Changed |= shortenOn0(MI, SystemZ::STE); 240 break; 241 242 case SystemZ::VL64: 243 Changed |= shortenOn0(MI, SystemZ::LD); 244 break; 245 246 case SystemZ::VST64: 247 Changed |= shortenOn0(MI, SystemZ::STD); 248 break; 249 } 250 251 LiveRegs.stepBackward(MI); 252 } 253 254 return Changed; 255 } 256 257 bool SystemZShortenInst::runOnMachineFunction(MachineFunction &F) { 258 const SystemZSubtarget &ST = F.getSubtarget<SystemZSubtarget>(); 259 TII = ST.getInstrInfo(); 260 TRI = ST.getRegisterInfo(); 261 LiveRegs.init(TRI); 262 263 bool Changed = false; 264 for (auto &MBB : F) 265 Changed |= processBlock(MBB); 266 267 return Changed; 268 } 269