// $Id: OMPDtransform.java,v 1.4 2000/12/20 06:16:54 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 ompd;

import java.io.*;
import exc.object.*;
import exc.block.*;
import exc.util.*;
import exc.flow.*;
import exc.openmp.*;

/* 
 * Compiler-based Distributed Shared Memory transformation
 */

public class OMPDtransform implements XobjectDefVisitor
{
  static public boolean debugFlag = true;
  static public boolean optFlag = true;

  BlockPrintWriter debug_out;

  instrumentRW instRW = new instrumentRW();
  mergeRWcheck mergeRW = new mergeRWcheck();

  liveVariableAnalyzer lva;
  SSAtransform SSAtrans;
  loopAnalyzer loop_analyzer;

  public OMPDtransform(){

    if(debugFlag){
      instrumentRW.debugFlag = true;
      loopAnalyzer.debugFlag = true;
      debug_out = new BlockPrintWriter(System.out);
    }

    lva = new liveVariableAnalyzer();
    SSAtrans = new SSAtransform();
    loop_analyzer = new loopAnalyzer();
  }

  public void doDef(XobjectDef d){
    FuncDefBlock fd = new FuncDefBlock(d);

    // find parallel region
    for(BlockIterator bi = new bottomupBlockIterator(fd.getBlock());
	!bi.end(); bi.next()){
      Block b = bi.getBlock();
      if(b.Opcode() == Xcode.OMP_PARALLEL)
	transParallelBlock((OMPparallelBlock)b);
    }
  }

  void transParallelBlock(OMPparallelBlock b){
    optBodyEnv optEnv = new optBodyEnv(b.getBody());
    optEnv.exposeAsgExpr();

    XobjectDecompileWriter.debugOutputFlag = true;

    if(!optFlag){
      optEnv.makeCFG();
      if(debugFlag){
	System.out.println("---------- canonicalizeAsgExpr:");
	debug_out.print(optEnv.getBody());
      }

      instRW.run(optEnv);
      instRW.analyzeMayWrite();
      instRW.removeRedundantRead();
      instRW.removeRedundantWrite();
      instRW.addFlush();

      if(debugFlag){
	System.out.println("---------- instRW:");
	debug_out.print(optEnv.getBody());
      }
    } else {
      optEnv.makeCFG();
      if(debugFlag){
	System.out.println("---------- CFG:"); System.out.flush();
	debug_out.print(optEnv.getBody());
	optEnv.getCFG().printCFG();
      }
      loop_analyzer.run(optEnv);
      lva.run(optEnv);
      SSAtrans.run(optEnv,lva);

      if(debugFlag){
	System.out.println("---------- after SSA:"); System.out.flush();
	debug_out.print(optEnv.getBody());
      }

      instRW.run(optEnv);

      if(debugFlag){
	System.out.println("---------- instRW:");
	debug_out.print(optEnv.getBody());
      }

      mergeRW.run(instRW);

      if(debugFlag){
	System.out.println("---------- after loopTrans:");
	debug_out.print(optEnv.getBody());
      }

      instRW.analyzeMayWrite();
      instRW.removeRedundantRead();
      instRW.removeRedundantWrite();
      instRW.addFlush();

      SSAtrans.normalize();
    }

    instRW.transCode();  // finalize code for RWinstrument
    optEnv.Finalize();
  }
}





