//===-- SPUNopFiller.cpp - Add nops/lnops to align the pipelines---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The final pass just before assembly printing. This pass is the last
// checkpoint where nops and lnops are added to the instruction stream to 
// satisfy the dual issue requirements. The actual dual issue scheduling is 
// done (TODO: nowhere, currently)
//
//===----------------------------------------------------------------------===//

#include "SPU.h"
#include "SPUTargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
  struct SPUNopFiller : public MachineFunctionPass {

    TargetMachine &TM;
    const TargetInstrInfo *TII;
    const InstrItineraryData *IID;
    bool isEvenPlace;  // the instruction slot (mem address) at hand is even/odd

    static char ID;
    SPUNopFiller(TargetMachine &tm) 
      : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()), 
        IID(tm.getInstrItineraryData()) 
    {
      DEBUG( dbgs() << "********** SPU Nop filler **********\n" ; );
    }

    virtual const char *getPassName() const {
      return "SPU nop/lnop Filler";
    }

    void runOnMachineBasicBlock(MachineBasicBlock &MBB);

    bool runOnMachineFunction(MachineFunction &F) {
      isEvenPlace = true; //all functions get an .align 3 directive at start 
      for (MachineFunction::iterator FI = F.begin(), FE = F.end();
           FI != FE; ++FI)
        runOnMachineBasicBlock(*FI);
      return true; //never-ever do any more modifications, just print it!
    }

    typedef enum { none   = 0, // no more instructions in this function / BB
                   pseudo = 1, // this does not get executed
                   even   = 2, 
                   odd    = 3 } SPUOpPlace;
    SPUOpPlace getOpPlacement( MachineInstr &instr );

  };
  char SPUNopFiller::ID = 0;

} 

// Fill a BasicBlock to alignment. 
// In the assebly we align the functions to 'even' adresses, but
// basic blocks have an implicit alignmnet. We hereby define 
// basic blocks to have the same, even, alignment.
void SPUNopFiller::
runOnMachineBasicBlock(MachineBasicBlock &MBB) 
{
  assert( isEvenPlace && "basic block start from odd address");
  for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
  {
    SPUOpPlace this_optype, next_optype;
    MachineBasicBlock::iterator J = I;
    J++;

    this_optype = getOpPlacement( *I );
    next_optype = none;
    while (J!=MBB.end()){
      next_optype = getOpPlacement( *J );
      ++J;
      if (next_optype != pseudo ) 
        break;
    }

    // padd: odd(wrong), even(wrong), ...
    // to:   nop(corr), odd(corr), even(corr)...
    if( isEvenPlace && this_optype == odd && next_optype == even ) {
      DEBUG( dbgs() <<"Adding NOP before: "; );
      DEBUG( I->dump(); );
      BuildMI(MBB, I, I->getDebugLoc(), TII->get(SPU::ENOP));
      isEvenPlace=false;
    }
    
    // padd: even(wrong), odd(wrong), ...
    // to:   lnop(corr), even(corr), odd(corr)...
    else if ( !isEvenPlace && this_optype == even && next_optype == odd){
      DEBUG( dbgs() <<"Adding LNOP before: "; );
      DEBUG( I->dump(); );
      BuildMI(MBB, I, I->getDebugLoc(), TII->get(SPU::LNOP));
      isEvenPlace=true;
    }
      
    // now go to next mem slot
    if( this_optype != pseudo )
      isEvenPlace = !isEvenPlace;    

  }

  // padd basicblock end
  if( !isEvenPlace ){
    MachineBasicBlock::iterator J = MBB.end();
    J--;
    if (getOpPlacement( *J ) == odd) {
      DEBUG( dbgs() <<"Padding basic block with NOP\n"; );
      BuildMI(MBB, J, J->getDebugLoc(), TII->get(SPU::ENOP));
    }  
    else {
      J++;
      DEBUG( dbgs() <<"Padding basic block with LNOP\n"; );
      BuildMI(MBB, J, DebugLoc(), TII->get(SPU::LNOP));
    }
    isEvenPlace=true;
  }
}

FunctionPass *llvm::createSPUNopFillerPass(SPUTargetMachine &tm) {
  return new SPUNopFiller(tm);
}

// Figure out if 'instr' is executed in the even or odd pipeline
SPUNopFiller::SPUOpPlace 
SPUNopFiller::getOpPlacement( MachineInstr &instr ) {
  int sc = instr.getDesc().getSchedClass();
  const InstrStage *stage = IID->beginStage(sc);
  unsigned FUs = stage->getUnits();
  SPUOpPlace retval;

  switch( FUs ) {
    case 0: retval = pseudo; break;
    case 1: retval = odd;    break;
    case 2: retval = even;   break;
    default: retval= pseudo; 
             assert( false && "got unknown FuncUnit\n");
             break;
  };
  return retval;
}
