LLVM API Documentation

AlphaLLRP.cpp

Go to the documentation of this file.
00001 //===-- AlphaLLRP.cpp - Alpha Load Load Replay Trap elimination 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 // Here we check for potential replay traps introduced by the spiller
00011 // We also align some branch targets if we can do so for free.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #define DEBUG_TYPE "alpha-nops"
00016 #include "Alpha.h"
00017 #include "llvm/CodeGen/MachineFunctionPass.h"
00018 #include "llvm/CodeGen/MachineInstrBuilder.h"
00019 #include "llvm/Target/TargetMachine.h"
00020 #include "llvm/Target/TargetInstrInfo.h"
00021 #include "llvm/ADT/SetOperations.h"
00022 #include "llvm/ADT/Statistic.h"
00023 #include "llvm/Support/CommandLine.h"
00024 using namespace llvm;
00025 
00026 STATISTIC(nopintro, "Number of nops inserted");
00027 STATISTIC(nopalign, "Number of nops inserted for alignment");
00028 
00029 namespace {
00030   cl::opt<bool>
00031   AlignAll("alpha-align-all", cl::Hidden,
00032                    cl::desc("Align all blocks"));
00033 
00034   struct AlphaLLRPPass : public MachineFunctionPass {
00035     /// Target machine description which we query for reg. names, data
00036     /// layout, etc.
00037     ///
00038     AlphaTargetMachine &TM;
00039 
00040     static char ID;
00041     AlphaLLRPPass(AlphaTargetMachine &tm) 
00042       : MachineFunctionPass(&ID), TM(tm) { }
00043 
00044     virtual const char *getPassName() const {
00045       return "Alpha NOP inserter";
00046     }
00047 
00048     bool runOnMachineFunction(MachineFunction &F) {
00049       const TargetInstrInfo *TII = F.getTarget().getInstrInfo();
00050       bool Changed = false;
00051       MachineInstr* prev[3] = {0,0,0};
00052       unsigned count = 0;
00053       for (MachineFunction::iterator FI = F.begin(), FE = F.end();
00054            FI != FE; ++FI) {
00055         MachineBasicBlock& MBB = *FI;
00056         bool ub = false;
00057         for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
00058           if (count%4 == 0)
00059             prev[0] = prev[1] = prev[2] = 0; //Slots cleared at fetch boundary
00060           ++count;
00061           MachineInstr *MI = I++;
00062           switch (MI->getOpcode()) {
00063           case Alpha::LDQ:  case Alpha::LDL:
00064           case Alpha::LDWU: case Alpha::LDBU:
00065           case Alpha::LDT: case Alpha::LDS:
00066           case Alpha::STQ:  case Alpha::STL:
00067           case Alpha::STW:  case Alpha::STB:
00068           case Alpha::STT: case Alpha::STS:
00069            if (MI->getOperand(2).getReg() == Alpha::R30) {
00070              if (prev[0] && 
00071                  prev[0]->getOperand(2).getReg() == MI->getOperand(2).getReg()&&
00072                  prev[0]->getOperand(1).getImm() == MI->getOperand(1).getImm()){
00073                prev[0] = prev[1];
00074                prev[1] = prev[2];
00075                prev[2] = 0;
00076                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
00077                  .addReg(Alpha::R31)
00078                  .addReg(Alpha::R31); 
00079                Changed = true; nopintro += 1;
00080                count += 1;
00081              } else if (prev[1] 
00082                         && prev[1]->getOperand(2).getReg() == 
00083                         MI->getOperand(2).getReg()
00084                         && prev[1]->getOperand(1).getImm() == 
00085                         MI->getOperand(1).getImm()) {
00086                prev[0] = prev[2];
00087                prev[1] = prev[2] = 0;
00088                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
00089                  .addReg(Alpha::R31)
00090                  .addReg(Alpha::R31); 
00091                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31)
00092                  .addReg(Alpha::R31)
00093                  .addReg(Alpha::R31);
00094                Changed = true; nopintro += 2;
00095                count += 2;
00096              } else if (prev[2] 
00097                         && prev[2]->getOperand(2).getReg() == 
00098                         MI->getOperand(2).getReg()
00099                         && prev[2]->getOperand(1).getImm() == 
00100                         MI->getOperand(1).getImm()) {
00101                prev[0] = prev[1] = prev[2] = 0;
00102                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
00103                  .addReg(Alpha::R31);
00104                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
00105                  .addReg(Alpha::R31);
00106                BuildMI(MBB, MI, TII->get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
00107                  .addReg(Alpha::R31);
00108                Changed = true; nopintro += 3;
00109                count += 3;
00110              }
00111              prev[0] = prev[1];
00112              prev[1] = prev[2];
00113              prev[2] = MI;
00114              break;
00115            }
00116            prev[0] = prev[1];
00117            prev[1] = prev[2];
00118            prev[2] = 0;
00119            break;
00120           case Alpha::ALTENT:
00121           case Alpha::MEMLABEL:
00122           case Alpha::PCLABEL:
00123             --count;
00124             break;
00125           case Alpha::BR:
00126           case Alpha::JMP:
00127             ub = true;
00128             //fall through
00129           default:
00130             prev[0] = prev[1];
00131             prev[1] = prev[2];
00132             prev[2] = 0;
00133             break;
00134           }
00135         }
00136         if (ub || AlignAll) {
00137           //we can align stuff for free at this point
00138           while (count % 4) {
00139             BuildMI(MBB, MBB.end(), TII->get(Alpha::BISr), Alpha::R31)
00140               .addReg(Alpha::R31).addReg(Alpha::R31);
00141             ++count;
00142             ++nopalign;
00143             prev[0] = prev[1];
00144             prev[1] = prev[2];
00145             prev[2] = 0;
00146           }
00147         }
00148       }
00149       return Changed;
00150     }
00151   };
00152   char AlphaLLRPPass::ID = 0;
00153 } // end of anonymous namespace
00154 
00155 FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) {
00156   return new AlphaLLRPPass(tm);
00157 }