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 was developed by Duraid Madina and is distributed under the
00006 // University of Illinois Open Source 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 #include "IA64.h"
00024 #include "llvm/CodeGen/MachineFunctionPass.h"
00025 #include "llvm/CodeGen/MachineInstrBuilder.h"
00026 #include "llvm/ADT/SetOperations.h"
00027 #include "llvm/ADT/Statistic.h"
00028 #include "llvm/Support/Debug.h"
00029 #include <set>
00030 #include <iostream>
00031 using namespace llvm;
00032 
00033 namespace {
00034   Statistic<> StopBitsAdded("ia64-codegen", "Number of stop bits added");
00035 
00036   struct IA64BundlingPass : public MachineFunctionPass {
00037     /// Target machine description which we query for reg. names, data
00038     /// layout, etc.
00039     ///
00040     IA64TargetMachine &TM;
00041 
00042     IA64BundlingPass(IA64TargetMachine &tm) : TM(tm) { }
00043 
00044     virtual const char *getPassName() const {
00045       return "IA64 (Itanium) Bundling Pass";
00046     }
00047 
00048     bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
00049     bool runOnMachineFunction(MachineFunction &F) {
00050       bool Changed = false;
00051       for (MachineFunction::iterator FI = F.begin(), FE = F.end();
00052            FI != FE; ++FI)
00053         Changed |= runOnMachineBasicBlock(*FI);
00054       return Changed;
00055     }
00056 
00057     std::set<unsigned> PendingRegWrites; // XXX: ugly global, but
00058                          // pending writes can cross basic blocks. Note that
00059                          // taken branches end instruction groups. So we
00060        // only need to worry about 'fallthrough' code
00061   };
00062 } // end of anonymous namespace
00063 
00064 /// createIA64BundlingPass - Returns a pass that adds STOP (;;) instructions
00065 /// and arranges the result into bundles.
00066 ///
00067 FunctionPass *llvm::createIA64BundlingPass(IA64TargetMachine &tm) {
00068   return new IA64BundlingPass(tm);
00069 }
00070 
00071 /// runOnMachineBasicBlock - add stops and bundle this MBB.
00072 ///
00073 bool IA64BundlingPass::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
00074   bool Changed = false;
00075 
00076   for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
00077     MachineInstr *CurrentInsn = I++;
00078     std::set<unsigned> CurrentReads, CurrentWrites, OrigWrites;
00079 
00080     for(unsigned i=0; i < CurrentInsn->getNumOperands(); i++) {
00081       MachineOperand &MO=CurrentInsn->getOperand(i);
00082       if(MO.isRegister()) {
00083         if(MO.isUse()) { // TODO: exclude p0
00084           CurrentReads.insert(MO.getReg());
00085         }
00086         if(MO.isDef()) { // TODO: exclude p0
00087           CurrentWrites.insert(MO.getReg());
00088           OrigWrites.insert(MO.getReg()); // FIXME: use a nondestructive
00089                                           // set_intersect instead?
00090         }
00091       }
00092     }
00093     
00094     // CurrentReads/CurrentWrites contain info for the current instruction.
00095     // Does it read or write any registers that are pending a write?
00096     // (i.e. not separated by a stop)
00097     set_intersect(CurrentReads, PendingRegWrites);
00098     set_intersect(CurrentWrites, PendingRegWrites);
00099     
00100     if(! (CurrentReads.empty() && CurrentWrites.empty()) ) {
00101       // there is a conflict, insert a stop and reset PendingRegWrites
00102       CurrentInsn = BuildMI(MBB, CurrentInsn, IA64::STOP, 0);
00103       PendingRegWrites=OrigWrites; // carry over current writes to next insn
00104       Changed=true; StopBitsAdded++; // update stats      
00105     } else { // otherwise, track additional pending writes
00106       set_union(PendingRegWrites, OrigWrites);
00107     }
00108   } // onto the next insn in the MBB
00109 
00110   return Changed;
00111 }
00112