LLVM API Documentation

IA64Bundling.cpp

Go to the documentation of this file.
00001 //===-- IA64Bundling.cpp - IA-64 instruction bundling 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 // Add stops where required to prevent read-after-write and write-after-write
00011 // dependencies, for both registers and memory addresses. There are exceptions:
00012 //
00013 //    - Compare instructions (cmp*, tbit, tnat, fcmp, frcpa) are OK with
00014 //      WAW dependencies so long as they all target p0, or are of parallel
00015 //      type (.and*/.or*)
00016 //
00017 // FIXME: bundling, for now, is left to the assembler.
00018 // FIXME: this might be an appropriate place to translate between different
00019 //        instructions that do the same thing, if this helps bundling.
00020 // 
00021 //===----------------------------------------------------------------------===//
00022 
00023 #define DEBUG_TYPE "ia64-codegen"
00024 #include "IA64.h"
00025 #include "IA64InstrInfo.h"
00026 #include "IA64TargetMachine.h"
00027 #include "llvm/CodeGen/MachineFunctionPass.h"
00028 #include "llvm/CodeGen/MachineInstrBuilder.h"
00029 #include "llvm/ADT/SetOperations.h"
00030 #include "llvm/ADT/Statistic.h"
00031 #include "llvm/Support/Debug.h"
00032 #include <set>
00033 using namespace llvm;
00034 
00035 STATISTIC(StopBitsAdded, "Number of stop bits added");
00036 
00037 namespace {
00038   struct IA64BundlingPass : public MachineFunctionPass {
00039     static char ID;
00040     /// Target machine description which we query for reg. names, data
00041     /// layout, etc.
00042     ///
00043     IA64TargetMachine &TM;
00044 
00045     IA64BundlingPass(IA64TargetMachine &tm) 
00046       : MachineFunctionPass(&ID), TM(tm) { }
00047 
00048     virtual const char *getPassName() const {
00049       return "IA64 (Itanium) Bundling Pass";
00050     }
00051 
00052     bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
00053     bool runOnMachineFunction(MachineFunction &F) {
00054       bool Changed = false;
00055       for (MachineFunction::iterator FI = F.begin(), FE = F.end();
00056            FI != FE; ++FI)
00057         Changed |= runOnMachineBasicBlock(*FI);
00058       return Changed;
00059     }
00060 
00061     // XXX: ugly global, but pending writes can cross basic blocks. Note that
00062     // taken branches end instruction groups. So we only need to worry about
00063     // 'fallthrough' code
00064     std::set<unsigned> PendingRegWrites;
00065   };
00066   char IA64BundlingPass::ID = 0;
00067 } // end of anonymous namespace
00068 
00069 /// createIA64BundlingPass - Returns a pass that adds STOP (;;) instructions
00070 /// and arranges the result into bundles.
00071 ///
00072 FunctionPass *llvm::createIA64BundlingPass(IA64TargetMachine &tm) {
00073   return new IA64BundlingPass(tm);
00074 }
00075 
00076 /// runOnMachineBasicBlock - add stops and bundle this MBB.
00077 ///
00078 bool IA64BundlingPass::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
00079   bool Changed = false;
00080 
00081   for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
00082     MachineInstr *CurrentInsn = I++;
00083     std::set<unsigned> CurrentReads, CurrentWrites, OrigWrites;
00084 
00085     for(unsigned i=0; i < CurrentInsn->getNumOperands(); i++) {
00086       MachineOperand &MO=CurrentInsn->getOperand(i);
00087       if (MO.isReg()) {
00088         if(MO.isUse()) { // TODO: exclude p0
00089           CurrentReads.insert(MO.getReg());
00090         }
00091         if(MO.isDef()) { // TODO: exclude p0
00092           CurrentWrites.insert(MO.getReg());
00093           OrigWrites.insert(MO.getReg()); // FIXME: use a nondestructive
00094                                           // set_intersect instead?
00095         }
00096       }
00097     }
00098     
00099     // CurrentReads/CurrentWrites contain info for the current instruction.
00100     // Does it read or write any registers that are pending a write?
00101     // (i.e. not separated by a stop)
00102     set_intersect(CurrentReads, PendingRegWrites);
00103     set_intersect(CurrentWrites, PendingRegWrites);
00104     
00105     if(! (CurrentReads.empty() && CurrentWrites.empty()) ) {
00106       // there is a conflict, insert a stop and reset PendingRegWrites
00107       CurrentInsn = BuildMI(MBB, CurrentInsn,
00108                             TM.getInstrInfo()->get(IA64::STOP), 0);
00109       PendingRegWrites=OrigWrites; // carry over current writes to next insn
00110       Changed=true; StopBitsAdded++; // update stats      
00111     } else { // otherwise, track additional pending writes
00112       set_union(PendingRegWrites, OrigWrites);
00113     }
00114   } // onto the next insn in the MBB
00115 
00116   return Changed;
00117 }
00118