LLVM API Documentation
00001 //===-- SystemZShortenInst.cpp - Instruction-shortening pass --------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass tries to replace instructions with shorter forms. For example, 00011 // IILF can be replaced with LLILL or LLILH if the constant fits and if the 00012 // other 32 bits of the GR64 destination are not live. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "SystemZTargetMachine.h" 00017 #include "llvm/CodeGen/MachineFunctionPass.h" 00018 00019 using namespace llvm; 00020 00021 #define DEBUG_TYPE "systemz-shorten-inst" 00022 00023 namespace { 00024 class SystemZShortenInst : public MachineFunctionPass { 00025 public: 00026 static char ID; 00027 SystemZShortenInst(const SystemZTargetMachine &tm); 00028 00029 const char *getPassName() const override { 00030 return "SystemZ Instruction Shortening"; 00031 } 00032 00033 bool processBlock(MachineBasicBlock &MBB); 00034 bool runOnMachineFunction(MachineFunction &F) override; 00035 00036 private: 00037 bool shortenIIF(MachineInstr &MI, unsigned *GPRMap, unsigned LiveOther, 00038 unsigned LLIxL, unsigned LLIxH); 00039 00040 const SystemZInstrInfo *TII; 00041 00042 // LowGPRs[I] has bit N set if LLVM register I includes the low 00043 // word of GPR N. HighGPRs is the same for the high word. 00044 unsigned LowGPRs[SystemZ::NUM_TARGET_REGS]; 00045 unsigned HighGPRs[SystemZ::NUM_TARGET_REGS]; 00046 }; 00047 00048 char SystemZShortenInst::ID = 0; 00049 } // end anonymous namespace 00050 00051 FunctionPass *llvm::createSystemZShortenInstPass(SystemZTargetMachine &TM) { 00052 return new SystemZShortenInst(TM); 00053 } 00054 00055 SystemZShortenInst::SystemZShortenInst(const SystemZTargetMachine &tm) 00056 : MachineFunctionPass(ID), TII(nullptr), LowGPRs(), HighGPRs() { 00057 // Set up LowGPRs and HighGPRs. 00058 for (unsigned I = 0; I < 16; ++I) { 00059 LowGPRs[SystemZMC::GR32Regs[I]] |= 1 << I; 00060 LowGPRs[SystemZMC::GR64Regs[I]] |= 1 << I; 00061 HighGPRs[SystemZMC::GRH32Regs[I]] |= 1 << I; 00062 HighGPRs[SystemZMC::GR64Regs[I]] |= 1 << I; 00063 if (unsigned GR128 = SystemZMC::GR128Regs[I]) { 00064 LowGPRs[GR128] |= 3 << I; 00065 HighGPRs[GR128] |= 3 << I; 00066 } 00067 } 00068 } 00069 00070 // MI loads one word of a GPR using an IIxF instruction and LLIxL and LLIxH 00071 // are the halfword immediate loads for the same word. Try to use one of them 00072 // instead of IIxF. If MI loads the high word, GPRMap[X] is the set of high 00073 // words referenced by LLVM register X while LiveOther is the mask of low 00074 // words that are currently live, and vice versa. 00075 bool SystemZShortenInst::shortenIIF(MachineInstr &MI, unsigned *GPRMap, 00076 unsigned LiveOther, unsigned LLIxL, 00077 unsigned LLIxH) { 00078 unsigned Reg = MI.getOperand(0).getReg(); 00079 assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number"); 00080 unsigned GPRs = GPRMap[Reg]; 00081 assert(GPRs != 0 && "Register must be a GPR"); 00082 if (GPRs & LiveOther) 00083 return false; 00084 00085 uint64_t Imm = MI.getOperand(1).getImm(); 00086 if (SystemZ::isImmLL(Imm)) { 00087 MI.setDesc(TII->get(LLIxL)); 00088 MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg)); 00089 return true; 00090 } 00091 if (SystemZ::isImmLH(Imm)) { 00092 MI.setDesc(TII->get(LLIxH)); 00093 MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg)); 00094 MI.getOperand(1).setImm(Imm >> 16); 00095 return true; 00096 } 00097 return false; 00098 } 00099 00100 // Process all instructions in MBB. Return true if something changed. 00101 bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) { 00102 bool Changed = false; 00103 00104 // Work out which words are live on exit from the block. 00105 unsigned LiveLow = 0; 00106 unsigned LiveHigh = 0; 00107 for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) { 00108 for (auto LI = (*SI)->livein_begin(), LE = (*SI)->livein_end(); 00109 LI != LE; ++LI) { 00110 unsigned Reg = *LI; 00111 assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number"); 00112 LiveLow |= LowGPRs[Reg]; 00113 LiveHigh |= HighGPRs[Reg]; 00114 } 00115 } 00116 00117 // Iterate backwards through the block looking for instructions to change. 00118 for (auto MBBI = MBB.rbegin(), MBBE = MBB.rend(); MBBI != MBBE; ++MBBI) { 00119 MachineInstr &MI = *MBBI; 00120 unsigned Opcode = MI.getOpcode(); 00121 if (Opcode == SystemZ::IILF) 00122 Changed |= shortenIIF(MI, LowGPRs, LiveHigh, SystemZ::LLILL, 00123 SystemZ::LLILH); 00124 else if (Opcode == SystemZ::IIHF) 00125 Changed |= shortenIIF(MI, HighGPRs, LiveLow, SystemZ::LLIHL, 00126 SystemZ::LLIHH); 00127 unsigned UsedLow = 0; 00128 unsigned UsedHigh = 0; 00129 for (auto MOI = MI.operands_begin(), MOE = MI.operands_end(); 00130 MOI != MOE; ++MOI) { 00131 MachineOperand &MO = *MOI; 00132 if (MO.isReg()) { 00133 if (unsigned Reg = MO.getReg()) { 00134 assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number"); 00135 if (MO.isDef()) { 00136 LiveLow &= ~LowGPRs[Reg]; 00137 LiveHigh &= ~HighGPRs[Reg]; 00138 } else if (!MO.isUndef()) { 00139 UsedLow |= LowGPRs[Reg]; 00140 UsedHigh |= HighGPRs[Reg]; 00141 } 00142 } 00143 } 00144 } 00145 LiveLow |= UsedLow; 00146 LiveHigh |= UsedHigh; 00147 } 00148 00149 return Changed; 00150 } 00151 00152 bool SystemZShortenInst::runOnMachineFunction(MachineFunction &F) { 00153 TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo()); 00154 00155 bool Changed = false; 00156 for (auto &MBB : F) 00157 Changed |= processBlock(MBB); 00158 00159 return Changed; 00160 }