HexagonCommonGEP.cpp revision 296417
1286425Sdim//===--- HexagonCommonGEP.cpp ---------------------------------------------===//
2286425Sdim//
3286425Sdim//                     The LLVM Compiler Infrastructure
4286425Sdim//
5286425Sdim// This file is distributed under the University of Illinois Open Source
6286425Sdim// License. See LICENSE.TXT for details.
7286425Sdim//
8286425Sdim//===----------------------------------------------------------------------===//
9286425Sdim
10286425Sdim#define DEBUG_TYPE "commgep"
11286425Sdim
12286425Sdim#include "llvm/Pass.h"
13286425Sdim#include "llvm/ADT/FoldingSet.h"
14286425Sdim#include "llvm/ADT/STLExtras.h"
15286425Sdim#include "llvm/Analysis/LoopInfo.h"
16286425Sdim#include "llvm/Analysis/PostDominators.h"
17286425Sdim#include "llvm/CodeGen/MachineFunctionAnalysis.h"
18286425Sdim#include "llvm/IR/Constants.h"
19286425Sdim#include "llvm/IR/Dominators.h"
20286425Sdim#include "llvm/IR/Function.h"
21286425Sdim#include "llvm/IR/Instructions.h"
22286425Sdim#include "llvm/IR/Verifier.h"
23286425Sdim#include "llvm/Support/Allocator.h"
24286425Sdim#include "llvm/Support/CommandLine.h"
25286425Sdim#include "llvm/Support/Debug.h"
26286425Sdim#include "llvm/Support/raw_ostream.h"
27286425Sdim#include "llvm/Transforms/Scalar.h"
28286425Sdim#include "llvm/Transforms/Utils/Local.h"
29286425Sdim
30286425Sdim#include <map>
31286425Sdim#include <set>
32286425Sdim#include <vector>
33286425Sdim
34286425Sdim#include "HexagonTargetMachine.h"
35286425Sdim
36286425Sdimusing namespace llvm;
37286425Sdim
38286425Sdimstatic cl::opt<bool> OptSpeculate("commgep-speculate", cl::init(true),
39286425Sdim  cl::Hidden, cl::ZeroOrMore);
40286425Sdim
41286425Sdimstatic cl::opt<bool> OptEnableInv("commgep-inv", cl::init(true), cl::Hidden,
42286425Sdim  cl::ZeroOrMore);
43286425Sdim
44286425Sdimstatic cl::opt<bool> OptEnableConst("commgep-const", cl::init(true),
45286425Sdim  cl::Hidden, cl::ZeroOrMore);
46286425Sdim
47286425Sdimnamespace llvm {
48286425Sdim  void initializeHexagonCommonGEPPass(PassRegistry&);
49286425Sdim}
50286425Sdim
51286425Sdimnamespace {
52286425Sdim  struct GepNode;
53286425Sdim  typedef std::set<GepNode*> NodeSet;
54286425Sdim  typedef std::map<GepNode*,Value*> NodeToValueMap;
55286425Sdim  typedef std::vector<GepNode*> NodeVect;
56286425Sdim  typedef std::map<GepNode*,NodeVect> NodeChildrenMap;
57286425Sdim  typedef std::set<Use*> UseSet;
58286425Sdim  typedef std::map<GepNode*,UseSet> NodeToUsesMap;
59286425Sdim
60286425Sdim  // Numbering map for gep nodes. Used to keep track of ordering for
61286425Sdim  // gep nodes.
62296417Sdim  struct NodeOrdering {
63296417Sdim    NodeOrdering() : LastNum(0) {}
64286425Sdim
65296417Sdim    void insert(const GepNode *N) { Map.insert(std::make_pair(N, ++LastNum)); }
66296417Sdim    void clear() { Map.clear(); }
67296417Sdim
68296417Sdim    bool operator()(const GepNode *N1, const GepNode *N2) const {
69296417Sdim      auto F1 = Map.find(N1), F2 = Map.find(N2);
70296417Sdim      assert(F1 != Map.end() && F2 != Map.end());
71286425Sdim      return F1->second < F2->second;
72286425Sdim    }
73296417Sdim
74286425Sdim  private:
75296417Sdim    std::map<const GepNode *, unsigned> Map;
76286425Sdim    unsigned LastNum;
77286425Sdim  };
78286425Sdim
79286425Sdim  class HexagonCommonGEP : public FunctionPass {
80286425Sdim  public:
81286425Sdim    static char ID;
82286425Sdim    HexagonCommonGEP() : FunctionPass(ID) {
83286425Sdim      initializeHexagonCommonGEPPass(*PassRegistry::getPassRegistry());
84286425Sdim    }
85286425Sdim    virtual bool runOnFunction(Function &F);
86286425Sdim    virtual const char *getPassName() const {
87286425Sdim      return "Hexagon Common GEP";
88286425Sdim    }
89286425Sdim
90286425Sdim    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
91286425Sdim      AU.addRequired<DominatorTreeWrapperPass>();
92286425Sdim      AU.addPreserved<DominatorTreeWrapperPass>();
93286425Sdim      AU.addRequired<PostDominatorTree>();
94286425Sdim      AU.addPreserved<PostDominatorTree>();
95286425Sdim      AU.addRequired<LoopInfoWrapperPass>();
96286425Sdim      AU.addPreserved<LoopInfoWrapperPass>();
97286425Sdim      FunctionPass::getAnalysisUsage(AU);
98286425Sdim    }
99286425Sdim
100286425Sdim  private:
101286425Sdim    typedef std::map<Value*,GepNode*> ValueToNodeMap;
102286425Sdim    typedef std::vector<Value*> ValueVect;
103286425Sdim    typedef std::map<GepNode*,ValueVect> NodeToValuesMap;
104286425Sdim
105286425Sdim    void getBlockTraversalOrder(BasicBlock *Root, ValueVect &Order);
106286425Sdim    bool isHandledGepForm(GetElementPtrInst *GepI);
107286425Sdim    void processGepInst(GetElementPtrInst *GepI, ValueToNodeMap &NM);
108286425Sdim    void collect();
109286425Sdim    void common();
110286425Sdim
111286425Sdim    BasicBlock *recalculatePlacement(GepNode *Node, NodeChildrenMap &NCM,
112286425Sdim                                     NodeToValueMap &Loc);
113286425Sdim    BasicBlock *recalculatePlacementRec(GepNode *Node, NodeChildrenMap &NCM,
114286425Sdim                                        NodeToValueMap &Loc);
115286425Sdim    bool isInvariantIn(Value *Val, Loop *L);
116286425Sdim    bool isInvariantIn(GepNode *Node, Loop *L);
117286425Sdim    bool isInMainPath(BasicBlock *B, Loop *L);
118286425Sdim    BasicBlock *adjustForInvariance(GepNode *Node, NodeChildrenMap &NCM,
119286425Sdim                                    NodeToValueMap &Loc);
120286425Sdim    void separateChainForNode(GepNode *Node, Use *U, NodeToValueMap &Loc);
121286425Sdim    void separateConstantChains(GepNode *Node, NodeChildrenMap &NCM,
122286425Sdim                                NodeToValueMap &Loc);
123286425Sdim    void computeNodePlacement(NodeToValueMap &Loc);
124286425Sdim
125286425Sdim    Value *fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
126286425Sdim                        BasicBlock *LocB);
127286425Sdim    void getAllUsersForNode(GepNode *Node, ValueVect &Values,
128286425Sdim                            NodeChildrenMap &NCM);
129286425Sdim    void materialize(NodeToValueMap &Loc);
130286425Sdim
131286425Sdim    void removeDeadCode();
132286425Sdim
133286425Sdim    NodeVect Nodes;
134286425Sdim    NodeToUsesMap Uses;
135286425Sdim    NodeOrdering NodeOrder;   // Node ordering, for deterministic behavior.
136286425Sdim    SpecificBumpPtrAllocator<GepNode> *Mem;
137286425Sdim    LLVMContext *Ctx;
138286425Sdim    LoopInfo *LI;
139286425Sdim    DominatorTree *DT;
140286425Sdim    PostDominatorTree *PDT;
141286425Sdim    Function *Fn;
142286425Sdim  };
143286425Sdim}
144286425Sdim
145286425Sdim
146286425Sdimchar HexagonCommonGEP::ID = 0;
147286425SdimINITIALIZE_PASS_BEGIN(HexagonCommonGEP, "hcommgep", "Hexagon Common GEP",
148286425Sdim      false, false)
149286425SdimINITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
150286425SdimINITIALIZE_PASS_DEPENDENCY(PostDominatorTree)
151286425SdimINITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
152286425SdimINITIALIZE_PASS_END(HexagonCommonGEP, "hcommgep", "Hexagon Common GEP",
153286425Sdim      false, false)
154286425Sdim
155286425Sdimnamespace {
156286425Sdim  struct GepNode {
157286425Sdim    enum {
158286425Sdim      None      = 0,
159286425Sdim      Root      = 0x01,
160286425Sdim      Internal  = 0x02,
161286425Sdim      Used      = 0x04
162286425Sdim    };
163286425Sdim
164286425Sdim    uint32_t Flags;
165286425Sdim    union {
166286425Sdim      GepNode *Parent;
167286425Sdim      Value *BaseVal;
168286425Sdim    };
169286425Sdim    Value *Idx;
170286425Sdim    Type *PTy;  // Type of the pointer operand.
171286425Sdim
172286425Sdim    GepNode() : Flags(0), Parent(0), Idx(0), PTy(0) {}
173286425Sdim    GepNode(const GepNode *N) : Flags(N->Flags), Idx(N->Idx), PTy(N->PTy) {
174286425Sdim      if (Flags & Root)
175286425Sdim        BaseVal = N->BaseVal;
176286425Sdim      else
177286425Sdim        Parent = N->Parent;
178286425Sdim    }
179286425Sdim    friend raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN);
180286425Sdim  };
181286425Sdim
182286425Sdim
183286425Sdim  Type *next_type(Type *Ty, Value *Idx) {
184286425Sdim    // Advance the type.
185286425Sdim    if (!Ty->isStructTy()) {
186286425Sdim      Type *NexTy = cast<SequentialType>(Ty)->getElementType();
187286425Sdim      return NexTy;
188286425Sdim    }
189286425Sdim    // Otherwise it is a struct type.
190286425Sdim    ConstantInt *CI = dyn_cast<ConstantInt>(Idx);
191286425Sdim    assert(CI && "Struct type with non-constant index");
192286425Sdim    int64_t i = CI->getValue().getSExtValue();
193286425Sdim    Type *NextTy = cast<StructType>(Ty)->getElementType(i);
194286425Sdim    return NextTy;
195286425Sdim  }
196286425Sdim
197286425Sdim
198286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN) {
199286425Sdim    OS << "{ {";
200286425Sdim    bool Comma = false;
201286425Sdim    if (GN.Flags & GepNode::Root) {
202286425Sdim      OS << "root";
203286425Sdim      Comma = true;
204286425Sdim    }
205286425Sdim    if (GN.Flags & GepNode::Internal) {
206286425Sdim      if (Comma)
207286425Sdim        OS << ',';
208286425Sdim      OS << "internal";
209286425Sdim      Comma = true;
210286425Sdim    }
211286425Sdim    if (GN.Flags & GepNode::Used) {
212286425Sdim      if (Comma)
213286425Sdim        OS << ',';
214286425Sdim      OS << "used";
215286425Sdim      Comma = true;
216286425Sdim    }
217286425Sdim    OS << "} ";
218286425Sdim    if (GN.Flags & GepNode::Root)
219286425Sdim      OS << "BaseVal:" << GN.BaseVal->getName() << '(' << GN.BaseVal << ')';
220286425Sdim    else
221286425Sdim      OS << "Parent:" << GN.Parent;
222286425Sdim
223286425Sdim    OS << " Idx:";
224286425Sdim    if (ConstantInt *CI = dyn_cast<ConstantInt>(GN.Idx))
225286425Sdim      OS << CI->getValue().getSExtValue();
226286425Sdim    else if (GN.Idx->hasName())
227286425Sdim      OS << GN.Idx->getName();
228286425Sdim    else
229286425Sdim      OS << "<anon> =" << *GN.Idx;
230286425Sdim
231286425Sdim    OS << " PTy:";
232286425Sdim    if (GN.PTy->isStructTy()) {
233286425Sdim      StructType *STy = cast<StructType>(GN.PTy);
234286425Sdim      if (!STy->isLiteral())
235286425Sdim        OS << GN.PTy->getStructName();
236286425Sdim      else
237286425Sdim        OS << "<anon-struct>:" << *STy;
238286425Sdim    }
239286425Sdim    else
240286425Sdim      OS << *GN.PTy;
241286425Sdim    OS << " }";
242286425Sdim    return OS;
243286425Sdim  }
244286425Sdim
245286425Sdim
246286425Sdim  template <typename NodeContainer>
247286425Sdim  void dump_node_container(raw_ostream &OS, const NodeContainer &S) {
248286425Sdim    typedef typename NodeContainer::const_iterator const_iterator;
249286425Sdim    for (const_iterator I = S.begin(), E = S.end(); I != E; ++I)
250286425Sdim      OS << *I << ' ' << **I << '\n';
251286425Sdim  }
252286425Sdim
253286425Sdim  raw_ostream &operator<< (raw_ostream &OS,
254286425Sdim                           const NodeVect &S) LLVM_ATTRIBUTE_UNUSED;
255286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const NodeVect &S) {
256286425Sdim    dump_node_container(OS, S);
257286425Sdim    return OS;
258286425Sdim  }
259286425Sdim
260286425Sdim
261286425Sdim  raw_ostream &operator<< (raw_ostream &OS,
262286425Sdim                           const NodeToUsesMap &M) LLVM_ATTRIBUTE_UNUSED;
263286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const NodeToUsesMap &M){
264286425Sdim    typedef NodeToUsesMap::const_iterator const_iterator;
265286425Sdim    for (const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
266286425Sdim      const UseSet &Us = I->second;
267286425Sdim      OS << I->first << " -> #" << Us.size() << '{';
268286425Sdim      for (UseSet::const_iterator J = Us.begin(), F = Us.end(); J != F; ++J) {
269286425Sdim        User *R = (*J)->getUser();
270286425Sdim        if (R->hasName())
271286425Sdim          OS << ' ' << R->getName();
272286425Sdim        else
273286425Sdim          OS << " <?>(" << *R << ')';
274286425Sdim      }
275286425Sdim      OS << " }\n";
276286425Sdim    }
277286425Sdim    return OS;
278286425Sdim  }
279286425Sdim
280286425Sdim
281286425Sdim  struct in_set {
282286425Sdim    in_set(const NodeSet &S) : NS(S) {}
283286425Sdim    bool operator() (GepNode *N) const {
284286425Sdim      return NS.find(N) != NS.end();
285286425Sdim    }
286286425Sdim  private:
287286425Sdim    const NodeSet &NS;
288286425Sdim  };
289286425Sdim}
290286425Sdim
291286425Sdim
292286425Sdiminline void *operator new(size_t, SpecificBumpPtrAllocator<GepNode> &A) {
293286425Sdim  return A.Allocate();
294286425Sdim}
295286425Sdim
296286425Sdim
297286425Sdimvoid HexagonCommonGEP::getBlockTraversalOrder(BasicBlock *Root,
298286425Sdim      ValueVect &Order) {
299286425Sdim  // Compute block ordering for a typical DT-based traversal of the flow
300286425Sdim  // graph: "before visiting a block, all of its dominators must have been
301286425Sdim  // visited".
302286425Sdim
303286425Sdim  Order.push_back(Root);
304286425Sdim  DomTreeNode *DTN = DT->getNode(Root);
305286425Sdim  typedef GraphTraits<DomTreeNode*> GTN;
306286425Sdim  typedef GTN::ChildIteratorType Iter;
307286425Sdim  for (Iter I = GTN::child_begin(DTN), E = GTN::child_end(DTN); I != E; ++I)
308286425Sdim    getBlockTraversalOrder((*I)->getBlock(), Order);
309286425Sdim}
310286425Sdim
311286425Sdim
312286425Sdimbool HexagonCommonGEP::isHandledGepForm(GetElementPtrInst *GepI) {
313286425Sdim  // No vector GEPs.
314286425Sdim  if (!GepI->getType()->isPointerTy())
315286425Sdim    return false;
316286425Sdim  // No GEPs without any indices.  (Is this possible?)
317286425Sdim  if (GepI->idx_begin() == GepI->idx_end())
318286425Sdim    return false;
319286425Sdim  return true;
320286425Sdim}
321286425Sdim
322286425Sdim
323286425Sdimvoid HexagonCommonGEP::processGepInst(GetElementPtrInst *GepI,
324286425Sdim      ValueToNodeMap &NM) {
325286425Sdim  DEBUG(dbgs() << "Visiting GEP: " << *GepI << '\n');
326286425Sdim  GepNode *N = new (*Mem) GepNode;
327286425Sdim  Value *PtrOp = GepI->getPointerOperand();
328286425Sdim  ValueToNodeMap::iterator F = NM.find(PtrOp);
329286425Sdim  if (F == NM.end()) {
330286425Sdim    N->BaseVal = PtrOp;
331286425Sdim    N->Flags |= GepNode::Root;
332286425Sdim  } else {
333286425Sdim    // If PtrOp was a GEP instruction, it must have already been processed.
334286425Sdim    // The ValueToNodeMap entry for it is the last gep node in the generated
335286425Sdim    // chain. Link to it here.
336286425Sdim    N->Parent = F->second;
337286425Sdim  }
338286425Sdim  N->PTy = PtrOp->getType();
339286425Sdim  N->Idx = *GepI->idx_begin();
340286425Sdim
341286425Sdim  // Collect the list of users of this GEP instruction. Will add it to the
342286425Sdim  // last node created for it.
343286425Sdim  UseSet Us;
344286425Sdim  for (Value::user_iterator UI = GepI->user_begin(), UE = GepI->user_end();
345286425Sdim       UI != UE; ++UI) {
346286425Sdim    // Check if this gep is used by anything other than other geps that
347286425Sdim    // we will process.
348286425Sdim    if (isa<GetElementPtrInst>(*UI)) {
349286425Sdim      GetElementPtrInst *UserG = cast<GetElementPtrInst>(*UI);
350286425Sdim      if (isHandledGepForm(UserG))
351286425Sdim        continue;
352286425Sdim    }
353286425Sdim    Us.insert(&UI.getUse());
354286425Sdim  }
355286425Sdim  Nodes.push_back(N);
356286425Sdim  NodeOrder.insert(N);
357286425Sdim
358286425Sdim  // Skip the first index operand, since we only handle 0. This dereferences
359286425Sdim  // the pointer operand.
360286425Sdim  GepNode *PN = N;
361286425Sdim  Type *PtrTy = cast<PointerType>(PtrOp->getType())->getElementType();
362286425Sdim  for (User::op_iterator OI = GepI->idx_begin()+1, OE = GepI->idx_end();
363286425Sdim       OI != OE; ++OI) {
364286425Sdim    Value *Op = *OI;
365286425Sdim    GepNode *Nx = new (*Mem) GepNode;
366286425Sdim    Nx->Parent = PN;  // Link Nx to the previous node.
367286425Sdim    Nx->Flags |= GepNode::Internal;
368286425Sdim    Nx->PTy = PtrTy;
369286425Sdim    Nx->Idx = Op;
370286425Sdim    Nodes.push_back(Nx);
371286425Sdim    NodeOrder.insert(Nx);
372286425Sdim    PN = Nx;
373286425Sdim
374286425Sdim    PtrTy = next_type(PtrTy, Op);
375286425Sdim  }
376286425Sdim
377286425Sdim  // After last node has been created, update the use information.
378286425Sdim  if (!Us.empty()) {
379286425Sdim    PN->Flags |= GepNode::Used;
380286425Sdim    Uses[PN].insert(Us.begin(), Us.end());
381286425Sdim  }
382286425Sdim
383286425Sdim  // Link the last node with the originating GEP instruction. This is to
384286425Sdim  // help with linking chained GEP instructions.
385286425Sdim  NM.insert(std::make_pair(GepI, PN));
386286425Sdim}
387286425Sdim
388286425Sdim
389286425Sdimvoid HexagonCommonGEP::collect() {
390286425Sdim  // Establish depth-first traversal order of the dominator tree.
391286425Sdim  ValueVect BO;
392296417Sdim  getBlockTraversalOrder(&Fn->front(), BO);
393286425Sdim
394286425Sdim  // The creation of gep nodes requires DT-traversal. When processing a GEP
395286425Sdim  // instruction that uses another GEP instruction as the base pointer, the
396286425Sdim  // gep node for the base pointer should already exist.
397286425Sdim  ValueToNodeMap NM;
398286425Sdim  for (ValueVect::iterator I = BO.begin(), E = BO.end(); I != E; ++I) {
399286425Sdim    BasicBlock *B = cast<BasicBlock>(*I);
400286425Sdim    for (BasicBlock::iterator J = B->begin(), F = B->end(); J != F; ++J) {
401286425Sdim      if (!isa<GetElementPtrInst>(J))
402286425Sdim        continue;
403286425Sdim      GetElementPtrInst *GepI = cast<GetElementPtrInst>(J);
404286425Sdim      if (isHandledGepForm(GepI))
405286425Sdim        processGepInst(GepI, NM);
406286425Sdim    }
407286425Sdim  }
408286425Sdim
409286425Sdim  DEBUG(dbgs() << "Gep nodes after initial collection:\n" << Nodes);
410286425Sdim}
411286425Sdim
412286425Sdim
413286425Sdimnamespace {
414286425Sdim  void invert_find_roots(const NodeVect &Nodes, NodeChildrenMap &NCM,
415286425Sdim        NodeVect &Roots) {
416286425Sdim    typedef NodeVect::const_iterator const_iterator;
417286425Sdim    for (const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
418286425Sdim      GepNode *N = *I;
419286425Sdim      if (N->Flags & GepNode::Root) {
420286425Sdim        Roots.push_back(N);
421286425Sdim        continue;
422286425Sdim      }
423286425Sdim      GepNode *PN = N->Parent;
424286425Sdim      NCM[PN].push_back(N);
425286425Sdim    }
426286425Sdim  }
427286425Sdim
428286425Sdim  void nodes_for_root(GepNode *Root, NodeChildrenMap &NCM, NodeSet &Nodes) {
429286425Sdim    NodeVect Work;
430286425Sdim    Work.push_back(Root);
431286425Sdim    Nodes.insert(Root);
432286425Sdim
433286425Sdim    while (!Work.empty()) {
434286425Sdim      NodeVect::iterator First = Work.begin();
435286425Sdim      GepNode *N = *First;
436286425Sdim      Work.erase(First);
437286425Sdim      NodeChildrenMap::iterator CF = NCM.find(N);
438286425Sdim      if (CF != NCM.end()) {
439286425Sdim        Work.insert(Work.end(), CF->second.begin(), CF->second.end());
440286425Sdim        Nodes.insert(CF->second.begin(), CF->second.end());
441286425Sdim      }
442286425Sdim    }
443286425Sdim  }
444286425Sdim}
445286425Sdim
446286425Sdim
447286425Sdimnamespace {
448286425Sdim  typedef std::set<NodeSet> NodeSymRel;
449286425Sdim  typedef std::pair<GepNode*,GepNode*> NodePair;
450286425Sdim  typedef std::set<NodePair> NodePairSet;
451286425Sdim
452286425Sdim  const NodeSet *node_class(GepNode *N, NodeSymRel &Rel) {
453286425Sdim    for (NodeSymRel::iterator I = Rel.begin(), E = Rel.end(); I != E; ++I)
454286425Sdim      if (I->count(N))
455286425Sdim        return &*I;
456286425Sdim    return 0;
457286425Sdim  }
458286425Sdim
459286425Sdim  // Create an ordered pair of GepNode pointers. The pair will be used in
460286425Sdim  // determining equality. The only purpose of the ordering is to eliminate
461286425Sdim  // duplication due to the commutativity of equality/non-equality.
462286425Sdim  NodePair node_pair(GepNode *N1, GepNode *N2) {
463286425Sdim    uintptr_t P1 = uintptr_t(N1), P2 = uintptr_t(N2);
464286425Sdim    if (P1 <= P2)
465286425Sdim      return std::make_pair(N1, N2);
466286425Sdim    return std::make_pair(N2, N1);
467286425Sdim  }
468286425Sdim
469286425Sdim  unsigned node_hash(GepNode *N) {
470286425Sdim    // Include everything except flags and parent.
471286425Sdim    FoldingSetNodeID ID;
472286425Sdim    ID.AddPointer(N->Idx);
473286425Sdim    ID.AddPointer(N->PTy);
474286425Sdim    return ID.ComputeHash();
475286425Sdim  }
476286425Sdim
477286425Sdim  bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq, NodePairSet &Ne) {
478286425Sdim    // Don't cache the result for nodes with different hashes. The hash
479286425Sdim    // comparison is fast enough.
480286425Sdim    if (node_hash(N1) != node_hash(N2))
481286425Sdim      return false;
482286425Sdim
483286425Sdim    NodePair NP = node_pair(N1, N2);
484286425Sdim    NodePairSet::iterator FEq = Eq.find(NP);
485286425Sdim    if (FEq != Eq.end())
486286425Sdim      return true;
487286425Sdim    NodePairSet::iterator FNe = Ne.find(NP);
488286425Sdim    if (FNe != Ne.end())
489286425Sdim      return false;
490286425Sdim    // Not previously compared.
491286425Sdim    bool Root1 = N1->Flags & GepNode::Root;
492286425Sdim    bool Root2 = N2->Flags & GepNode::Root;
493286425Sdim    NodePair P = node_pair(N1, N2);
494286425Sdim    // If the Root flag has different values, the nodes are different.
495286425Sdim    // If both nodes are root nodes, but their base pointers differ,
496286425Sdim    // they are different.
497286425Sdim    if (Root1 != Root2 || (Root1 && N1->BaseVal != N2->BaseVal)) {
498286425Sdim      Ne.insert(P);
499286425Sdim      return false;
500286425Sdim    }
501286425Sdim    // Here the root flags are identical, and for root nodes the
502286425Sdim    // base pointers are equal, so the root nodes are equal.
503286425Sdim    // For non-root nodes, compare their parent nodes.
504286425Sdim    if (Root1 || node_eq(N1->Parent, N2->Parent, Eq, Ne)) {
505286425Sdim      Eq.insert(P);
506286425Sdim      return true;
507286425Sdim    }
508286425Sdim    return false;
509286425Sdim  }
510286425Sdim}
511286425Sdim
512286425Sdim
513286425Sdimvoid HexagonCommonGEP::common() {
514286425Sdim  // The essence of this commoning is finding gep nodes that are equal.
515286425Sdim  // To do this we need to compare all pairs of nodes. To save time,
516286425Sdim  // first, partition the set of all nodes into sets of potentially equal
517286425Sdim  // nodes, and then compare pairs from within each partition.
518286425Sdim  typedef std::map<unsigned,NodeSet> NodeSetMap;
519286425Sdim  NodeSetMap MaybeEq;
520286425Sdim
521286425Sdim  for (NodeVect::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
522286425Sdim    GepNode *N = *I;
523286425Sdim    unsigned H = node_hash(N);
524286425Sdim    MaybeEq[H].insert(N);
525286425Sdim  }
526286425Sdim
527286425Sdim  // Compute the equivalence relation for the gep nodes.  Use two caches,
528286425Sdim  // one for equality and the other for non-equality.
529286425Sdim  NodeSymRel EqRel;  // Equality relation (as set of equivalence classes).
530286425Sdim  NodePairSet Eq, Ne;  // Caches.
531286425Sdim  for (NodeSetMap::iterator I = MaybeEq.begin(), E = MaybeEq.end();
532286425Sdim       I != E; ++I) {
533286425Sdim    NodeSet &S = I->second;
534286425Sdim    for (NodeSet::iterator NI = S.begin(), NE = S.end(); NI != NE; ++NI) {
535286425Sdim      GepNode *N = *NI;
536286425Sdim      // If node already has a class, then the class must have been created
537286425Sdim      // in a prior iteration of this loop. Since equality is transitive,
538286425Sdim      // nothing more will be added to that class, so skip it.
539286425Sdim      if (node_class(N, EqRel))
540286425Sdim        continue;
541286425Sdim
542286425Sdim      // Create a new class candidate now.
543286425Sdim      NodeSet C;
544286425Sdim      for (NodeSet::iterator NJ = std::next(NI); NJ != NE; ++NJ)
545286425Sdim        if (node_eq(N, *NJ, Eq, Ne))
546286425Sdim          C.insert(*NJ);
547286425Sdim      // If Tmp is empty, N would be the only element in it. Don't bother
548286425Sdim      // creating a class for it then.
549286425Sdim      if (!C.empty()) {
550286425Sdim        C.insert(N);  // Finalize the set before adding it to the relation.
551286425Sdim        std::pair<NodeSymRel::iterator, bool> Ins = EqRel.insert(C);
552286425Sdim        (void)Ins;
553286425Sdim        assert(Ins.second && "Cannot add a class");
554286425Sdim      }
555286425Sdim    }
556286425Sdim  }
557286425Sdim
558286425Sdim  DEBUG({
559286425Sdim    dbgs() << "Gep node equality:\n";
560286425Sdim    for (NodePairSet::iterator I = Eq.begin(), E = Eq.end(); I != E; ++I)
561286425Sdim      dbgs() << "{ " << I->first << ", " << I->second << " }\n";
562286425Sdim
563286425Sdim    dbgs() << "Gep equivalence classes:\n";
564286425Sdim    for (NodeSymRel::iterator I = EqRel.begin(), E = EqRel.end(); I != E; ++I) {
565286425Sdim      dbgs() << '{';
566286425Sdim      const NodeSet &S = *I;
567286425Sdim      for (NodeSet::const_iterator J = S.begin(), F = S.end(); J != F; ++J) {
568286425Sdim        if (J != S.begin())
569286425Sdim          dbgs() << ',';
570286425Sdim        dbgs() << ' ' << *J;
571286425Sdim      }
572286425Sdim      dbgs() << " }\n";
573286425Sdim    }
574286425Sdim  });
575286425Sdim
576286425Sdim
577286425Sdim  // Create a projection from a NodeSet to the minimal element in it.
578286425Sdim  typedef std::map<const NodeSet*,GepNode*> ProjMap;
579286425Sdim  ProjMap PM;
580286425Sdim  for (NodeSymRel::iterator I = EqRel.begin(), E = EqRel.end(); I != E; ++I) {
581286425Sdim    const NodeSet &S = *I;
582286425Sdim    GepNode *Min = *std::min_element(S.begin(), S.end(), NodeOrder);
583286425Sdim    std::pair<ProjMap::iterator,bool> Ins = PM.insert(std::make_pair(&S, Min));
584286425Sdim    (void)Ins;
585286425Sdim    assert(Ins.second && "Cannot add minimal element");
586286425Sdim
587286425Sdim    // Update the min element's flags, and user list.
588286425Sdim    uint32_t Flags = 0;
589286425Sdim    UseSet &MinUs = Uses[Min];
590286425Sdim    for (NodeSet::iterator J = S.begin(), F = S.end(); J != F; ++J) {
591286425Sdim      GepNode *N = *J;
592286425Sdim      uint32_t NF = N->Flags;
593286425Sdim      // If N is used, append all original values of N to the list of
594286425Sdim      // original values of Min.
595286425Sdim      if (NF & GepNode::Used)
596286425Sdim        MinUs.insert(Uses[N].begin(), Uses[N].end());
597286425Sdim      Flags |= NF;
598286425Sdim    }
599286425Sdim    if (MinUs.empty())
600286425Sdim      Uses.erase(Min);
601286425Sdim
602286425Sdim    // The collected flags should include all the flags from the min element.
603286425Sdim    assert((Min->Flags & Flags) == Min->Flags);
604286425Sdim    Min->Flags = Flags;
605286425Sdim  }
606286425Sdim
607286425Sdim  // Commoning: for each non-root gep node, replace "Parent" with the
608286425Sdim  // selected (minimum) node from the corresponding equivalence class.
609286425Sdim  // If a given parent does not have an equivalence class, leave it
610286425Sdim  // unchanged (it means that it's the only element in its class).
611286425Sdim  for (NodeVect::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
612286425Sdim    GepNode *N = *I;
613286425Sdim    if (N->Flags & GepNode::Root)
614286425Sdim      continue;
615286425Sdim    const NodeSet *PC = node_class(N->Parent, EqRel);
616286425Sdim    if (!PC)
617286425Sdim      continue;
618286425Sdim    ProjMap::iterator F = PM.find(PC);
619286425Sdim    if (F == PM.end())
620286425Sdim      continue;
621286425Sdim    // Found a replacement, use it.
622286425Sdim    GepNode *Rep = F->second;
623286425Sdim    N->Parent = Rep;
624286425Sdim  }
625286425Sdim
626286425Sdim  DEBUG(dbgs() << "Gep nodes after commoning:\n" << Nodes);
627286425Sdim
628286425Sdim  // Finally, erase the nodes that are no longer used.
629286425Sdim  NodeSet Erase;
630286425Sdim  for (NodeVect::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
631286425Sdim    GepNode *N = *I;
632286425Sdim    const NodeSet *PC = node_class(N, EqRel);
633286425Sdim    if (!PC)
634286425Sdim      continue;
635286425Sdim    ProjMap::iterator F = PM.find(PC);
636286425Sdim    if (F == PM.end())
637286425Sdim      continue;
638286425Sdim    if (N == F->second)
639286425Sdim      continue;
640286425Sdim    // Node for removal.
641286425Sdim    Erase.insert(*I);
642286425Sdim  }
643286425Sdim  NodeVect::iterator NewE = std::remove_if(Nodes.begin(), Nodes.end(),
644286425Sdim                                           in_set(Erase));
645286425Sdim  Nodes.resize(std::distance(Nodes.begin(), NewE));
646286425Sdim
647286425Sdim  DEBUG(dbgs() << "Gep nodes after post-commoning cleanup:\n" << Nodes);
648286425Sdim}
649286425Sdim
650286425Sdim
651286425Sdimnamespace {
652286425Sdim  template <typename T>
653286425Sdim  BasicBlock *nearest_common_dominator(DominatorTree *DT, T &Blocks) {
654286425Sdim    DEBUG({
655286425Sdim      dbgs() << "NCD of {";
656286425Sdim      for (typename T::iterator I = Blocks.begin(), E = Blocks.end();
657286425Sdim           I != E; ++I) {
658286425Sdim        if (!*I)
659286425Sdim          continue;
660286425Sdim        BasicBlock *B = cast<BasicBlock>(*I);
661286425Sdim        dbgs() << ' ' << B->getName();
662286425Sdim      }
663286425Sdim      dbgs() << " }\n";
664286425Sdim    });
665286425Sdim
666286425Sdim    // Allow null basic blocks in Blocks.  In such cases, return 0.
667286425Sdim    typename T::iterator I = Blocks.begin(), E = Blocks.end();
668286425Sdim    if (I == E || !*I)
669286425Sdim      return 0;
670286425Sdim    BasicBlock *Dom = cast<BasicBlock>(*I);
671286425Sdim    while (++I != E) {
672286425Sdim      BasicBlock *B = cast_or_null<BasicBlock>(*I);
673286425Sdim      Dom = B ? DT->findNearestCommonDominator(Dom, B) : 0;
674286425Sdim      if (!Dom)
675286425Sdim        return 0;
676286425Sdim    }
677286425Sdim    DEBUG(dbgs() << "computed:" << Dom->getName() << '\n');
678286425Sdim    return Dom;
679286425Sdim  }
680286425Sdim
681286425Sdim  template <typename T>
682286425Sdim  BasicBlock *nearest_common_dominatee(DominatorTree *DT, T &Blocks) {
683286425Sdim    // If two blocks, A and B, dominate a block C, then A dominates B,
684286425Sdim    // or B dominates A.
685286425Sdim    typename T::iterator I = Blocks.begin(), E = Blocks.end();
686286425Sdim    // Find the first non-null block.
687286425Sdim    while (I != E && !*I)
688286425Sdim      ++I;
689286425Sdim    if (I == E)
690286425Sdim      return DT->getRoot();
691286425Sdim    BasicBlock *DomB = cast<BasicBlock>(*I);
692286425Sdim    while (++I != E) {
693286425Sdim      if (!*I)
694286425Sdim        continue;
695286425Sdim      BasicBlock *B = cast<BasicBlock>(*I);
696286425Sdim      if (DT->dominates(B, DomB))
697286425Sdim        continue;
698286425Sdim      if (!DT->dominates(DomB, B))
699286425Sdim        return 0;
700286425Sdim      DomB = B;
701286425Sdim    }
702286425Sdim    return DomB;
703286425Sdim  }
704286425Sdim
705286425Sdim  // Find the first use in B of any value from Values. If no such use,
706286425Sdim  // return B->end().
707286425Sdim  template <typename T>
708286425Sdim  BasicBlock::iterator first_use_of_in_block(T &Values, BasicBlock *B) {
709286425Sdim    BasicBlock::iterator FirstUse = B->end(), BEnd = B->end();
710286425Sdim    typedef typename T::iterator iterator;
711286425Sdim    for (iterator I = Values.begin(), E = Values.end(); I != E; ++I) {
712286425Sdim      Value *V = *I;
713286425Sdim      // If V is used in a PHI node, the use belongs to the incoming block,
714286425Sdim      // not the block with the PHI node. In the incoming block, the use
715286425Sdim      // would be considered as being at the end of it, so it cannot
716286425Sdim      // influence the position of the first use (which is assumed to be
717286425Sdim      // at the end to start with).
718286425Sdim      if (isa<PHINode>(V))
719286425Sdim        continue;
720286425Sdim      if (!isa<Instruction>(V))
721286425Sdim        continue;
722286425Sdim      Instruction *In = cast<Instruction>(V);
723286425Sdim      if (In->getParent() != B)
724286425Sdim        continue;
725296417Sdim      BasicBlock::iterator It = In->getIterator();
726286425Sdim      if (std::distance(FirstUse, BEnd) < std::distance(It, BEnd))
727286425Sdim        FirstUse = It;
728286425Sdim    }
729286425Sdim    return FirstUse;
730286425Sdim  }
731286425Sdim
732286425Sdim  bool is_empty(const BasicBlock *B) {
733286425Sdim    return B->empty() || (&*B->begin() == B->getTerminator());
734286425Sdim  }
735286425Sdim}
736286425Sdim
737286425Sdim
738286425SdimBasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
739286425Sdim      NodeChildrenMap &NCM, NodeToValueMap &Loc) {
740286425Sdim  DEBUG(dbgs() << "Loc for node:" << Node << '\n');
741286425Sdim  // Recalculate the placement for Node, assuming that the locations of
742286425Sdim  // its children in Loc are valid.
743286425Sdim  // Return 0 if there is no valid placement for Node (for example, it
744286425Sdim  // uses an index value that is not available at the location required
745286425Sdim  // to dominate all children, etc.).
746286425Sdim
747286425Sdim  // Find the nearest common dominator for:
748286425Sdim  // - all users, if the node is used, and
749286425Sdim  // - all children.
750286425Sdim  ValueVect Bs;
751286425Sdim  if (Node->Flags & GepNode::Used) {
752286425Sdim    // Append all blocks with uses of the original values to the
753286425Sdim    // block vector Bs.
754286425Sdim    NodeToUsesMap::iterator UF = Uses.find(Node);
755286425Sdim    assert(UF != Uses.end() && "Used node with no use information");
756286425Sdim    UseSet &Us = UF->second;
757286425Sdim    for (UseSet::iterator I = Us.begin(), E = Us.end(); I != E; ++I) {
758286425Sdim      Use *U = *I;
759286425Sdim      User *R = U->getUser();
760286425Sdim      if (!isa<Instruction>(R))
761286425Sdim        continue;
762286425Sdim      BasicBlock *PB = isa<PHINode>(R)
763286425Sdim          ? cast<PHINode>(R)->getIncomingBlock(*U)
764286425Sdim          : cast<Instruction>(R)->getParent();
765286425Sdim      Bs.push_back(PB);
766286425Sdim    }
767286425Sdim  }
768286425Sdim  // Append the location of each child.
769286425Sdim  NodeChildrenMap::iterator CF = NCM.find(Node);
770286425Sdim  if (CF != NCM.end()) {
771286425Sdim    NodeVect &Cs = CF->second;
772286425Sdim    for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
773286425Sdim      GepNode *CN = *I;
774286425Sdim      NodeToValueMap::iterator LF = Loc.find(CN);
775286425Sdim      // If the child is only used in GEP instructions (i.e. is not used in
776286425Sdim      // non-GEP instructions), the nearest dominator computed for it may
777286425Sdim      // have been null. In such case it won't have a location available.
778286425Sdim      if (LF == Loc.end())
779286425Sdim        continue;
780286425Sdim      Bs.push_back(LF->second);
781286425Sdim    }
782286425Sdim  }
783286425Sdim
784286425Sdim  BasicBlock *DomB = nearest_common_dominator(DT, Bs);
785286425Sdim  if (!DomB)
786286425Sdim    return 0;
787286425Sdim  // Check if the index used by Node dominates the computed dominator.
788286425Sdim  Instruction *IdxI = dyn_cast<Instruction>(Node->Idx);
789286425Sdim  if (IdxI && !DT->dominates(IdxI->getParent(), DomB))
790286425Sdim    return 0;
791286425Sdim
792286425Sdim  // Avoid putting nodes into empty blocks.
793286425Sdim  while (is_empty(DomB)) {
794286425Sdim    DomTreeNode *N = (*DT)[DomB]->getIDom();
795286425Sdim    if (!N)
796286425Sdim      break;
797286425Sdim    DomB = N->getBlock();
798286425Sdim  }
799286425Sdim
800286425Sdim  // Otherwise, DomB is fine. Update the location map.
801286425Sdim  Loc[Node] = DomB;
802286425Sdim  return DomB;
803286425Sdim}
804286425Sdim
805286425Sdim
806286425SdimBasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *Node,
807286425Sdim      NodeChildrenMap &NCM, NodeToValueMap &Loc) {
808286425Sdim  DEBUG(dbgs() << "LocRec begin for node:" << Node << '\n');
809286425Sdim  // Recalculate the placement of Node, after recursively recalculating the
810286425Sdim  // placements of all its children.
811286425Sdim  NodeChildrenMap::iterator CF = NCM.find(Node);
812286425Sdim  if (CF != NCM.end()) {
813286425Sdim    NodeVect &Cs = CF->second;
814286425Sdim    for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I)
815286425Sdim      recalculatePlacementRec(*I, NCM, Loc);
816286425Sdim  }
817286425Sdim  BasicBlock *LB = recalculatePlacement(Node, NCM, Loc);
818286425Sdim  DEBUG(dbgs() << "LocRec end for node:" << Node << '\n');
819286425Sdim  return LB;
820286425Sdim}
821286425Sdim
822286425Sdim
823286425Sdimbool HexagonCommonGEP::isInvariantIn(Value *Val, Loop *L) {
824286425Sdim  if (isa<Constant>(Val) || isa<Argument>(Val))
825286425Sdim    return true;
826286425Sdim  Instruction *In = dyn_cast<Instruction>(Val);
827286425Sdim  if (!In)
828286425Sdim    return false;
829286425Sdim  BasicBlock *HdrB = L->getHeader(), *DefB = In->getParent();
830286425Sdim  return DT->properlyDominates(DefB, HdrB);
831286425Sdim}
832286425Sdim
833286425Sdim
834286425Sdimbool HexagonCommonGEP::isInvariantIn(GepNode *Node, Loop *L) {
835286425Sdim  if (Node->Flags & GepNode::Root)
836286425Sdim    if (!isInvariantIn(Node->BaseVal, L))
837286425Sdim      return false;
838286425Sdim  return isInvariantIn(Node->Idx, L);
839286425Sdim}
840286425Sdim
841286425Sdim
842286425Sdimbool HexagonCommonGEP::isInMainPath(BasicBlock *B, Loop *L) {
843286425Sdim  BasicBlock *HB = L->getHeader();
844286425Sdim  BasicBlock *LB = L->getLoopLatch();
845286425Sdim  // B must post-dominate the loop header or dominate the loop latch.
846286425Sdim  if (PDT->dominates(B, HB))
847286425Sdim    return true;
848286425Sdim  if (LB && DT->dominates(B, LB))
849286425Sdim    return true;
850286425Sdim  return false;
851286425Sdim}
852286425Sdim
853286425Sdim
854286425Sdimnamespace {
855286425Sdim  BasicBlock *preheader(DominatorTree *DT, Loop *L) {
856286425Sdim    if (BasicBlock *PH = L->getLoopPreheader())
857286425Sdim      return PH;
858286425Sdim    if (!OptSpeculate)
859286425Sdim      return 0;
860286425Sdim    DomTreeNode *DN = DT->getNode(L->getHeader());
861286425Sdim    if (!DN)
862286425Sdim      return 0;
863286425Sdim    return DN->getIDom()->getBlock();
864286425Sdim  }
865286425Sdim}
866286425Sdim
867286425Sdim
868286425SdimBasicBlock *HexagonCommonGEP::adjustForInvariance(GepNode *Node,
869286425Sdim      NodeChildrenMap &NCM, NodeToValueMap &Loc) {
870286425Sdim  // Find the "topmost" location for Node: it must be dominated by both,
871286425Sdim  // its parent (or the BaseVal, if it's a root node), and by the index
872286425Sdim  // value.
873286425Sdim  ValueVect Bs;
874286425Sdim  if (Node->Flags & GepNode::Root) {
875286425Sdim    if (Instruction *PIn = dyn_cast<Instruction>(Node->BaseVal))
876286425Sdim      Bs.push_back(PIn->getParent());
877286425Sdim  } else {
878286425Sdim    Bs.push_back(Loc[Node->Parent]);
879286425Sdim  }
880286425Sdim  if (Instruction *IIn = dyn_cast<Instruction>(Node->Idx))
881286425Sdim    Bs.push_back(IIn->getParent());
882286425Sdim  BasicBlock *TopB = nearest_common_dominatee(DT, Bs);
883286425Sdim
884286425Sdim  // Traverse the loop nest upwards until we find a loop in which Node
885286425Sdim  // is no longer invariant, or until we get to the upper limit of Node's
886286425Sdim  // placement. The traversal will also stop when a suitable "preheader"
887286425Sdim  // cannot be found for a given loop. The "preheader" may actually be
888286425Sdim  // a regular block outside of the loop (i.e. not guarded), in which case
889286425Sdim  // the Node will be speculated.
890286425Sdim  // For nodes that are not in the main path of the containing loop (i.e.
891286425Sdim  // are not executed in each iteration), do not move them out of the loop.
892286425Sdim  BasicBlock *LocB = cast_or_null<BasicBlock>(Loc[Node]);
893286425Sdim  if (LocB) {
894286425Sdim    Loop *Lp = LI->getLoopFor(LocB);
895286425Sdim    while (Lp) {
896286425Sdim      if (!isInvariantIn(Node, Lp) || !isInMainPath(LocB, Lp))
897286425Sdim        break;
898286425Sdim      BasicBlock *NewLoc = preheader(DT, Lp);
899286425Sdim      if (!NewLoc || !DT->dominates(TopB, NewLoc))
900286425Sdim        break;
901286425Sdim      Lp = Lp->getParentLoop();
902286425Sdim      LocB = NewLoc;
903286425Sdim    }
904286425Sdim  }
905286425Sdim  Loc[Node] = LocB;
906286425Sdim
907286425Sdim  // Recursively compute the locations of all children nodes.
908286425Sdim  NodeChildrenMap::iterator CF = NCM.find(Node);
909286425Sdim  if (CF != NCM.end()) {
910286425Sdim    NodeVect &Cs = CF->second;
911286425Sdim    for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I)
912286425Sdim      adjustForInvariance(*I, NCM, Loc);
913286425Sdim  }
914286425Sdim  return LocB;
915286425Sdim}
916286425Sdim
917286425Sdim
918286425Sdimnamespace {
919286425Sdim  struct LocationAsBlock {
920286425Sdim    LocationAsBlock(const NodeToValueMap &L) : Map(L) {}
921286425Sdim    const NodeToValueMap &Map;
922286425Sdim  };
923286425Sdim
924286425Sdim  raw_ostream &operator<< (raw_ostream &OS,
925286425Sdim                           const LocationAsBlock &Loc) LLVM_ATTRIBUTE_UNUSED ;
926286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const LocationAsBlock &Loc) {
927286425Sdim    for (NodeToValueMap::const_iterator I = Loc.Map.begin(), E = Loc.Map.end();
928286425Sdim         I != E; ++I) {
929286425Sdim      OS << I->first << " -> ";
930286425Sdim      BasicBlock *B = cast<BasicBlock>(I->second);
931286425Sdim      OS << B->getName() << '(' << B << ')';
932286425Sdim      OS << '\n';
933286425Sdim    }
934286425Sdim    return OS;
935286425Sdim  }
936286425Sdim
937286425Sdim  inline bool is_constant(GepNode *N) {
938286425Sdim    return isa<ConstantInt>(N->Idx);
939286425Sdim  }
940286425Sdim}
941286425Sdim
942286425Sdim
943286425Sdimvoid HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
944286425Sdim      NodeToValueMap &Loc) {
945286425Sdim  User *R = U->getUser();
946286425Sdim  DEBUG(dbgs() << "Separating chain for node (" << Node << ") user: "
947286425Sdim               << *R << '\n');
948286425Sdim  BasicBlock *PB = cast<Instruction>(R)->getParent();
949286425Sdim
950286425Sdim  GepNode *N = Node;
951286425Sdim  GepNode *C = 0, *NewNode = 0;
952286425Sdim  while (is_constant(N) && !(N->Flags & GepNode::Root)) {
953286425Sdim    // XXX if (single-use) dont-replicate;
954286425Sdim    GepNode *NewN = new (*Mem) GepNode(N);
955286425Sdim    Nodes.push_back(NewN);
956286425Sdim    Loc[NewN] = PB;
957286425Sdim
958286425Sdim    if (N == Node)
959286425Sdim      NewNode = NewN;
960286425Sdim    NewN->Flags &= ~GepNode::Used;
961286425Sdim    if (C)
962286425Sdim      C->Parent = NewN;
963286425Sdim    C = NewN;
964286425Sdim    N = N->Parent;
965286425Sdim  }
966286425Sdim  if (!NewNode)
967286425Sdim    return;
968286425Sdim
969286425Sdim  // Move over all uses that share the same user as U from Node to NewNode.
970286425Sdim  NodeToUsesMap::iterator UF = Uses.find(Node);
971286425Sdim  assert(UF != Uses.end());
972286425Sdim  UseSet &Us = UF->second;
973286425Sdim  UseSet NewUs;
974286425Sdim  for (UseSet::iterator I = Us.begin(); I != Us.end(); ) {
975286425Sdim    User *S = (*I)->getUser();
976286425Sdim    UseSet::iterator Nx = std::next(I);
977286425Sdim    if (S == R) {
978286425Sdim      NewUs.insert(*I);
979286425Sdim      Us.erase(I);
980286425Sdim    }
981286425Sdim    I = Nx;
982286425Sdim  }
983286425Sdim  if (Us.empty()) {
984286425Sdim    Node->Flags &= ~GepNode::Used;
985286425Sdim    Uses.erase(UF);
986286425Sdim  }
987286425Sdim
988286425Sdim  // Should at least have U in NewUs.
989286425Sdim  NewNode->Flags |= GepNode::Used;
990286425Sdim  DEBUG(dbgs() << "new node: " << NewNode << "  " << *NewNode << '\n');
991286425Sdim  assert(!NewUs.empty());
992286425Sdim  Uses[NewNode] = NewUs;
993286425Sdim}
994286425Sdim
995286425Sdim
996286425Sdimvoid HexagonCommonGEP::separateConstantChains(GepNode *Node,
997286425Sdim      NodeChildrenMap &NCM, NodeToValueMap &Loc) {
998286425Sdim  // First approximation: extract all chains.
999286425Sdim  NodeSet Ns;
1000286425Sdim  nodes_for_root(Node, NCM, Ns);
1001286425Sdim
1002286425Sdim  DEBUG(dbgs() << "Separating constant chains for node: " << Node << '\n');
1003286425Sdim  // Collect all used nodes together with the uses from loads and stores,
1004286425Sdim  // where the GEP node could be folded into the load/store instruction.
1005286425Sdim  NodeToUsesMap FNs; // Foldable nodes.
1006286425Sdim  for (NodeSet::iterator I = Ns.begin(), E = Ns.end(); I != E; ++I) {
1007286425Sdim    GepNode *N = *I;
1008286425Sdim    if (!(N->Flags & GepNode::Used))
1009286425Sdim      continue;
1010286425Sdim    NodeToUsesMap::iterator UF = Uses.find(N);
1011286425Sdim    assert(UF != Uses.end());
1012286425Sdim    UseSet &Us = UF->second;
1013286425Sdim    // Loads/stores that use the node N.
1014286425Sdim    UseSet LSs;
1015286425Sdim    for (UseSet::iterator J = Us.begin(), F = Us.end(); J != F; ++J) {
1016286425Sdim      Use *U = *J;
1017286425Sdim      User *R = U->getUser();
1018286425Sdim      // We're interested in uses that provide the address. It can happen
1019286425Sdim      // that the value may also be provided via GEP, but we won't handle
1020286425Sdim      // those cases here for now.
1021286425Sdim      if (LoadInst *Ld = dyn_cast<LoadInst>(R)) {
1022286425Sdim        unsigned PtrX = LoadInst::getPointerOperandIndex();
1023286425Sdim        if (&Ld->getOperandUse(PtrX) == U)
1024286425Sdim          LSs.insert(U);
1025286425Sdim      } else if (StoreInst *St = dyn_cast<StoreInst>(R)) {
1026286425Sdim        unsigned PtrX = StoreInst::getPointerOperandIndex();
1027286425Sdim        if (&St->getOperandUse(PtrX) == U)
1028286425Sdim          LSs.insert(U);
1029286425Sdim      }
1030286425Sdim    }
1031286425Sdim    // Even if the total use count is 1, separating the chain may still be
1032286425Sdim    // beneficial, since the constant chain may be longer than the GEP alone
1033286425Sdim    // would be (e.g. if the parent node has a constant index and also has
1034286425Sdim    // other children).
1035286425Sdim    if (!LSs.empty())
1036286425Sdim      FNs.insert(std::make_pair(N, LSs));
1037286425Sdim  }
1038286425Sdim
1039286425Sdim  DEBUG(dbgs() << "Nodes with foldable users:\n" << FNs);
1040286425Sdim
1041286425Sdim  for (NodeToUsesMap::iterator I = FNs.begin(), E = FNs.end(); I != E; ++I) {
1042286425Sdim    GepNode *N = I->first;
1043286425Sdim    UseSet &Us = I->second;
1044286425Sdim    for (UseSet::iterator J = Us.begin(), F = Us.end(); J != F; ++J)
1045286425Sdim      separateChainForNode(N, *J, Loc);
1046286425Sdim  }
1047286425Sdim}
1048286425Sdim
1049286425Sdim
1050286425Sdimvoid HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
1051286425Sdim  // Compute the inverse of the Node.Parent links. Also, collect the set
1052286425Sdim  // of root nodes.
1053286425Sdim  NodeChildrenMap NCM;
1054286425Sdim  NodeVect Roots;
1055286425Sdim  invert_find_roots(Nodes, NCM, Roots);
1056286425Sdim
1057286425Sdim  // Compute the initial placement determined by the users' locations, and
1058286425Sdim  // the locations of the child nodes.
1059286425Sdim  for (NodeVect::iterator I = Roots.begin(), E = Roots.end(); I != E; ++I)
1060286425Sdim    recalculatePlacementRec(*I, NCM, Loc);
1061286425Sdim
1062286425Sdim  DEBUG(dbgs() << "Initial node placement:\n" << LocationAsBlock(Loc));
1063286425Sdim
1064286425Sdim  if (OptEnableInv) {
1065286425Sdim    for (NodeVect::iterator I = Roots.begin(), E = Roots.end(); I != E; ++I)
1066286425Sdim      adjustForInvariance(*I, NCM, Loc);
1067286425Sdim
1068286425Sdim    DEBUG(dbgs() << "Node placement after adjustment for invariance:\n"
1069286425Sdim                 << LocationAsBlock(Loc));
1070286425Sdim  }
1071286425Sdim  if (OptEnableConst) {
1072286425Sdim    for (NodeVect::iterator I = Roots.begin(), E = Roots.end(); I != E; ++I)
1073286425Sdim      separateConstantChains(*I, NCM, Loc);
1074286425Sdim  }
1075286425Sdim  DEBUG(dbgs() << "Node use information:\n" << Uses);
1076286425Sdim
1077286425Sdim  // At the moment, there is no further refinement of the initial placement.
1078286425Sdim  // Such a refinement could include splitting the nodes if they are placed
1079286425Sdim  // too far from some of its users.
1080286425Sdim
1081286425Sdim  DEBUG(dbgs() << "Final node placement:\n" << LocationAsBlock(Loc));
1082286425Sdim}
1083286425Sdim
1084286425Sdim
1085286425SdimValue *HexagonCommonGEP::fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
1086286425Sdim      BasicBlock *LocB) {
1087286425Sdim  DEBUG(dbgs() << "Fabricating GEP in " << LocB->getName()
1088286425Sdim               << " for nodes:\n" << NA);
1089286425Sdim  unsigned Num = NA.size();
1090286425Sdim  GepNode *RN = NA[0];
1091286425Sdim  assert((RN->Flags & GepNode::Root) && "Creating GEP for non-root");
1092286425Sdim
1093286425Sdim  Value *NewInst = 0;
1094286425Sdim  Value *Input = RN->BaseVal;
1095286425Sdim  Value **IdxList = new Value*[Num+1];
1096286425Sdim  unsigned nax = 0;
1097286425Sdim  do {
1098286425Sdim    unsigned IdxC = 0;
1099286425Sdim    // If the type of the input of the first node is not a pointer,
1100286425Sdim    // we need to add an artificial i32 0 to the indices (because the
1101286425Sdim    // actual input in the IR will be a pointer).
1102286425Sdim    if (!NA[nax]->PTy->isPointerTy()) {
1103286425Sdim      Type *Int32Ty = Type::getInt32Ty(*Ctx);
1104286425Sdim      IdxList[IdxC++] = ConstantInt::get(Int32Ty, 0);
1105286425Sdim    }
1106286425Sdim
1107286425Sdim    // Keep adding indices from NA until we have to stop and generate
1108286425Sdim    // an "intermediate" GEP.
1109286425Sdim    while (++nax <= Num) {
1110286425Sdim      GepNode *N = NA[nax-1];
1111286425Sdim      IdxList[IdxC++] = N->Idx;
1112286425Sdim      if (nax < Num) {
1113286425Sdim        // We have to stop, if the expected type of the output of this node
1114286425Sdim        // is not the same as the input type of the next node.
1115286425Sdim        Type *NextTy = next_type(N->PTy, N->Idx);
1116286425Sdim        if (NextTy != NA[nax]->PTy)
1117286425Sdim          break;
1118286425Sdim      }
1119286425Sdim    }
1120286425Sdim    ArrayRef<Value*> A(IdxList, IdxC);
1121286425Sdim    Type *InpTy = Input->getType();
1122286425Sdim    Type *ElTy = cast<PointerType>(InpTy->getScalarType())->getElementType();
1123296417Sdim    NewInst = GetElementPtrInst::Create(ElTy, Input, A, "cgep", &*At);
1124286425Sdim    DEBUG(dbgs() << "new GEP: " << *NewInst << '\n');
1125286425Sdim    Input = NewInst;
1126286425Sdim  } while (nax <= Num);
1127286425Sdim
1128286425Sdim  delete[] IdxList;
1129286425Sdim  return NewInst;
1130286425Sdim}
1131286425Sdim
1132286425Sdim
1133286425Sdimvoid HexagonCommonGEP::getAllUsersForNode(GepNode *Node, ValueVect &Values,
1134286425Sdim      NodeChildrenMap &NCM) {
1135286425Sdim  NodeVect Work;
1136286425Sdim  Work.push_back(Node);
1137286425Sdim
1138286425Sdim  while (!Work.empty()) {
1139286425Sdim    NodeVect::iterator First = Work.begin();
1140286425Sdim    GepNode *N = *First;
1141286425Sdim    Work.erase(First);
1142286425Sdim    if (N->Flags & GepNode::Used) {
1143286425Sdim      NodeToUsesMap::iterator UF = Uses.find(N);
1144286425Sdim      assert(UF != Uses.end() && "No use information for used node");
1145286425Sdim      UseSet &Us = UF->second;
1146286425Sdim      for (UseSet::iterator I = Us.begin(), E = Us.end(); I != E; ++I)
1147286425Sdim        Values.push_back((*I)->getUser());
1148286425Sdim    }
1149286425Sdim    NodeChildrenMap::iterator CF = NCM.find(N);
1150286425Sdim    if (CF != NCM.end()) {
1151286425Sdim      NodeVect &Cs = CF->second;
1152286425Sdim      Work.insert(Work.end(), Cs.begin(), Cs.end());
1153286425Sdim    }
1154286425Sdim  }
1155286425Sdim}
1156286425Sdim
1157286425Sdim
1158286425Sdimvoid HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
1159286425Sdim  DEBUG(dbgs() << "Nodes before materialization:\n" << Nodes << '\n');
1160286425Sdim  NodeChildrenMap NCM;
1161286425Sdim  NodeVect Roots;
1162286425Sdim  // Compute the inversion again, since computing placement could alter
1163286425Sdim  // "parent" relation between nodes.
1164286425Sdim  invert_find_roots(Nodes, NCM, Roots);
1165286425Sdim
1166286425Sdim  while (!Roots.empty()) {
1167286425Sdim    NodeVect::iterator First = Roots.begin();
1168286425Sdim    GepNode *Root = *First, *Last = *First;
1169286425Sdim    Roots.erase(First);
1170286425Sdim
1171286425Sdim    NodeVect NA;  // Nodes to assemble.
1172286425Sdim    // Append to NA all child nodes up to (and including) the first child
1173286425Sdim    // that:
1174286425Sdim    // (1) has more than 1 child, or
1175286425Sdim    // (2) is used, or
1176286425Sdim    // (3) has a child located in a different block.
1177286425Sdim    bool LastUsed = false;
1178286425Sdim    unsigned LastCN = 0;
1179286425Sdim    // The location may be null if the computation failed (it can legitimately
1180286425Sdim    // happen for nodes created from dead GEPs).
1181286425Sdim    Value *LocV = Loc[Last];
1182286425Sdim    if (!LocV)
1183286425Sdim      continue;
1184286425Sdim    BasicBlock *LastB = cast<BasicBlock>(LocV);
1185286425Sdim    do {
1186286425Sdim      NA.push_back(Last);
1187286425Sdim      LastUsed = (Last->Flags & GepNode::Used);
1188286425Sdim      if (LastUsed)
1189286425Sdim        break;
1190286425Sdim      NodeChildrenMap::iterator CF = NCM.find(Last);
1191286425Sdim      LastCN = (CF != NCM.end()) ? CF->second.size() : 0;
1192286425Sdim      if (LastCN != 1)
1193286425Sdim        break;
1194286425Sdim      GepNode *Child = CF->second.front();
1195286425Sdim      BasicBlock *ChildB = cast_or_null<BasicBlock>(Loc[Child]);
1196286425Sdim      if (ChildB != 0 && LastB != ChildB)
1197286425Sdim        break;
1198286425Sdim      Last = Child;
1199286425Sdim    } while (true);
1200286425Sdim
1201296417Sdim    BasicBlock::iterator InsertAt = LastB->getTerminator()->getIterator();
1202286425Sdim    if (LastUsed || LastCN > 0) {
1203286425Sdim      ValueVect Urs;
1204286425Sdim      getAllUsersForNode(Root, Urs, NCM);
1205286425Sdim      BasicBlock::iterator FirstUse = first_use_of_in_block(Urs, LastB);
1206286425Sdim      if (FirstUse != LastB->end())
1207286425Sdim        InsertAt = FirstUse;
1208286425Sdim    }
1209286425Sdim
1210286425Sdim    // Generate a new instruction for NA.
1211286425Sdim    Value *NewInst = fabricateGEP(NA, InsertAt, LastB);
1212286425Sdim
1213286425Sdim    // Convert all the children of Last node into roots, and append them
1214286425Sdim    // to the Roots list.
1215286425Sdim    if (LastCN > 0) {
1216286425Sdim      NodeVect &Cs = NCM[Last];
1217286425Sdim      for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
1218286425Sdim        GepNode *CN = *I;
1219286425Sdim        CN->Flags &= ~GepNode::Internal;
1220286425Sdim        CN->Flags |= GepNode::Root;
1221286425Sdim        CN->BaseVal = NewInst;
1222286425Sdim        Roots.push_back(CN);
1223286425Sdim      }
1224286425Sdim    }
1225286425Sdim
1226286425Sdim    // Lastly, if the Last node was used, replace all uses with the new GEP.
1227286425Sdim    // The uses reference the original GEP values.
1228286425Sdim    if (LastUsed) {
1229286425Sdim      NodeToUsesMap::iterator UF = Uses.find(Last);
1230286425Sdim      assert(UF != Uses.end() && "No use information found");
1231286425Sdim      UseSet &Us = UF->second;
1232286425Sdim      for (UseSet::iterator I = Us.begin(), E = Us.end(); I != E; ++I) {
1233286425Sdim        Use *U = *I;
1234286425Sdim        U->set(NewInst);
1235286425Sdim      }
1236286425Sdim    }
1237286425Sdim  }
1238286425Sdim}
1239286425Sdim
1240286425Sdim
1241286425Sdimvoid HexagonCommonGEP::removeDeadCode() {
1242286425Sdim  ValueVect BO;
1243286425Sdim  BO.push_back(&Fn->front());
1244286425Sdim
1245286425Sdim  for (unsigned i = 0; i < BO.size(); ++i) {
1246286425Sdim    BasicBlock *B = cast<BasicBlock>(BO[i]);
1247286425Sdim    DomTreeNode *N = DT->getNode(B);
1248286425Sdim    typedef GraphTraits<DomTreeNode*> GTN;
1249286425Sdim    typedef GTN::ChildIteratorType Iter;
1250286425Sdim    for (Iter I = GTN::child_begin(N), E = GTN::child_end(N); I != E; ++I)
1251286425Sdim      BO.push_back((*I)->getBlock());
1252286425Sdim  }
1253286425Sdim
1254286425Sdim  for (unsigned i = BO.size(); i > 0; --i) {
1255286425Sdim    BasicBlock *B = cast<BasicBlock>(BO[i-1]);
1256286425Sdim    BasicBlock::InstListType &IL = B->getInstList();
1257286425Sdim    typedef BasicBlock::InstListType::reverse_iterator reverse_iterator;
1258286425Sdim    ValueVect Ins;
1259286425Sdim    for (reverse_iterator I = IL.rbegin(), E = IL.rend(); I != E; ++I)
1260286425Sdim      Ins.push_back(&*I);
1261286425Sdim    for (ValueVect::iterator I = Ins.begin(), E = Ins.end(); I != E; ++I) {
1262286425Sdim      Instruction *In = cast<Instruction>(*I);
1263286425Sdim      if (isInstructionTriviallyDead(In))
1264286425Sdim        In->eraseFromParent();
1265286425Sdim    }
1266286425Sdim  }
1267286425Sdim}
1268286425Sdim
1269286425Sdim
1270286425Sdimbool HexagonCommonGEP::runOnFunction(Function &F) {
1271286425Sdim  // For now bail out on C++ exception handling.
1272286425Sdim  for (Function::iterator A = F.begin(), Z = F.end(); A != Z; ++A)
1273286425Sdim    for (BasicBlock::iterator I = A->begin(), E = A->end(); I != E; ++I)
1274286425Sdim      if (isa<InvokeInst>(I) || isa<LandingPadInst>(I))
1275286425Sdim        return false;
1276286425Sdim
1277286425Sdim  Fn = &F;
1278286425Sdim  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1279286425Sdim  PDT = &getAnalysis<PostDominatorTree>();
1280286425Sdim  LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1281286425Sdim  Ctx = &F.getContext();
1282286425Sdim
1283286425Sdim  Nodes.clear();
1284286425Sdim  Uses.clear();
1285286425Sdim  NodeOrder.clear();
1286286425Sdim
1287286425Sdim  SpecificBumpPtrAllocator<GepNode> Allocator;
1288286425Sdim  Mem = &Allocator;
1289286425Sdim
1290286425Sdim  collect();
1291286425Sdim  common();
1292286425Sdim
1293286425Sdim  NodeToValueMap Loc;
1294286425Sdim  computeNodePlacement(Loc);
1295286425Sdim  materialize(Loc);
1296286425Sdim  removeDeadCode();
1297286425Sdim
1298286425Sdim#ifdef XDEBUG
1299286425Sdim  // Run this only when expensive checks are enabled.
1300286425Sdim  verifyFunction(F);
1301286425Sdim#endif
1302286425Sdim  return true;
1303286425Sdim}
1304286425Sdim
1305286425Sdim
1306286425Sdimnamespace llvm {
1307286425Sdim  FunctionPass *createHexagonCommonGEP() {
1308286425Sdim    return new HexagonCommonGEP();
1309286425Sdim  }
1310286425Sdim}
1311