// $Id: loopAnalyzer.java,v 1.5 2001/01/11 10:12:45 msato Exp $
// $RWC_Release: Omni-1.6 $
// $RWC_Copyright:
//  Omni Compiler Software Version 1.5-1.6
//  Copyright (C) 2002 PC Cluster Consortium
//  
//  This software is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License version
//  2.1 published by the Free Software Foundation.
//  
//  Omni Compiler Software Version 1.0-1.4
//  Copyright (C) 1999, 2000, 2001.
//   Tsukuba Research Center, Real World Computing Partnership, Japan.
//  
//  Please check the Copyright and License information in the files named
//  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
//  Software release kit.
//  
//  
//  $
package exc.flow;

import exc.object.*;
import exc.block.*;
import exc.openmp.*;

import java.util.Vector;

public class loopAnalyzer {
  public static boolean debugFlag;

  final static String loopProp = "loopAnalyzer.loopInfo";
  optBodyEnv optEnv;

  // find optimizable loops and mark it.
  // Put Property "loopProp" with loopInfo at Loop landing_pad.
  public void run(optBodyEnv env){
    optEnv = env;

    ControlFlowGraph cfg = optEnv.getCFG();
    for(BasicBlock bb = cfg.getHead(); bb != null; bb = bb.topNext()){

      if(bb.getParent().Opcode() == Xcode.OMP_FORALL &&
	 bb.getParent().getBasicBlock() == bb){
	/* check the head of OMP_FORALL block */
	bb.setProp(loopProp,
		   new forallInfo(optEnv,(OMPforallBlock)bb.getParent()));
	continue;
      }

      /* find backedge */
      Vector out_edges = bb.getCflowOut();
      for(int i = 0; i < out_edges.size(); i++){
	BasicBlock bp = (BasicBlock)out_edges.elementAt(i);
	if(bp.DFN() <= bb.DFN()) checkLoop(bp,bb);
      }
    }
  }

  /* check optimizable loop:
   * (1) single entry / single exit. 
   * (2) single landing pad
   * (3) single flow in exit block.
   */
  void checkLoop(BasicBlock header, BasicBlock tail){
    BasicBlock bb,exit_bb;

    if(debugFlag) System.out.println("checkLoop["+header+","+tail+"]");

    /* check single landing pad */
    if(header.getCflowIn().size() != 2){
      if(debugFlag) System.out.println("fail, header In != 2");
      return;
    }
      
    /* mark all loop block */
    ControlFlowGraph cfg = optEnv.getCFG();
    for(bb = cfg.getHead(); bb != null; bb = bb.topNext()) bb.resetMark();
    header.setMark();
    backwardMarkBasicBlock(tail);

    /* find exit basic block */
    exit_bb = null;
    for(bb = header; ; bb = bb.topNext()){
      if(!bb.isMarked()) break;
      Vector out_edges = bb.getCflowOut();
      for(int i = 0; i < out_edges.size(); i++){
	BasicBlock bp = (BasicBlock)out_edges.elementAt(i);
	if(!bp.isMarked()){
	  if(exit_bb != null){
	    if(debugFlag) System.out.println("fail, #exit > 1");
	    return; /* fail */
	  }
	  exit_bb = bp;
	}
      }
      if(bb == tail) break;
    }
    if(exit_bb == null
       || exit_bb.getCflowIn() == null
       || exit_bb.getCflowIn().size() != 1){
      if(debugFlag) System.out.println("fail, exit #In != 1");
      return;
    }

    BasicBlock landing_pad = header.getCflowIn(0);

    if(landing_pad.getCflowOut().size() != 1){
      if(debugFlag) System.out.println("fail, exit #Out != 1");
      return;
    }
      
    if(landing_pad.isMarked()){
       if(debugFlag) System.out.println("fail, landing_pad marked");
      return;
    }

    landing_pad.setProp(loopProp,
			new loopInfo(optEnv,header,tail,landing_pad,exit_bb));

    if(debugFlag) 
      System.out.println("success! landing_pad="+landing_pad+
			  ", exit_pad"+exit_bb);
  }

  void backwardMarkBasicBlock(BasicBlock bb){
    if(bb.isMarked()) return;
    bb.setMark();
    Vector in_edges = bb.getCflowIn();
    for(int i = 0; i < in_edges.size(); i++)
      backwardMarkBasicBlock((BasicBlock)in_edges.elementAt(i));
  }

  /*
   * Call visitor.
   */
  public void topdownVisit(loopVisitor visitor){
    ControlFlowGraph cfg = optEnv.getCFG();
    for(BasicBlock bb = cfg.getHead(); bb != null; bb = bb.topNext()){
      loopInfo info = (loopInfo)bb.getProp(loopProp);
      if(info != null){
	visitor.visitLoop(info);
      }
    }
  }

  public void bottomupVisit(loopVisitor visitor){
    ControlFlowGraph cfg = optEnv.getCFG();
    for(BasicBlock bb = cfg.getTail(); bb != null; bb = bb.topPrev()){
      loopInfo info = (loopInfo)bb.getProp(loopProp);
      if(info != null){
	visitor.visitLoop(info);
      }
    }
  }

  public static loopInfo getLoopInfo(BasicBlock bb){
    return (loopInfo)bb.getProp(loopProp);
  }
}


