Home | History | Annotate | Download | only in SystemZ
      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 
     19 using namespace llvm;
     20 
     21 #define DEBUG_TYPE "systemz-shorten-inst"
     22 
     23 namespace {
     24 class SystemZShortenInst : public MachineFunctionPass {
     25 public:
     26   static char ID;
     27   SystemZShortenInst(const SystemZTargetMachine &tm);
     28 
     29   const char *getPassName() const override {
     30     return "SystemZ Instruction Shortening";
     31   }
     32 
     33   bool processBlock(MachineBasicBlock &MBB);
     34   bool runOnMachineFunction(MachineFunction &F) override;
     35 
     36 private:
     37   bool shortenIIF(MachineInstr &MI, unsigned *GPRMap, unsigned LiveOther,
     38                   unsigned LLIxL, unsigned LLIxH);
     39 
     40   const SystemZInstrInfo *TII;
     41 
     42   // LowGPRs[I] has bit N set if LLVM register I includes the low
     43   // word of GPR N.  HighGPRs is the same for the high word.
     44   unsigned LowGPRs[SystemZ::NUM_TARGET_REGS];
     45   unsigned HighGPRs[SystemZ::NUM_TARGET_REGS];
     46 };
     47 
     48 char SystemZShortenInst::ID = 0;
     49 } // end anonymous namespace
     50 
     51 FunctionPass *llvm::createSystemZShortenInstPass(SystemZTargetMachine &TM) {
     52   return new SystemZShortenInst(TM);
     53 }
     54 
     55 SystemZShortenInst::SystemZShortenInst(const SystemZTargetMachine &tm)
     56   : MachineFunctionPass(ID), TII(nullptr), LowGPRs(), HighGPRs() {
     57   // Set up LowGPRs and HighGPRs.
     58   for (unsigned I = 0; I < 16; ++I) {
     59     LowGPRs[SystemZMC::GR32Regs[I]] |= 1 << I;
     60     LowGPRs[SystemZMC::GR64Regs[I]] |= 1 << I;
     61     HighGPRs[SystemZMC::GRH32Regs[I]] |= 1 << I;
     62     HighGPRs[SystemZMC::GR64Regs[I]] |= 1 << I;
     63     if (unsigned GR128 = SystemZMC::GR128Regs[I]) {
     64       LowGPRs[GR128] |= 3 << I;
     65       HighGPRs[GR128] |= 3 << I;
     66     }
     67   }
     68 }
     69 
     70 // MI loads one word of a GPR using an IIxF instruction and LLIxL and LLIxH
     71 // are the halfword immediate loads for the same word.  Try to use one of them
     72 // instead of IIxF.  If MI loads the high word, GPRMap[X] is the set of high
     73 // words referenced by LLVM register X while LiveOther is the mask of low
     74 // words that are currently live, and vice versa.
     75 bool SystemZShortenInst::shortenIIF(MachineInstr &MI, unsigned *GPRMap,
     76                                     unsigned LiveOther, unsigned LLIxL,
     77                                     unsigned LLIxH) {
     78   unsigned Reg = MI.getOperand(0).getReg();
     79   assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number");
     80   unsigned GPRs = GPRMap[Reg];
     81   assert(GPRs != 0 && "Register must be a GPR");
     82   if (GPRs & LiveOther)
     83     return false;
     84 
     85   uint64_t Imm = MI.getOperand(1).getImm();
     86   if (SystemZ::isImmLL(Imm)) {
     87     MI.setDesc(TII->get(LLIxL));
     88     MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg));
     89     return true;
     90   }
     91   if (SystemZ::isImmLH(Imm)) {
     92     MI.setDesc(TII->get(LLIxH));
     93     MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg));
     94     MI.getOperand(1).setImm(Imm >> 16);
     95     return true;
     96   }
     97   return false;
     98 }
     99 
    100 // Process all instructions in MBB.  Return true if something changed.
    101 bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) {
    102   bool Changed = false;
    103 
    104   // Work out which words are live on exit from the block.
    105   unsigned LiveLow = 0;
    106   unsigned LiveHigh = 0;
    107   for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) {
    108     for (auto LI = (*SI)->livein_begin(), LE = (*SI)->livein_end();
    109          LI != LE; ++LI) {
    110       unsigned Reg = *LI;
    111       assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number");
    112       LiveLow |= LowGPRs[Reg];
    113       LiveHigh |= HighGPRs[Reg];
    114     }
    115   }
    116 
    117   // Iterate backwards through the block looking for instructions to change.
    118   for (auto MBBI = MBB.rbegin(), MBBE = MBB.rend(); MBBI != MBBE; ++MBBI) {
    119     MachineInstr &MI = *MBBI;
    120     unsigned Opcode = MI.getOpcode();
    121     if (Opcode == SystemZ::IILF)
    122       Changed |= shortenIIF(MI, LowGPRs, LiveHigh, SystemZ::LLILL,
    123                             SystemZ::LLILH);
    124     else if (Opcode == SystemZ::IIHF)
    125       Changed |= shortenIIF(MI, HighGPRs, LiveLow, SystemZ::LLIHL,
    126                             SystemZ::LLIHH);
    127     unsigned UsedLow = 0;
    128     unsigned UsedHigh = 0;
    129     for (auto MOI = MI.operands_begin(), MOE = MI.operands_end();
    130          MOI != MOE; ++MOI) {
    131       MachineOperand &MO = *MOI;
    132       if (MO.isReg()) {
    133         if (unsigned Reg = MO.getReg()) {
    134           assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number");
    135           if (MO.isDef()) {
    136             LiveLow &= ~LowGPRs[Reg];
    137             LiveHigh &= ~HighGPRs[Reg];
    138           } else if (!MO.isUndef()) {
    139             UsedLow |= LowGPRs[Reg];
    140             UsedHigh |= HighGPRs[Reg];
    141           }
    142         }
    143       }
    144     }
    145     LiveLow |= UsedLow;
    146     LiveHigh |= UsedHigh;
    147   }
    148 
    149   return Changed;
    150 }
    151 
    152 bool SystemZShortenInst::runOnMachineFunction(MachineFunction &F) {
    153   TII = static_cast<const SystemZInstrInfo *>(F.getTarget().getInstrInfo());
    154 
    155   bool Changed = false;
    156   for (auto &MBB : F)
    157     Changed |= processBlock(MBB);
    158 
    159   return Changed;
    160 }
    161