Index: osprey/be/com/alias_analyzer.h
===================================================================
--- osprey/be/com/alias_analyzer.h	(revision 3703)
+++ osprey/be/com/alias_analyzer.h	(working copy)
@@ -27,7 +27,9 @@
 #include "opt_alias_interface.h"
 #include "opt_alias_rule.h"
 #include "wn_map.h"
+#include "config_opt.h"
 
+#define IPA_WN_MAP_ID(filePUIdx, wn_map_id) ((((UINT64)filePUIdx)<<32) | ((wn_map_id)&0xffffffff))
 struct WN;
 struct ST;
 
@@ -76,6 +78,13 @@
 typedef hash_map<QueryFileKey,bool,
                  hashQueryFileKey,equalQueryFileKey> QueryFileMap;
 
+template <class _Key> struct IPAIndexhash { };
+template <> struct IPAIndexhash<UINT64> {
+  size_t operator()(const UINT64 x)const{return (size_t)x;}
+};
+
+typedef hash_map<UINT64, UINT32, IPAIndexhash<UINT64> > IPAWNAliasTagMap;
+
 class AliasAnalyzer {
 
 private:
@@ -85,11 +94,18 @@
    UINT32 _aliasedCount;      // Used for debugging
    QueryFileMap *_queryFileMap;
 
+   // Map WN to AliasTags in IPA:preopt mode
+   // It maps all PUs's alias tag in one map.
+   // key is [file_idx_16bit][pu_idx_16bit][wn_map_id_32_bit]
+   IPAWNAliasTagMap _IPAAliasTageMap;
+   bool _ipaMode;
+   UINT32 _curFilePUIdx;   // current process IPA node's file and PU index
+
 protected:
    MEM_POOL _memPool;
 
 public:
-   AliasAnalyzer();
+   AliasAnalyzer(bool ipaMode=false);
 
    virtual ~AliasAnalyzer();
 
@@ -134,20 +150,61 @@
 
    virtual AliasTag meet(AliasTag destTag, AliasTag srcTag);
 
-   void setAliasTag(WN *wn, AliasTag tag)
+   void setAliasTag(WN *wn, AliasTag tag, UINT32 filePUIdx=UINT32_MAX)
    {
-     IPA_WN_MAP32_Set(Current_Map_Tab, _aliasTagMap, wn, (INT32)tag);
+     if (!_ipaMode) {
+       IPA_WN_MAP32_Set(Current_Map_Tab, _aliasTagMap, wn, (INT32)tag);
+     }
+     else {
+       INT32 wn_map_id = WN_map_id(wn);
+       if (wn_map_id == -1) {
+         WN_MAP_Set_ID(Current_Map_Tab, wn);
+         wn_map_id = WN_map_id(wn);
+       }
+       Is_True(wn_map_id != -1, ("invalid WN map id\n"));
+       if (filePUIdx == UINT32_MAX) {
+         filePUIdx = curFilePUIdx();
+       }
+       UINT64 ipa_map_id = IPA_WN_MAP_ID(filePUIdx, wn_map_id);
+       _IPAAliasTageMap[ipa_map_id] = (UINT32)tag;
+     }
    }
 
-   AliasTag getAliasTag(const WN *wn) const
+   AliasTag getAliasTag(const WN *wn, UINT32 filePUIdx=UINT32_MAX) const
    {
-     return (AliasTag)IPA_WN_MAP32_Get(Current_Map_Tab, _aliasTagMap, wn);
+     if (!_ipaMode) { 
+       return (AliasTag)IPA_WN_MAP32_Get(Current_Map_Tab, _aliasTagMap, wn);
+     }
+     else {
+       // get WN map id and compose IPA_WN_MAP_id
+       INT32 wn_map_id = WN_map_id(wn);
+       if (wn_map_id == -1) {
+         return InvalidAliasTag;
+       }
+       if (filePUIdx == UINT32_MAX) {
+         filePUIdx = curFilePUIdx();
+       }
+       UINT64 ipa_map_id = IPA_WN_MAP_ID(filePUIdx, wn_map_id);
+
+       // search in _IPAAliasTageMap map.
+       IPAWNAliasTagMap::const_iterator iter = _IPAAliasTageMap.find(ipa_map_id);
+       if (iter != _IPAAliasTageMap.end())
+        return (AliasTag)iter->second;
+
+       return InvalidAliasTag;
+     }
    }
 
    UINT32 aliasQueryCount(void)      { return _aliasQueryCount; }
    UINT32 incrAliasQueryCount(void)  { return _aliasQueryCount++; }
    UINT32 incrAliasedCount(void)     { return _aliasedCount++; }
 
+   // IPA preopt related
+   bool ipaMode() const { return _ipaMode; }
+   void ipaMode(bool ipaMode) { _ipaMode = ipaMode; } 
+   UINT32 curFilePUIdx() const {return _curFilePUIdx; }
+   void curFilePUIdx(UINT32 filePUIdx) { _curFilePUIdx = filePUIdx; }
+
    bool checkQueryFile(UINT32 pu, AliasTag tag1, AliasTag tag2, bool &result);
 
    WN_MAP aliasTagMap() { return _aliasTagMap; }
Index: osprey/be/com/nystrom_alias_analyzer.cxx
===================================================================
--- osprey/be/com/nystrom_alias_analyzer.cxx	(revision 3703)
+++ osprey/be/com/nystrom_alias_analyzer.cxx	(working copy)
@@ -34,6 +34,21 @@
 
 PointsTo NystromAliasAnalyzer::emptyPointsToSet;
 
+// post IPA is true, because it has the post IPAA alias info.
+NystromAliasAnalyzer::NystromAliasAnalyzer(ALIAS_CONTEXT &ac)
+  : AliasAnalyzer(true),
+    _nextAliasTag(InitialAliasTag),
+    _isPostIPA(true)
+{
+  // Activate the use of the Nystrom points-to analysis by the
+  // ALIAS_RULE harness and disable alias classification rules.
+  ac |= ALIAS_ANALYZER_RULE;
+  ac &= ~(CLAS_RULE|IP_CLAS_RULE); 
+
+  Write_ALIAS_CGNODE_Map = TRUE;
+}
+
+
 NystromAliasAnalyzer::NystromAliasAnalyzer(ALIAS_CONTEXT &ac, WN* entryWN,
                                            bool backend)
   : AliasAnalyzer(),
@@ -204,8 +219,23 @@
 
   // First we adjust the requested offset by any modulus that
   // is being model by the constraint graph for this symbol.
-  ConstraintGraph *cg = _constraintGraph;
-  StInfo *stInfo = cg->stInfo(CG_ST_st_idx(st));
+  ConstraintGraph *cg;
+  CG_ST_IDX cg_st_idx;
+  // in IPA:preopt mode, check if st is global. Find st info in global CG.
+  if (ipaMode() && StInfo::isGlobalStInfo(st)) {
+    cg = ConstraintGraph::globalCG();
+    cg_st_idx = CG_ST_st_idx(st);
+  }
+  else {
+    cg = _constraintGraph;
+    if (ipaMode()) {
+      cg_st_idx = IPA_CG_ST_st_idx(curFilePUIdx(), st);
+    }
+    else {
+      cg_st_idx = CG_ST_st_idx(st);
+    }
+  }
+  StInfo *stInfo = cg->stInfo(cg_st_idx);
   if (!stInfo) {
     if(isPostIPA() && ST_class(st) == CLASS_BLOCK) {
       INT64 new_offset;
@@ -222,7 +252,7 @@
     offset = stInfo->applyModulus(offset);
   }
   // First we check to see if we have been asked this question before...
-  StToAliasTagKey atKey(CG_ST_st_idx(st),offset,size);
+  StToAliasTagKey atKey(cg_st_idx,offset,size);
   StToAliasTagMapIterator atIter = _stToAliasTagMap.find(atKey);
   if (atIter != _stToAliasTagMap.end())
     aliasTag = atIter->second;
@@ -231,7 +261,7 @@
     // (a) find <ST,offset> exactly when size == 0
     // (b) find <ST,offset> ... <ST,offset+size-1> when size >= zero
     if (size == 0) {
-      ConstraintGraphNode *node = cg->checkCGNode(CG_ST_st_idx(st),offset);
+      ConstraintGraphNode *node = cg->checkCGNode(cg_st_idx,offset);
       if (node) {
         node = cg->aliasedSym(node);
         aliasTag = newAliasTag();
Index: osprey/be/com/nystrom_alias_analyzer.h
===================================================================
--- osprey/be/com/nystrom_alias_analyzer.h	(revision 3703)
+++ osprey/be/com/nystrom_alias_analyzer.h	(working copy)
@@ -119,8 +119,13 @@
 };
 
 class NystromAliasAnalyzer : public AliasAnalyzer {
+
+   friend class AliasAnalyzer;
    
 public:
+   // Invoked in ipa mode, alias analyzer shared by all PUs.
+   NystromAliasAnalyzer(ALIAS_CONTEXT&);
+   
    // Invoked in non-ipa mode when WN to CGNodeId map is not available
    NystromAliasAnalyzer(ALIAS_CONTEXT &,WN *);
 
@@ -164,6 +169,8 @@
 
    ConstraintGraph *constraintGraph() const { return _constraintGraph; }
 
+   void constraintGraph(ConstraintGraph *cg) { _constraintGraph=cg; }
+
    CGNodeId cgNodeId(AliasTag tag) 
    {
      hash_map<UINT32, CGNodeId>::iterator iter = 
Index: osprey/be/com/constraint_graph.cxx
===================================================================
--- osprey/be/com/constraint_graph.cxx	(revision 3703)
+++ osprey/be/com/constraint_graph.cxx	(working copy)
@@ -39,6 +39,7 @@
 CallSiteId ConstraintGraph::nextCallSiteId = 1;
 bool ConstraintGraph::isIPA = false;
 ConstraintGraph *ConstraintGraph::globalConstraintGraph = NULL;
+ConstraintGraph *ConstraintGraph::currentIPANodeConstraintGraph = NULL;
 ConstraintGraphNode *ConstraintGraph::notAPointerCGNode = NULL;
 ConstraintGraphNode *ConstraintGraph::blackHoleCGNode = NULL;
 CGIdToNodeMap ConstraintGraph::cgIdToNodeMap(8192);
@@ -502,15 +503,7 @@
 
   // Set the flags
   ST_SCLASS storage_class = ST_sclass(st);
-  if (storage_class == SCLASS_FSTATIC ||
-      (storage_class == SCLASS_PSTATIC &&
-       ST_IDX_level(st_idx) == GLOBAL_SYMTAB) ||
-      storage_class == SCLASS_COMMON ||
-      storage_class == SCLASS_UGLOBAL ||
-      storage_class == SCLASS_DGLOBAL ||
-      storage_class == SCLASS_UNKNOWN ||
-      storage_class == SCLASS_TEXT ||
-      storage_class == SCLASS_EXTERN)
+  if (isGlobalStInfo(st))
     addFlags(CG_ST_FLAGS_GLOBAL);
 
   if (ST_class(st) == CLASS_FUNC)
@@ -530,6 +523,25 @@
     addFlags(CG_ST_FLAGS_NOCNTXT);
 }
 
+bool 
+StInfo::isGlobalStInfo(ST* st)
+{
+  ST_SCLASS storage_class = ST_sclass(st);
+  ST_IDX st_idx = ST_st_idx(st);
+  if (storage_class == SCLASS_FSTATIC ||
+      (storage_class == SCLASS_PSTATIC &&
+       ST_IDX_level(st_idx) == GLOBAL_SYMTAB) ||
+      storage_class == SCLASS_COMMON ||
+      storage_class == SCLASS_UGLOBAL ||
+      storage_class == SCLASS_DGLOBAL ||
+      storage_class == SCLASS_UNKNOWN ||
+      storage_class == SCLASS_TEXT ||
+      storage_class == SCLASS_EXTERN) {
+    return true;
+  }
+  return false;
+}
+
 bool
 ConstraintGraphNode::isAPossiblePtr()
 {
Index: osprey/be/com/constraint_graph.h
===================================================================
--- osprey/be/com/constraint_graph.h	(revision 3703)
+++ osprey/be/com/constraint_graph.h	(working copy)
@@ -186,6 +186,7 @@
 // where we assume the file and pu num is zero and the ST_IDX will be able
 // to uniquely identify the ST
 #define CG_ST_st_idx(s) (ST_st_idx((s)) & 0x00000000ffffffffLL)
+#define IPA_CG_ST_st_idx(filePUIdx, s) (((filePUIdx) << 32) | ST_st_idx((s)) & 0x00000000ffffffffLL)
   
 using namespace std;
 using namespace __gnu_cxx;
@@ -1147,6 +1148,8 @@
     _u._modulus = m;
   }
 
+  static bool isGlobalStInfo(ST* st);
+
   TY_IDX ty_idx() const { return _ty_idx; }
   void ty_idx(TY_IDX idx) { _ty_idx = idx; }
 
@@ -1292,6 +1295,10 @@
 
   static CG_ST_IDX adjustCGstIdx(IPA_NODE *ipaNode, CG_ST_IDX cg_st_idx);
 
+  static ConstraintGraph *IPANodeCG()        { return currentIPANodeConstraintGraph; }
+
+  static void IPANodeCG(ConstraintGraph* cg)        { currentIPANodeConstraintGraph = cg; }
+
   // Map from unique call site id to CallSite in ipa
   static CallSite *uniqueCallSite(CallSiteId uniqueCallSiteId)
   {
@@ -1540,6 +1547,10 @@
 
   CallSite *findUniqueCallSite(CallSiteId id);
 
+  void setUniqueMapped(void);
+
+  bool uniqueMapped(void);
+
   void updateSummaryCallSiteId(SUMMARY_CALLSITE &summCallSite);
 
   void updateCallSiteForBE(CallSite *cs);
@@ -1604,6 +1615,9 @@
   // The global constraint graph for IPA
   static ConstraintGraph *globalConstraintGraph;
 
+  // info used for CG for one IPA_NODE in IPA
+  static ConstraintGraph *currentIPANodeConstraintGraph;
+
   // Pool to hold all edges, since edges span multiple ConstraintGraphs
   static MEM_POOL *edgeMemPool;
 
@@ -1719,6 +1733,7 @@
   CGIdToNodeMap _uniqueCGNodeIdMap;
   CallSiteMap   _uniqueCallSiteIdMap;
   CGStInfoMap   _ipaCGStIdxToStInfoMap;
+  bool          _uniqueMapped; // indicate if uniqueMap is performed.
 
   // IPA call graph node corresponding to this CG
   IPA_NODE *_ipaNode;
Index: osprey/be/com/alias_analyzer.cxx
===================================================================
--- osprey/be/com/alias_analyzer.cxx	(revision 3703)
+++ osprey/be/com/alias_analyzer.cxx	(working copy)
@@ -37,6 +37,23 @@
 AliasAnalyzer *
 AliasAnalyzer::Create_Alias_Analyzer(ALIAS_CONTEXT &ac, WN *tree)
 {
+  // if create nystrom alias analyzer in IPA phase.
+  // only creat one instance for all PUs.
+  if (Alias_Nystrom_Analyzer && Alias_Analyzer_in_IPA) {
+    if (_alias_analyzer == NULL) {
+      _alias_analyzer = new NystromAliasAnalyzer(ac);
+    }
+
+    // this alias analyzer is for IPA:preopt
+    Is_True(Current_IPANode_File_PU_Idx != UINT32_MAX, ("invlaid IPANode PUFileIdx\n"));
+    _alias_analyzer->curFilePUIdx(Current_IPANode_File_PU_Idx);
+
+    FmtAssert(ConstraintGraph::IPANodeCG() != NULL, ("Create Alias anlyzer IPA node cg is NULL")); 
+    ((NystromAliasAnalyzer*)_alias_analyzer)->constraintGraph(ConstraintGraph::IPANodeCG());
+    ((NystromAliasAnalyzer*)_alias_analyzer)->createAliasTags(tree);
+    return _alias_analyzer;
+  }
+  
   if (_alias_analyzer != NULL) {
     // Activate the use of the Nystrom points-to analysis by the
     // ALIAS_RULE harness and disable alias classification rules.
@@ -72,13 +89,20 @@
   }
 }
   
-AliasAnalyzer::AliasAnalyzer() 
+AliasAnalyzer::AliasAnalyzer(bool ipaMode) 
   : _aliasQueryCount(0),
     _aliasedCount(0),
-    _queryFileMap(NULL)
+    _aliasTagMap(WN_MAP_UNDEFINED),
+    _queryFileMap(NULL),
+    _ipaMode(ipaMode),
+    _curFilePUIdx(0)
 {
   MEM_POOL_Initialize(&_memPool, "AliasAnalyzer_pool", FALSE);
-  _aliasTagMap = IPA_WN_MAP32_Create(Current_Map_Tab, &_memPool);
+  // if in IPA:preopt mode, use the inter-procedure _IPAAliasTageMap
+  // to record WN->alias tag map.
+  if (!_ipaMode) {
+    _aliasTagMap = IPA_WN_MAP32_Create(Current_Map_Tab, &_memPool);
+  }
 
   if (Alias_Query_File) {
     loadQueryFile(Alias_Query_File);
@@ -96,7 +120,9 @@
             (float)_aliasedCount/(float)_aliasQueryCount * 100.0);
   
   MEM_POOL_Delete(&_memPool);
-  IPA_WN_MAP_Delete(Current_Map_Tab, _aliasTagMap);
+  if (!_ipaMode) {
+    IPA_WN_MAP_Delete(Current_Map_Tab, _aliasTagMap);
+  }
 }
 
 ALIAS_RESULT
Index: osprey/common/com/config_opt.h
===================================================================
--- osprey/common/com/config_opt.h	(revision 3703)
+++ osprey/common/com/config_opt.h	(working copy)
@@ -122,6 +122,8 @@
                                            in a common block */
 extern BOOL  Alias_F90_Pointer_Unaliased;  /* Are F90 pointers unaliased? */
 extern BOOL Alias_Nystrom_Analyzer;     /* Are we using Nystrom alias analysis? */
+extern BOOL Alias_Analyzer_in_IPA; /* Are we create Nystrom alias analyzer in IPA? */ 
+extern UINT32 Current_IPANode_File_PU_Idx; /* current processing IPA node's file pu index */ 
 
 /***** Expression folding options *****/
 extern BOOL Enable_Cfold_Float;		/* FP constant folding? */
Index: osprey/common/com/config_opt.cxx
===================================================================
--- osprey/common/com/config_opt.cxx	(revision 3703)
+++ osprey/common/com/config_opt.cxx	(working copy)
@@ -121,6 +121,8 @@
 BOOL  Alias_F90_Pointer_Unaliased = FALSE;  /* Are F90 pointers unaliased? */
 
 BOOL  Alias_Nystrom_Analyzer = FALSE;  /* Using Nystrom-based alias analysis? */
+BOOL  Alias_Analyzer_in_IPA = FALSE;  /* Create nystrom alias in IPA */
+UINT32 Current_IPANode_File_PU_Idx = 0; /* current processing IPA node's file pu index */ 
 
 /***** Alignment control *****/
 BOOL Align_Object = TRUE;	/* Try to improve alignment of objects */
Index: osprey/ipa/main/analyze/ipa_nystrom_alias_analyzer.cxx
===================================================================
--- osprey/ipa/main/analyze/ipa_nystrom_alias_analyzer.cxx	(revision 3703)
+++ osprey/ipa/main/analyze/ipa_nystrom_alias_analyzer.cxx	(working copy)
@@ -256,6 +256,19 @@
 }
 
 void 
+ConstraintGraph::setUniqueMapped(void)
+{
+  Is_True(_uniqueMapped == false, ("unique map already tranformed\n"));
+  _uniqueMapped = true;
+}
+
+bool 
+ConstraintGraph::uniqueMapped(void)
+{
+  return _uniqueMapped;
+}
+
+void 
 ConstraintGraph::buildCGipa(IPA_NODE *ipaNode)
 {
   INT32 size;
@@ -274,6 +287,7 @@
   // during summary to constraint graph construction, map them to their 
   // globally unique ids so that lookups don't fail
   _uniqueCGNodeIdMap[notAPointer()->id()] = notAPointer();
+  _uniqueMapped = false;
 
   // Add the StInfos.
   UINT32 stInfoIdx = proc->Get_constraint_graph_stinfos_idx();
@@ -1989,6 +2003,8 @@
   FmtAssert(entryWN != NULL, ("Null WN tree!\n"));
 
   ConstraintGraph *cg = this->cg(node->Node_Index());
+  if (cg->uniqueMapped())
+    return;
 
   // fprintf(stderr, "mapWNToUniqCGNodeId: %s\n", cg->name());
 
@@ -2016,6 +2032,7 @@
       WN_MAP_CGNodeId_Set(wn, newId);
     }
   }
+  cg->setUniqueMapped();
 }
 
 void
Index: osprey/ipa/main/analyze/ipa_preopt.cxx
===================================================================
--- osprey/ipa/main/analyze/ipa_preopt.cxx	(revision 3703)
+++ osprey/ipa/main/analyze/ipa_preopt.cxx	(working copy)
@@ -83,6 +83,7 @@
 #include "optimizer.h"                  // Pre_Optimizer
 #include "region_main.h"                // REGION_Initialize
 #include "ipa_main.h"
+#include "ipa_nystrom_alias_analyzer.h"
 
 // --- from wopt.so
 #pragma weak Create_Du_Manager
@@ -686,7 +687,6 @@
     fdump_tree (TFile, wn);
   }
 
-
   REGION_Initialize (wn, PU_has_region(node->Get_PU()));
 
   MEM_POOL_Push (&MEM_local_pool);
@@ -714,6 +714,20 @@
   PU_adjust_addr_flags(Get_Current_PU_ST(), wn);
 
   DU_MANAGER* du_mgr = Create_Du_Manager (MEM_pu_nz_pool_ptr);
+
+  // tell alias analyzer, current nystrom alias analyzer
+  // is crated for IPA
+  if (Alias_Nystrom_Analyzer) {
+    Alias_Analyzer_in_IPA = TRUE;
+    UINT16 fileIdx = (UINT16)(node->File_Index());
+    UINT16 puIdx   = (UINT16)(node->Proc_Info_Index());
+    Current_IPANode_File_PU_Idx = (fileIdx << 16) | puIdx;
+
+    IPA_NystromAliasAnalyzer *ipan = IPA_NystromAliasAnalyzer::aliasAnalyzer();
+    ConstraintGraph::IPANodeCG(ipan->cg(node->Node_Index()));
+
+    IPA_NystromAliasAnalyzer::aliasAnalyzer()->mapWNToUniqCallSiteCGNodeId(node);
+  }
   ALIAS_MANAGER* alias_mgr = Create_Alias_Manager (MEM_pu_nz_pool_ptr, wn);
 
   // call the preopt, which then calls Perform_Procedure_Summary_Phase
