LLVM API Documentation

SystemZShortenInst.cpp
Go to the documentation of this file.
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 }