HexagonCommonGEP.cpp revision 321369
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
12314564Sdim#include "llvm/ADT/ArrayRef.h"
13286425Sdim#include "llvm/ADT/FoldingSet.h"
14286425Sdim#include "llvm/ADT/STLExtras.h"
15314564Sdim#include "llvm/ADT/StringRef.h"
16286425Sdim#include "llvm/Analysis/LoopInfo.h"
17286425Sdim#include "llvm/Analysis/PostDominators.h"
18314564Sdim#include "llvm/IR/BasicBlock.h"
19314564Sdim#include "llvm/IR/Constant.h"
20286425Sdim#include "llvm/IR/Constants.h"
21314564Sdim#include "llvm/IR/DerivedTypes.h"
22286425Sdim#include "llvm/IR/Dominators.h"
23286425Sdim#include "llvm/IR/Function.h"
24314564Sdim#include "llvm/IR/Instruction.h"
25286425Sdim#include "llvm/IR/Instructions.h"
26314564Sdim#include "llvm/IR/Type.h"
27314564Sdim#include "llvm/IR/Use.h"
28314564Sdim#include "llvm/IR/User.h"
29314564Sdim#include "llvm/IR/Value.h"
30286425Sdim#include "llvm/IR/Verifier.h"
31314564Sdim#include "llvm/Pass.h"
32286425Sdim#include "llvm/Support/Allocator.h"
33314564Sdim#include "llvm/Support/Casting.h"
34286425Sdim#include "llvm/Support/CommandLine.h"
35314564Sdim#include "llvm/Support/Compiler.h"
36286425Sdim#include "llvm/Support/Debug.h"
37286425Sdim#include "llvm/Support/raw_ostream.h"
38286425Sdim#include "llvm/Transforms/Utils/Local.h"
39314564Sdim#include <algorithm>
40314564Sdim#include <cassert>
41314564Sdim#include <cstddef>
42314564Sdim#include <cstdint>
43314564Sdim#include <iterator>
44286425Sdim#include <map>
45286425Sdim#include <set>
46314564Sdim#include <utility>
47286425Sdim#include <vector>
48286425Sdim
49286425Sdimusing namespace llvm;
50286425Sdim
51286425Sdimstatic cl::opt<bool> OptSpeculate("commgep-speculate", cl::init(true),
52286425Sdim  cl::Hidden, cl::ZeroOrMore);
53286425Sdim
54286425Sdimstatic cl::opt<bool> OptEnableInv("commgep-inv", cl::init(true), cl::Hidden,
55286425Sdim  cl::ZeroOrMore);
56286425Sdim
57286425Sdimstatic cl::opt<bool> OptEnableConst("commgep-const", cl::init(true),
58286425Sdim  cl::Hidden, cl::ZeroOrMore);
59286425Sdim
60286425Sdimnamespace llvm {
61314564Sdim
62286425Sdim  void initializeHexagonCommonGEPPass(PassRegistry&);
63286425Sdim
64314564Sdim} // end namespace llvm
65314564Sdim
66286425Sdimnamespace {
67314564Sdim
68286425Sdim  struct GepNode;
69286425Sdim  typedef std::set<GepNode*> NodeSet;
70286425Sdim  typedef std::map<GepNode*,Value*> NodeToValueMap;
71286425Sdim  typedef std::vector<GepNode*> NodeVect;
72286425Sdim  typedef std::map<GepNode*,NodeVect> NodeChildrenMap;
73286425Sdim  typedef std::set<Use*> UseSet;
74286425Sdim  typedef std::map<GepNode*,UseSet> NodeToUsesMap;
75286425Sdim
76286425Sdim  // Numbering map for gep nodes. Used to keep track of ordering for
77286425Sdim  // gep nodes.
78296417Sdim  struct NodeOrdering {
79314564Sdim    NodeOrdering() = default;
80286425Sdim
81296417Sdim    void insert(const GepNode *N) { Map.insert(std::make_pair(N, ++LastNum)); }
82296417Sdim    void clear() { Map.clear(); }
83296417Sdim
84296417Sdim    bool operator()(const GepNode *N1, const GepNode *N2) const {
85296417Sdim      auto F1 = Map.find(N1), F2 = Map.find(N2);
86296417Sdim      assert(F1 != Map.end() && F2 != Map.end());
87286425Sdim      return F1->second < F2->second;
88286425Sdim    }
89296417Sdim
90286425Sdim  private:
91296417Sdim    std::map<const GepNode *, unsigned> Map;
92314564Sdim    unsigned LastNum = 0;
93286425Sdim  };
94286425Sdim
95286425Sdim  class HexagonCommonGEP : public FunctionPass {
96286425Sdim  public:
97286425Sdim    static char ID;
98314564Sdim
99286425Sdim    HexagonCommonGEP() : FunctionPass(ID) {
100286425Sdim      initializeHexagonCommonGEPPass(*PassRegistry::getPassRegistry());
101286425Sdim    }
102286425Sdim
103314564Sdim    bool runOnFunction(Function &F) override;
104314564Sdim    StringRef getPassName() const override { return "Hexagon Common GEP"; }
105314564Sdim
106314564Sdim    void getAnalysisUsage(AnalysisUsage &AU) const override {
107286425Sdim      AU.addRequired<DominatorTreeWrapperPass>();
108286425Sdim      AU.addPreserved<DominatorTreeWrapperPass>();
109309124Sdim      AU.addRequired<PostDominatorTreeWrapperPass>();
110309124Sdim      AU.addPreserved<PostDominatorTreeWrapperPass>();
111286425Sdim      AU.addRequired<LoopInfoWrapperPass>();
112286425Sdim      AU.addPreserved<LoopInfoWrapperPass>();
113286425Sdim      FunctionPass::getAnalysisUsage(AU);
114286425Sdim    }
115286425Sdim
116286425Sdim  private:
117286425Sdim    typedef std::map<Value*,GepNode*> ValueToNodeMap;
118286425Sdim    typedef std::vector<Value*> ValueVect;
119286425Sdim    typedef std::map<GepNode*,ValueVect> NodeToValuesMap;
120286425Sdim
121286425Sdim    void getBlockTraversalOrder(BasicBlock *Root, ValueVect &Order);
122286425Sdim    bool isHandledGepForm(GetElementPtrInst *GepI);
123286425Sdim    void processGepInst(GetElementPtrInst *GepI, ValueToNodeMap &NM);
124286425Sdim    void collect();
125286425Sdim    void common();
126286425Sdim
127286425Sdim    BasicBlock *recalculatePlacement(GepNode *Node, NodeChildrenMap &NCM,
128286425Sdim                                     NodeToValueMap &Loc);
129286425Sdim    BasicBlock *recalculatePlacementRec(GepNode *Node, NodeChildrenMap &NCM,
130286425Sdim                                        NodeToValueMap &Loc);
131286425Sdim    bool isInvariantIn(Value *Val, Loop *L);
132286425Sdim    bool isInvariantIn(GepNode *Node, Loop *L);
133286425Sdim    bool isInMainPath(BasicBlock *B, Loop *L);
134286425Sdim    BasicBlock *adjustForInvariance(GepNode *Node, NodeChildrenMap &NCM,
135286425Sdim                                    NodeToValueMap &Loc);
136286425Sdim    void separateChainForNode(GepNode *Node, Use *U, NodeToValueMap &Loc);
137286425Sdim    void separateConstantChains(GepNode *Node, NodeChildrenMap &NCM,
138286425Sdim                                NodeToValueMap &Loc);
139286425Sdim    void computeNodePlacement(NodeToValueMap &Loc);
140286425Sdim
141286425Sdim    Value *fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
142286425Sdim                        BasicBlock *LocB);
143286425Sdim    void getAllUsersForNode(GepNode *Node, ValueVect &Values,
144286425Sdim                            NodeChildrenMap &NCM);
145286425Sdim    void materialize(NodeToValueMap &Loc);
146286425Sdim
147286425Sdim    void removeDeadCode();
148286425Sdim
149286425Sdim    NodeVect Nodes;
150286425Sdim    NodeToUsesMap Uses;
151286425Sdim    NodeOrdering NodeOrder;   // Node ordering, for deterministic behavior.
152286425Sdim    SpecificBumpPtrAllocator<GepNode> *Mem;
153286425Sdim    LLVMContext *Ctx;
154286425Sdim    LoopInfo *LI;
155286425Sdim    DominatorTree *DT;
156286425Sdim    PostDominatorTree *PDT;
157286425Sdim    Function *Fn;
158286425Sdim  };
159286425Sdim
160314564Sdim} // end anonymous namespace
161286425Sdim
162286425Sdimchar HexagonCommonGEP::ID = 0;
163286425SdimINITIALIZE_PASS_BEGIN(HexagonCommonGEP, "hcommgep", "Hexagon Common GEP",
164286425Sdim      false, false)
165286425SdimINITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
166309124SdimINITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
167286425SdimINITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
168286425SdimINITIALIZE_PASS_END(HexagonCommonGEP, "hcommgep", "Hexagon Common GEP",
169286425Sdim      false, false)
170286425Sdim
171286425Sdimnamespace {
172314564Sdim
173286425Sdim  struct GepNode {
174286425Sdim    enum {
175286425Sdim      None      = 0,
176286425Sdim      Root      = 0x01,
177286425Sdim      Internal  = 0x02,
178321369Sdim      Used      = 0x04,
179321369Sdim      InBounds  = 0x08
180286425Sdim    };
181286425Sdim
182286425Sdim    uint32_t Flags;
183286425Sdim    union {
184286425Sdim      GepNode *Parent;
185286425Sdim      Value *BaseVal;
186286425Sdim    };
187286425Sdim    Value *Idx;
188286425Sdim    Type *PTy;  // Type of the pointer operand.
189286425Sdim
190314564Sdim    GepNode() : Flags(0), Parent(nullptr), Idx(nullptr), PTy(nullptr) {}
191286425Sdim    GepNode(const GepNode *N) : Flags(N->Flags), Idx(N->Idx), PTy(N->PTy) {
192286425Sdim      if (Flags & Root)
193286425Sdim        BaseVal = N->BaseVal;
194286425Sdim      else
195286425Sdim        Parent = N->Parent;
196286425Sdim    }
197314564Sdim
198286425Sdim    friend raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN);
199286425Sdim  };
200286425Sdim
201286425Sdim  Type *next_type(Type *Ty, Value *Idx) {
202314564Sdim    if (auto *PTy = dyn_cast<PointerType>(Ty))
203314564Sdim      return PTy->getElementType();
204286425Sdim    // Advance the type.
205286425Sdim    if (!Ty->isStructTy()) {
206286425Sdim      Type *NexTy = cast<SequentialType>(Ty)->getElementType();
207286425Sdim      return NexTy;
208286425Sdim    }
209286425Sdim    // Otherwise it is a struct type.
210286425Sdim    ConstantInt *CI = dyn_cast<ConstantInt>(Idx);
211286425Sdim    assert(CI && "Struct type with non-constant index");
212286425Sdim    int64_t i = CI->getValue().getSExtValue();
213286425Sdim    Type *NextTy = cast<StructType>(Ty)->getElementType(i);
214286425Sdim    return NextTy;
215286425Sdim  }
216286425Sdim
217286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN) {
218286425Sdim    OS << "{ {";
219286425Sdim    bool Comma = false;
220286425Sdim    if (GN.Flags & GepNode::Root) {
221286425Sdim      OS << "root";
222286425Sdim      Comma = true;
223286425Sdim    }
224286425Sdim    if (GN.Flags & GepNode::Internal) {
225286425Sdim      if (Comma)
226286425Sdim        OS << ',';
227286425Sdim      OS << "internal";
228286425Sdim      Comma = true;
229286425Sdim    }
230286425Sdim    if (GN.Flags & GepNode::Used) {
231286425Sdim      if (Comma)
232286425Sdim        OS << ',';
233286425Sdim      OS << "used";
234286425Sdim    }
235321369Sdim    if (GN.Flags & GepNode::InBounds) {
236321369Sdim      if (Comma)
237321369Sdim        OS << ',';
238321369Sdim      OS << "inbounds";
239321369Sdim    }
240286425Sdim    OS << "} ";
241286425Sdim    if (GN.Flags & GepNode::Root)
242286425Sdim      OS << "BaseVal:" << GN.BaseVal->getName() << '(' << GN.BaseVal << ')';
243286425Sdim    else
244286425Sdim      OS << "Parent:" << GN.Parent;
245286425Sdim
246286425Sdim    OS << " Idx:";
247286425Sdim    if (ConstantInt *CI = dyn_cast<ConstantInt>(GN.Idx))
248286425Sdim      OS << CI->getValue().getSExtValue();
249286425Sdim    else if (GN.Idx->hasName())
250286425Sdim      OS << GN.Idx->getName();
251286425Sdim    else
252286425Sdim      OS << "<anon> =" << *GN.Idx;
253286425Sdim
254286425Sdim    OS << " PTy:";
255286425Sdim    if (GN.PTy->isStructTy()) {
256286425Sdim      StructType *STy = cast<StructType>(GN.PTy);
257286425Sdim      if (!STy->isLiteral())
258286425Sdim        OS << GN.PTy->getStructName();
259286425Sdim      else
260286425Sdim        OS << "<anon-struct>:" << *STy;
261286425Sdim    }
262286425Sdim    else
263286425Sdim      OS << *GN.PTy;
264286425Sdim    OS << " }";
265286425Sdim    return OS;
266286425Sdim  }
267286425Sdim
268286425Sdim  template <typename NodeContainer>
269286425Sdim  void dump_node_container(raw_ostream &OS, const NodeContainer &S) {
270286425Sdim    typedef typename NodeContainer::const_iterator const_iterator;
271286425Sdim    for (const_iterator I = S.begin(), E = S.end(); I != E; ++I)
272286425Sdim      OS << *I << ' ' << **I << '\n';
273286425Sdim  }
274286425Sdim
275286425Sdim  raw_ostream &operator<< (raw_ostream &OS,
276286425Sdim                           const NodeVect &S) LLVM_ATTRIBUTE_UNUSED;
277286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const NodeVect &S) {
278286425Sdim    dump_node_container(OS, S);
279286425Sdim    return OS;
280286425Sdim  }
281286425Sdim
282286425Sdim  raw_ostream &operator<< (raw_ostream &OS,
283286425Sdim                           const NodeToUsesMap &M) LLVM_ATTRIBUTE_UNUSED;
284286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const NodeToUsesMap &M){
285286425Sdim    typedef NodeToUsesMap::const_iterator const_iterator;
286286425Sdim    for (const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
287286425Sdim      const UseSet &Us = I->second;
288286425Sdim      OS << I->first << " -> #" << Us.size() << '{';
289286425Sdim      for (UseSet::const_iterator J = Us.begin(), F = Us.end(); J != F; ++J) {
290286425Sdim        User *R = (*J)->getUser();
291286425Sdim        if (R->hasName())
292286425Sdim          OS << ' ' << R->getName();
293286425Sdim        else
294286425Sdim          OS << " <?>(" << *R << ')';
295286425Sdim      }
296286425Sdim      OS << " }\n";
297286425Sdim    }
298286425Sdim    return OS;
299286425Sdim  }
300286425Sdim
301286425Sdim  struct in_set {
302286425Sdim    in_set(const NodeSet &S) : NS(S) {}
303286425Sdim    bool operator() (GepNode *N) const {
304286425Sdim      return NS.find(N) != NS.end();
305286425Sdim    }
306314564Sdim
307286425Sdim  private:
308286425Sdim    const NodeSet &NS;
309286425Sdim  };
310286425Sdim
311314564Sdim} // end anonymous namespace
312286425Sdim
313286425Sdiminline void *operator new(size_t, SpecificBumpPtrAllocator<GepNode> &A) {
314286425Sdim  return A.Allocate();
315286425Sdim}
316286425Sdim
317286425Sdimvoid HexagonCommonGEP::getBlockTraversalOrder(BasicBlock *Root,
318286425Sdim      ValueVect &Order) {
319286425Sdim  // Compute block ordering for a typical DT-based traversal of the flow
320286425Sdim  // graph: "before visiting a block, all of its dominators must have been
321286425Sdim  // visited".
322286425Sdim
323286425Sdim  Order.push_back(Root);
324321369Sdim  for (auto *DTN : children<DomTreeNode*>(DT->getNode(Root)))
325321369Sdim    getBlockTraversalOrder(DTN->getBlock(), Order);
326286425Sdim}
327286425Sdim
328286425Sdimbool HexagonCommonGEP::isHandledGepForm(GetElementPtrInst *GepI) {
329286425Sdim  // No vector GEPs.
330286425Sdim  if (!GepI->getType()->isPointerTy())
331286425Sdim    return false;
332286425Sdim  // No GEPs without any indices.  (Is this possible?)
333286425Sdim  if (GepI->idx_begin() == GepI->idx_end())
334286425Sdim    return false;
335286425Sdim  return true;
336286425Sdim}
337286425Sdim
338286425Sdimvoid HexagonCommonGEP::processGepInst(GetElementPtrInst *GepI,
339286425Sdim      ValueToNodeMap &NM) {
340286425Sdim  DEBUG(dbgs() << "Visiting GEP: " << *GepI << '\n');
341286425Sdim  GepNode *N = new (*Mem) GepNode;
342286425Sdim  Value *PtrOp = GepI->getPointerOperand();
343321369Sdim  uint32_t InBounds = GepI->isInBounds() ? GepNode::InBounds : 0;
344286425Sdim  ValueToNodeMap::iterator F = NM.find(PtrOp);
345286425Sdim  if (F == NM.end()) {
346286425Sdim    N->BaseVal = PtrOp;
347321369Sdim    N->Flags |= GepNode::Root | InBounds;
348286425Sdim  } else {
349286425Sdim    // If PtrOp was a GEP instruction, it must have already been processed.
350286425Sdim    // The ValueToNodeMap entry for it is the last gep node in the generated
351286425Sdim    // chain. Link to it here.
352286425Sdim    N->Parent = F->second;
353286425Sdim  }
354286425Sdim  N->PTy = PtrOp->getType();
355286425Sdim  N->Idx = *GepI->idx_begin();
356286425Sdim
357286425Sdim  // Collect the list of users of this GEP instruction. Will add it to the
358286425Sdim  // last node created for it.
359286425Sdim  UseSet Us;
360286425Sdim  for (Value::user_iterator UI = GepI->user_begin(), UE = GepI->user_end();
361286425Sdim       UI != UE; ++UI) {
362286425Sdim    // Check if this gep is used by anything other than other geps that
363286425Sdim    // we will process.
364286425Sdim    if (isa<GetElementPtrInst>(*UI)) {
365286425Sdim      GetElementPtrInst *UserG = cast<GetElementPtrInst>(*UI);
366286425Sdim      if (isHandledGepForm(UserG))
367286425Sdim        continue;
368286425Sdim    }
369286425Sdim    Us.insert(&UI.getUse());
370286425Sdim  }
371286425Sdim  Nodes.push_back(N);
372286425Sdim  NodeOrder.insert(N);
373286425Sdim
374286425Sdim  // Skip the first index operand, since we only handle 0. This dereferences
375286425Sdim  // the pointer operand.
376286425Sdim  GepNode *PN = N;
377286425Sdim  Type *PtrTy = cast<PointerType>(PtrOp->getType())->getElementType();
378286425Sdim  for (User::op_iterator OI = GepI->idx_begin()+1, OE = GepI->idx_end();
379286425Sdim       OI != OE; ++OI) {
380286425Sdim    Value *Op = *OI;
381286425Sdim    GepNode *Nx = new (*Mem) GepNode;
382286425Sdim    Nx->Parent = PN;  // Link Nx to the previous node.
383321369Sdim    Nx->Flags |= GepNode::Internal | InBounds;
384286425Sdim    Nx->PTy = PtrTy;
385286425Sdim    Nx->Idx = Op;
386286425Sdim    Nodes.push_back(Nx);
387286425Sdim    NodeOrder.insert(Nx);
388286425Sdim    PN = Nx;
389286425Sdim
390286425Sdim    PtrTy = next_type(PtrTy, Op);
391286425Sdim  }
392286425Sdim
393286425Sdim  // After last node has been created, update the use information.
394286425Sdim  if (!Us.empty()) {
395286425Sdim    PN->Flags |= GepNode::Used;
396286425Sdim    Uses[PN].insert(Us.begin(), Us.end());
397286425Sdim  }
398286425Sdim
399286425Sdim  // Link the last node with the originating GEP instruction. This is to
400286425Sdim  // help with linking chained GEP instructions.
401286425Sdim  NM.insert(std::make_pair(GepI, PN));
402286425Sdim}
403286425Sdim
404286425Sdimvoid HexagonCommonGEP::collect() {
405286425Sdim  // Establish depth-first traversal order of the dominator tree.
406286425Sdim  ValueVect BO;
407296417Sdim  getBlockTraversalOrder(&Fn->front(), BO);
408286425Sdim
409286425Sdim  // The creation of gep nodes requires DT-traversal. When processing a GEP
410286425Sdim  // instruction that uses another GEP instruction as the base pointer, the
411286425Sdim  // gep node for the base pointer should already exist.
412286425Sdim  ValueToNodeMap NM;
413286425Sdim  for (ValueVect::iterator I = BO.begin(), E = BO.end(); I != E; ++I) {
414286425Sdim    BasicBlock *B = cast<BasicBlock>(*I);
415286425Sdim    for (BasicBlock::iterator J = B->begin(), F = B->end(); J != F; ++J) {
416286425Sdim      if (!isa<GetElementPtrInst>(J))
417286425Sdim        continue;
418286425Sdim      GetElementPtrInst *GepI = cast<GetElementPtrInst>(J);
419286425Sdim      if (isHandledGepForm(GepI))
420286425Sdim        processGepInst(GepI, NM);
421286425Sdim    }
422286425Sdim  }
423286425Sdim
424286425Sdim  DEBUG(dbgs() << "Gep nodes after initial collection:\n" << Nodes);
425286425Sdim}
426286425Sdim
427314564Sdimstatic void invert_find_roots(const NodeVect &Nodes, NodeChildrenMap &NCM,
428314564Sdim                              NodeVect &Roots) {
429286425Sdim    typedef NodeVect::const_iterator const_iterator;
430286425Sdim    for (const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
431286425Sdim      GepNode *N = *I;
432286425Sdim      if (N->Flags & GepNode::Root) {
433286425Sdim        Roots.push_back(N);
434286425Sdim        continue;
435286425Sdim      }
436286425Sdim      GepNode *PN = N->Parent;
437286425Sdim      NCM[PN].push_back(N);
438286425Sdim    }
439314564Sdim}
440286425Sdim
441314564Sdimstatic void nodes_for_root(GepNode *Root, NodeChildrenMap &NCM,
442314564Sdim                           NodeSet &Nodes) {
443286425Sdim    NodeVect Work;
444286425Sdim    Work.push_back(Root);
445286425Sdim    Nodes.insert(Root);
446286425Sdim
447286425Sdim    while (!Work.empty()) {
448286425Sdim      NodeVect::iterator First = Work.begin();
449286425Sdim      GepNode *N = *First;
450286425Sdim      Work.erase(First);
451286425Sdim      NodeChildrenMap::iterator CF = NCM.find(N);
452286425Sdim      if (CF != NCM.end()) {
453286425Sdim        Work.insert(Work.end(), CF->second.begin(), CF->second.end());
454286425Sdim        Nodes.insert(CF->second.begin(), CF->second.end());
455286425Sdim      }
456286425Sdim    }
457286425Sdim}
458286425Sdim
459314564Sdimnamespace {
460286425Sdim
461286425Sdim  typedef std::set<NodeSet> NodeSymRel;
462286425Sdim  typedef std::pair<GepNode*,GepNode*> NodePair;
463286425Sdim  typedef std::set<NodePair> NodePairSet;
464286425Sdim
465314564Sdim} // end anonymous namespace
466314564Sdim
467314564Sdimstatic const NodeSet *node_class(GepNode *N, NodeSymRel &Rel) {
468286425Sdim    for (NodeSymRel::iterator I = Rel.begin(), E = Rel.end(); I != E; ++I)
469286425Sdim      if (I->count(N))
470286425Sdim        return &*I;
471314564Sdim    return nullptr;
472314564Sdim}
473286425Sdim
474286425Sdim  // Create an ordered pair of GepNode pointers. The pair will be used in
475286425Sdim  // determining equality. The only purpose of the ordering is to eliminate
476286425Sdim  // duplication due to the commutativity of equality/non-equality.
477314564Sdimstatic NodePair node_pair(GepNode *N1, GepNode *N2) {
478286425Sdim    uintptr_t P1 = uintptr_t(N1), P2 = uintptr_t(N2);
479286425Sdim    if (P1 <= P2)
480286425Sdim      return std::make_pair(N1, N2);
481286425Sdim    return std::make_pair(N2, N1);
482314564Sdim}
483286425Sdim
484314564Sdimstatic unsigned node_hash(GepNode *N) {
485286425Sdim    // Include everything except flags and parent.
486286425Sdim    FoldingSetNodeID ID;
487286425Sdim    ID.AddPointer(N->Idx);
488286425Sdim    ID.AddPointer(N->PTy);
489286425Sdim    return ID.ComputeHash();
490314564Sdim}
491286425Sdim
492314564Sdimstatic bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq,
493314564Sdim                    NodePairSet &Ne) {
494286425Sdim    // Don't cache the result for nodes with different hashes. The hash
495286425Sdim    // comparison is fast enough.
496286425Sdim    if (node_hash(N1) != node_hash(N2))
497286425Sdim      return false;
498286425Sdim
499286425Sdim    NodePair NP = node_pair(N1, N2);
500286425Sdim    NodePairSet::iterator FEq = Eq.find(NP);
501286425Sdim    if (FEq != Eq.end())
502286425Sdim      return true;
503286425Sdim    NodePairSet::iterator FNe = Ne.find(NP);
504286425Sdim    if (FNe != Ne.end())
505286425Sdim      return false;
506286425Sdim    // Not previously compared.
507286425Sdim    bool Root1 = N1->Flags & GepNode::Root;
508286425Sdim    bool Root2 = N2->Flags & GepNode::Root;
509286425Sdim    NodePair P = node_pair(N1, N2);
510286425Sdim    // If the Root flag has different values, the nodes are different.
511286425Sdim    // If both nodes are root nodes, but their base pointers differ,
512286425Sdim    // they are different.
513286425Sdim    if (Root1 != Root2 || (Root1 && N1->BaseVal != N2->BaseVal)) {
514286425Sdim      Ne.insert(P);
515286425Sdim      return false;
516286425Sdim    }
517286425Sdim    // Here the root flags are identical, and for root nodes the
518286425Sdim    // base pointers are equal, so the root nodes are equal.
519286425Sdim    // For non-root nodes, compare their parent nodes.
520286425Sdim    if (Root1 || node_eq(N1->Parent, N2->Parent, Eq, Ne)) {
521286425Sdim      Eq.insert(P);
522286425Sdim      return true;
523286425Sdim    }
524286425Sdim    return false;
525286425Sdim}
526286425Sdim
527286425Sdimvoid HexagonCommonGEP::common() {
528286425Sdim  // The essence of this commoning is finding gep nodes that are equal.
529286425Sdim  // To do this we need to compare all pairs of nodes. To save time,
530286425Sdim  // first, partition the set of all nodes into sets of potentially equal
531286425Sdim  // nodes, and then compare pairs from within each partition.
532286425Sdim  typedef std::map<unsigned,NodeSet> NodeSetMap;
533286425Sdim  NodeSetMap MaybeEq;
534286425Sdim
535286425Sdim  for (NodeVect::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
536286425Sdim    GepNode *N = *I;
537286425Sdim    unsigned H = node_hash(N);
538286425Sdim    MaybeEq[H].insert(N);
539286425Sdim  }
540286425Sdim
541286425Sdim  // Compute the equivalence relation for the gep nodes.  Use two caches,
542286425Sdim  // one for equality and the other for non-equality.
543286425Sdim  NodeSymRel EqRel;  // Equality relation (as set of equivalence classes).
544286425Sdim  NodePairSet Eq, Ne;  // Caches.
545286425Sdim  for (NodeSetMap::iterator I = MaybeEq.begin(), E = MaybeEq.end();
546286425Sdim       I != E; ++I) {
547286425Sdim    NodeSet &S = I->second;
548286425Sdim    for (NodeSet::iterator NI = S.begin(), NE = S.end(); NI != NE; ++NI) {
549286425Sdim      GepNode *N = *NI;
550286425Sdim      // If node already has a class, then the class must have been created
551286425Sdim      // in a prior iteration of this loop. Since equality is transitive,
552286425Sdim      // nothing more will be added to that class, so skip it.
553286425Sdim      if (node_class(N, EqRel))
554286425Sdim        continue;
555286425Sdim
556286425Sdim      // Create a new class candidate now.
557286425Sdim      NodeSet C;
558286425Sdim      for (NodeSet::iterator NJ = std::next(NI); NJ != NE; ++NJ)
559286425Sdim        if (node_eq(N, *NJ, Eq, Ne))
560286425Sdim          C.insert(*NJ);
561286425Sdim      // If Tmp is empty, N would be the only element in it. Don't bother
562286425Sdim      // creating a class for it then.
563286425Sdim      if (!C.empty()) {
564286425Sdim        C.insert(N);  // Finalize the set before adding it to the relation.
565286425Sdim        std::pair<NodeSymRel::iterator, bool> Ins = EqRel.insert(C);
566286425Sdim        (void)Ins;
567286425Sdim        assert(Ins.second && "Cannot add a class");
568286425Sdim      }
569286425Sdim    }
570286425Sdim  }
571286425Sdim
572286425Sdim  DEBUG({
573286425Sdim    dbgs() << "Gep node equality:\n";
574286425Sdim    for (NodePairSet::iterator I = Eq.begin(), E = Eq.end(); I != E; ++I)
575286425Sdim      dbgs() << "{ " << I->first << ", " << I->second << " }\n";
576286425Sdim
577286425Sdim    dbgs() << "Gep equivalence classes:\n";
578286425Sdim    for (NodeSymRel::iterator I = EqRel.begin(), E = EqRel.end(); I != E; ++I) {
579286425Sdim      dbgs() << '{';
580286425Sdim      const NodeSet &S = *I;
581286425Sdim      for (NodeSet::const_iterator J = S.begin(), F = S.end(); J != F; ++J) {
582286425Sdim        if (J != S.begin())
583286425Sdim          dbgs() << ',';
584286425Sdim        dbgs() << ' ' << *J;
585286425Sdim      }
586286425Sdim      dbgs() << " }\n";
587286425Sdim    }
588286425Sdim  });
589286425Sdim
590286425Sdim  // Create a projection from a NodeSet to the minimal element in it.
591286425Sdim  typedef std::map<const NodeSet*,GepNode*> ProjMap;
592286425Sdim  ProjMap PM;
593286425Sdim  for (NodeSymRel::iterator I = EqRel.begin(), E = EqRel.end(); I != E; ++I) {
594286425Sdim    const NodeSet &S = *I;
595286425Sdim    GepNode *Min = *std::min_element(S.begin(), S.end(), NodeOrder);
596286425Sdim    std::pair<ProjMap::iterator,bool> Ins = PM.insert(std::make_pair(&S, Min));
597286425Sdim    (void)Ins;
598286425Sdim    assert(Ins.second && "Cannot add minimal element");
599286425Sdim
600286425Sdim    // Update the min element's flags, and user list.
601286425Sdim    uint32_t Flags = 0;
602286425Sdim    UseSet &MinUs = Uses[Min];
603286425Sdim    for (NodeSet::iterator J = S.begin(), F = S.end(); J != F; ++J) {
604286425Sdim      GepNode *N = *J;
605286425Sdim      uint32_t NF = N->Flags;
606286425Sdim      // If N is used, append all original values of N to the list of
607286425Sdim      // original values of Min.
608286425Sdim      if (NF & GepNode::Used)
609286425Sdim        MinUs.insert(Uses[N].begin(), Uses[N].end());
610286425Sdim      Flags |= NF;
611286425Sdim    }
612286425Sdim    if (MinUs.empty())
613286425Sdim      Uses.erase(Min);
614286425Sdim
615286425Sdim    // The collected flags should include all the flags from the min element.
616286425Sdim    assert((Min->Flags & Flags) == Min->Flags);
617286425Sdim    Min->Flags = Flags;
618286425Sdim  }
619286425Sdim
620286425Sdim  // Commoning: for each non-root gep node, replace "Parent" with the
621286425Sdim  // selected (minimum) node from the corresponding equivalence class.
622286425Sdim  // If a given parent does not have an equivalence class, leave it
623286425Sdim  // unchanged (it means that it's the only element in its class).
624286425Sdim  for (NodeVect::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
625286425Sdim    GepNode *N = *I;
626286425Sdim    if (N->Flags & GepNode::Root)
627286425Sdim      continue;
628286425Sdim    const NodeSet *PC = node_class(N->Parent, EqRel);
629286425Sdim    if (!PC)
630286425Sdim      continue;
631286425Sdim    ProjMap::iterator F = PM.find(PC);
632286425Sdim    if (F == PM.end())
633286425Sdim      continue;
634286425Sdim    // Found a replacement, use it.
635286425Sdim    GepNode *Rep = F->second;
636286425Sdim    N->Parent = Rep;
637286425Sdim  }
638286425Sdim
639286425Sdim  DEBUG(dbgs() << "Gep nodes after commoning:\n" << Nodes);
640286425Sdim
641286425Sdim  // Finally, erase the nodes that are no longer used.
642286425Sdim  NodeSet Erase;
643286425Sdim  for (NodeVect::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
644286425Sdim    GepNode *N = *I;
645286425Sdim    const NodeSet *PC = node_class(N, EqRel);
646286425Sdim    if (!PC)
647286425Sdim      continue;
648286425Sdim    ProjMap::iterator F = PM.find(PC);
649286425Sdim    if (F == PM.end())
650286425Sdim      continue;
651286425Sdim    if (N == F->second)
652286425Sdim      continue;
653286425Sdim    // Node for removal.
654286425Sdim    Erase.insert(*I);
655286425Sdim  }
656314564Sdim  NodeVect::iterator NewE = remove_if(Nodes, in_set(Erase));
657286425Sdim  Nodes.resize(std::distance(Nodes.begin(), NewE));
658286425Sdim
659286425Sdim  DEBUG(dbgs() << "Gep nodes after post-commoning cleanup:\n" << Nodes);
660286425Sdim}
661286425Sdim
662314564Sdimtemplate <typename T>
663314564Sdimstatic BasicBlock *nearest_common_dominator(DominatorTree *DT, T &Blocks) {
664286425Sdim    DEBUG({
665286425Sdim      dbgs() << "NCD of {";
666286425Sdim      for (typename T::iterator I = Blocks.begin(), E = Blocks.end();
667286425Sdim           I != E; ++I) {
668286425Sdim        if (!*I)
669286425Sdim          continue;
670286425Sdim        BasicBlock *B = cast<BasicBlock>(*I);
671286425Sdim        dbgs() << ' ' << B->getName();
672286425Sdim      }
673286425Sdim      dbgs() << " }\n";
674286425Sdim    });
675286425Sdim
676314564Sdim    // Allow null basic blocks in Blocks.  In such cases, return nullptr.
677286425Sdim    typename T::iterator I = Blocks.begin(), E = Blocks.end();
678286425Sdim    if (I == E || !*I)
679314564Sdim      return nullptr;
680286425Sdim    BasicBlock *Dom = cast<BasicBlock>(*I);
681286425Sdim    while (++I != E) {
682286425Sdim      BasicBlock *B = cast_or_null<BasicBlock>(*I);
683314564Sdim      Dom = B ? DT->findNearestCommonDominator(Dom, B) : nullptr;
684286425Sdim      if (!Dom)
685314564Sdim        return nullptr;
686286425Sdim    }
687286425Sdim    DEBUG(dbgs() << "computed:" << Dom->getName() << '\n');
688286425Sdim    return Dom;
689314564Sdim}
690286425Sdim
691314564Sdimtemplate <typename T>
692314564Sdimstatic BasicBlock *nearest_common_dominatee(DominatorTree *DT, T &Blocks) {
693286425Sdim    // If two blocks, A and B, dominate a block C, then A dominates B,
694286425Sdim    // or B dominates A.
695286425Sdim    typename T::iterator I = Blocks.begin(), E = Blocks.end();
696286425Sdim    // Find the first non-null block.
697286425Sdim    while (I != E && !*I)
698286425Sdim      ++I;
699286425Sdim    if (I == E)
700286425Sdim      return DT->getRoot();
701286425Sdim    BasicBlock *DomB = cast<BasicBlock>(*I);
702286425Sdim    while (++I != E) {
703286425Sdim      if (!*I)
704286425Sdim        continue;
705286425Sdim      BasicBlock *B = cast<BasicBlock>(*I);
706286425Sdim      if (DT->dominates(B, DomB))
707286425Sdim        continue;
708286425Sdim      if (!DT->dominates(DomB, B))
709314564Sdim        return nullptr;
710286425Sdim      DomB = B;
711286425Sdim    }
712286425Sdim    return DomB;
713314564Sdim}
714286425Sdim
715314564Sdim// Find the first use in B of any value from Values. If no such use,
716314564Sdim// return B->end().
717314564Sdimtemplate <typename T>
718314564Sdimstatic BasicBlock::iterator first_use_of_in_block(T &Values, BasicBlock *B) {
719286425Sdim    BasicBlock::iterator FirstUse = B->end(), BEnd = B->end();
720286425Sdim    typedef typename T::iterator iterator;
721286425Sdim    for (iterator I = Values.begin(), E = Values.end(); I != E; ++I) {
722286425Sdim      Value *V = *I;
723286425Sdim      // If V is used in a PHI node, the use belongs to the incoming block,
724286425Sdim      // not the block with the PHI node. In the incoming block, the use
725286425Sdim      // would be considered as being at the end of it, so it cannot
726286425Sdim      // influence the position of the first use (which is assumed to be
727286425Sdim      // at the end to start with).
728286425Sdim      if (isa<PHINode>(V))
729286425Sdim        continue;
730286425Sdim      if (!isa<Instruction>(V))
731286425Sdim        continue;
732286425Sdim      Instruction *In = cast<Instruction>(V);
733286425Sdim      if (In->getParent() != B)
734286425Sdim        continue;
735296417Sdim      BasicBlock::iterator It = In->getIterator();
736286425Sdim      if (std::distance(FirstUse, BEnd) < std::distance(It, BEnd))
737286425Sdim        FirstUse = It;
738286425Sdim    }
739286425Sdim    return FirstUse;
740314564Sdim}
741286425Sdim
742314564Sdimstatic bool is_empty(const BasicBlock *B) {
743286425Sdim    return B->empty() || (&*B->begin() == B->getTerminator());
744286425Sdim}
745286425Sdim
746286425SdimBasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
747286425Sdim      NodeChildrenMap &NCM, NodeToValueMap &Loc) {
748286425Sdim  DEBUG(dbgs() << "Loc for node:" << Node << '\n');
749286425Sdim  // Recalculate the placement for Node, assuming that the locations of
750286425Sdim  // its children in Loc are valid.
751314564Sdim  // Return nullptr if there is no valid placement for Node (for example, it
752286425Sdim  // uses an index value that is not available at the location required
753286425Sdim  // to dominate all children, etc.).
754286425Sdim
755286425Sdim  // Find the nearest common dominator for:
756286425Sdim  // - all users, if the node is used, and
757286425Sdim  // - all children.
758286425Sdim  ValueVect Bs;
759286425Sdim  if (Node->Flags & GepNode::Used) {
760286425Sdim    // Append all blocks with uses of the original values to the
761286425Sdim    // block vector Bs.
762286425Sdim    NodeToUsesMap::iterator UF = Uses.find(Node);
763286425Sdim    assert(UF != Uses.end() && "Used node with no use information");
764286425Sdim    UseSet &Us = UF->second;
765286425Sdim    for (UseSet::iterator I = Us.begin(), E = Us.end(); I != E; ++I) {
766286425Sdim      Use *U = *I;
767286425Sdim      User *R = U->getUser();
768286425Sdim      if (!isa<Instruction>(R))
769286425Sdim        continue;
770286425Sdim      BasicBlock *PB = isa<PHINode>(R)
771286425Sdim          ? cast<PHINode>(R)->getIncomingBlock(*U)
772286425Sdim          : cast<Instruction>(R)->getParent();
773286425Sdim      Bs.push_back(PB);
774286425Sdim    }
775286425Sdim  }
776286425Sdim  // Append the location of each child.
777286425Sdim  NodeChildrenMap::iterator CF = NCM.find(Node);
778286425Sdim  if (CF != NCM.end()) {
779286425Sdim    NodeVect &Cs = CF->second;
780286425Sdim    for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
781286425Sdim      GepNode *CN = *I;
782286425Sdim      NodeToValueMap::iterator LF = Loc.find(CN);
783286425Sdim      // If the child is only used in GEP instructions (i.e. is not used in
784286425Sdim      // non-GEP instructions), the nearest dominator computed for it may
785286425Sdim      // have been null. In such case it won't have a location available.
786286425Sdim      if (LF == Loc.end())
787286425Sdim        continue;
788286425Sdim      Bs.push_back(LF->second);
789286425Sdim    }
790286425Sdim  }
791286425Sdim
792286425Sdim  BasicBlock *DomB = nearest_common_dominator(DT, Bs);
793286425Sdim  if (!DomB)
794314564Sdim    return nullptr;
795286425Sdim  // Check if the index used by Node dominates the computed dominator.
796286425Sdim  Instruction *IdxI = dyn_cast<Instruction>(Node->Idx);
797286425Sdim  if (IdxI && !DT->dominates(IdxI->getParent(), DomB))
798314564Sdim    return nullptr;
799286425Sdim
800286425Sdim  // Avoid putting nodes into empty blocks.
801286425Sdim  while (is_empty(DomB)) {
802286425Sdim    DomTreeNode *N = (*DT)[DomB]->getIDom();
803286425Sdim    if (!N)
804286425Sdim      break;
805286425Sdim    DomB = N->getBlock();
806286425Sdim  }
807286425Sdim
808286425Sdim  // Otherwise, DomB is fine. Update the location map.
809286425Sdim  Loc[Node] = DomB;
810286425Sdim  return DomB;
811286425Sdim}
812286425Sdim
813286425SdimBasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *Node,
814286425Sdim      NodeChildrenMap &NCM, NodeToValueMap &Loc) {
815286425Sdim  DEBUG(dbgs() << "LocRec begin for node:" << Node << '\n');
816286425Sdim  // Recalculate the placement of Node, after recursively recalculating the
817286425Sdim  // placements of all its children.
818286425Sdim  NodeChildrenMap::iterator CF = NCM.find(Node);
819286425Sdim  if (CF != NCM.end()) {
820286425Sdim    NodeVect &Cs = CF->second;
821286425Sdim    for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I)
822286425Sdim      recalculatePlacementRec(*I, NCM, Loc);
823286425Sdim  }
824286425Sdim  BasicBlock *LB = recalculatePlacement(Node, NCM, Loc);
825286425Sdim  DEBUG(dbgs() << "LocRec end for node:" << Node << '\n');
826286425Sdim  return LB;
827286425Sdim}
828286425Sdim
829286425Sdimbool HexagonCommonGEP::isInvariantIn(Value *Val, Loop *L) {
830286425Sdim  if (isa<Constant>(Val) || isa<Argument>(Val))
831286425Sdim    return true;
832286425Sdim  Instruction *In = dyn_cast<Instruction>(Val);
833286425Sdim  if (!In)
834286425Sdim    return false;
835286425Sdim  BasicBlock *HdrB = L->getHeader(), *DefB = In->getParent();
836286425Sdim  return DT->properlyDominates(DefB, HdrB);
837286425Sdim}
838286425Sdim
839286425Sdimbool HexagonCommonGEP::isInvariantIn(GepNode *Node, Loop *L) {
840286425Sdim  if (Node->Flags & GepNode::Root)
841286425Sdim    if (!isInvariantIn(Node->BaseVal, L))
842286425Sdim      return false;
843286425Sdim  return isInvariantIn(Node->Idx, L);
844286425Sdim}
845286425Sdim
846286425Sdimbool HexagonCommonGEP::isInMainPath(BasicBlock *B, Loop *L) {
847286425Sdim  BasicBlock *HB = L->getHeader();
848286425Sdim  BasicBlock *LB = L->getLoopLatch();
849286425Sdim  // B must post-dominate the loop header or dominate the loop latch.
850286425Sdim  if (PDT->dominates(B, HB))
851286425Sdim    return true;
852286425Sdim  if (LB && DT->dominates(B, LB))
853286425Sdim    return true;
854286425Sdim  return false;
855286425Sdim}
856286425Sdim
857314564Sdimstatic BasicBlock *preheader(DominatorTree *DT, Loop *L) {
858314564Sdim  if (BasicBlock *PH = L->getLoopPreheader())
859314564Sdim    return PH;
860314564Sdim  if (!OptSpeculate)
861314564Sdim    return nullptr;
862314564Sdim  DomTreeNode *DN = DT->getNode(L->getHeader());
863314564Sdim  if (!DN)
864314564Sdim    return nullptr;
865314564Sdim  return DN->getIDom()->getBlock();
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
917314564Sdimnamespace {
918286425Sdim
919286425Sdim  struct LocationAsBlock {
920286425Sdim    LocationAsBlock(const NodeToValueMap &L) : Map(L) {}
921314564Sdim
922286425Sdim    const NodeToValueMap &Map;
923286425Sdim  };
924286425Sdim
925286425Sdim  raw_ostream &operator<< (raw_ostream &OS,
926286425Sdim                           const LocationAsBlock &Loc) LLVM_ATTRIBUTE_UNUSED ;
927286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const LocationAsBlock &Loc) {
928286425Sdim    for (NodeToValueMap::const_iterator I = Loc.Map.begin(), E = Loc.Map.end();
929286425Sdim         I != E; ++I) {
930286425Sdim      OS << I->first << " -> ";
931286425Sdim      BasicBlock *B = cast<BasicBlock>(I->second);
932286425Sdim      OS << B->getName() << '(' << B << ')';
933286425Sdim      OS << '\n';
934286425Sdim    }
935286425Sdim    return OS;
936286425Sdim  }
937286425Sdim
938286425Sdim  inline bool is_constant(GepNode *N) {
939286425Sdim    return isa<ConstantInt>(N->Idx);
940286425Sdim  }
941286425Sdim
942314564Sdim} // end anonymous namespace
943286425Sdim
944286425Sdimvoid HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
945286425Sdim      NodeToValueMap &Loc) {
946286425Sdim  User *R = U->getUser();
947286425Sdim  DEBUG(dbgs() << "Separating chain for node (" << Node << ") user: "
948286425Sdim               << *R << '\n');
949286425Sdim  BasicBlock *PB = cast<Instruction>(R)->getParent();
950286425Sdim
951286425Sdim  GepNode *N = Node;
952314564Sdim  GepNode *C = nullptr, *NewNode = nullptr;
953286425Sdim  while (is_constant(N) && !(N->Flags & GepNode::Root)) {
954286425Sdim    // XXX if (single-use) dont-replicate;
955286425Sdim    GepNode *NewN = new (*Mem) GepNode(N);
956286425Sdim    Nodes.push_back(NewN);
957286425Sdim    Loc[NewN] = PB;
958286425Sdim
959286425Sdim    if (N == Node)
960286425Sdim      NewNode = NewN;
961286425Sdim    NewN->Flags &= ~GepNode::Used;
962286425Sdim    if (C)
963286425Sdim      C->Parent = NewN;
964286425Sdim    C = NewN;
965286425Sdim    N = N->Parent;
966286425Sdim  }
967286425Sdim  if (!NewNode)
968286425Sdim    return;
969286425Sdim
970286425Sdim  // Move over all uses that share the same user as U from Node to NewNode.
971286425Sdim  NodeToUsesMap::iterator UF = Uses.find(Node);
972286425Sdim  assert(UF != Uses.end());
973286425Sdim  UseSet &Us = UF->second;
974286425Sdim  UseSet NewUs;
975286425Sdim  for (UseSet::iterator I = Us.begin(); I != Us.end(); ) {
976286425Sdim    User *S = (*I)->getUser();
977286425Sdim    UseSet::iterator Nx = std::next(I);
978286425Sdim    if (S == R) {
979286425Sdim      NewUs.insert(*I);
980286425Sdim      Us.erase(I);
981286425Sdim    }
982286425Sdim    I = Nx;
983286425Sdim  }
984286425Sdim  if (Us.empty()) {
985286425Sdim    Node->Flags &= ~GepNode::Used;
986286425Sdim    Uses.erase(UF);
987286425Sdim  }
988286425Sdim
989286425Sdim  // Should at least have U in NewUs.
990286425Sdim  NewNode->Flags |= GepNode::Used;
991286425Sdim  DEBUG(dbgs() << "new node: " << NewNode << "  " << *NewNode << '\n');
992286425Sdim  assert(!NewUs.empty());
993286425Sdim  Uses[NewNode] = NewUs;
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
1049286425Sdimvoid HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
1050286425Sdim  // Compute the inverse of the Node.Parent links. Also, collect the set
1051286425Sdim  // of root nodes.
1052286425Sdim  NodeChildrenMap NCM;
1053286425Sdim  NodeVect Roots;
1054286425Sdim  invert_find_roots(Nodes, NCM, Roots);
1055286425Sdim
1056286425Sdim  // Compute the initial placement determined by the users' locations, and
1057286425Sdim  // the locations of the child nodes.
1058286425Sdim  for (NodeVect::iterator I = Roots.begin(), E = Roots.end(); I != E; ++I)
1059286425Sdim    recalculatePlacementRec(*I, NCM, Loc);
1060286425Sdim
1061286425Sdim  DEBUG(dbgs() << "Initial node placement:\n" << LocationAsBlock(Loc));
1062286425Sdim
1063286425Sdim  if (OptEnableInv) {
1064286425Sdim    for (NodeVect::iterator I = Roots.begin(), E = Roots.end(); I != E; ++I)
1065286425Sdim      adjustForInvariance(*I, NCM, Loc);
1066286425Sdim
1067286425Sdim    DEBUG(dbgs() << "Node placement after adjustment for invariance:\n"
1068286425Sdim                 << LocationAsBlock(Loc));
1069286425Sdim  }
1070286425Sdim  if (OptEnableConst) {
1071286425Sdim    for (NodeVect::iterator I = Roots.begin(), E = Roots.end(); I != E; ++I)
1072286425Sdim      separateConstantChains(*I, NCM, Loc);
1073286425Sdim  }
1074286425Sdim  DEBUG(dbgs() << "Node use information:\n" << Uses);
1075286425Sdim
1076286425Sdim  // At the moment, there is no further refinement of the initial placement.
1077286425Sdim  // Such a refinement could include splitting the nodes if they are placed
1078286425Sdim  // too far from some of its users.
1079286425Sdim
1080286425Sdim  DEBUG(dbgs() << "Final node placement:\n" << LocationAsBlock(Loc));
1081286425Sdim}
1082286425Sdim
1083286425SdimValue *HexagonCommonGEP::fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
1084286425Sdim      BasicBlock *LocB) {
1085286425Sdim  DEBUG(dbgs() << "Fabricating GEP in " << LocB->getName()
1086286425Sdim               << " for nodes:\n" << NA);
1087286425Sdim  unsigned Num = NA.size();
1088286425Sdim  GepNode *RN = NA[0];
1089286425Sdim  assert((RN->Flags & GepNode::Root) && "Creating GEP for non-root");
1090286425Sdim
1091321369Sdim  GetElementPtrInst *NewInst = nullptr;
1092286425Sdim  Value *Input = RN->BaseVal;
1093286425Sdim  Value **IdxList = new Value*[Num+1];
1094286425Sdim  unsigned nax = 0;
1095286425Sdim  do {
1096286425Sdim    unsigned IdxC = 0;
1097286425Sdim    // If the type of the input of the first node is not a pointer,
1098286425Sdim    // we need to add an artificial i32 0 to the indices (because the
1099286425Sdim    // actual input in the IR will be a pointer).
1100286425Sdim    if (!NA[nax]->PTy->isPointerTy()) {
1101286425Sdim      Type *Int32Ty = Type::getInt32Ty(*Ctx);
1102286425Sdim      IdxList[IdxC++] = ConstantInt::get(Int32Ty, 0);
1103286425Sdim    }
1104286425Sdim
1105286425Sdim    // Keep adding indices from NA until we have to stop and generate
1106286425Sdim    // an "intermediate" GEP.
1107286425Sdim    while (++nax <= Num) {
1108286425Sdim      GepNode *N = NA[nax-1];
1109286425Sdim      IdxList[IdxC++] = N->Idx;
1110286425Sdim      if (nax < Num) {
1111286425Sdim        // We have to stop, if the expected type of the output of this node
1112286425Sdim        // is not the same as the input type of the next node.
1113286425Sdim        Type *NextTy = next_type(N->PTy, N->Idx);
1114286425Sdim        if (NextTy != NA[nax]->PTy)
1115286425Sdim          break;
1116286425Sdim      }
1117286425Sdim    }
1118286425Sdim    ArrayRef<Value*> A(IdxList, IdxC);
1119286425Sdim    Type *InpTy = Input->getType();
1120286425Sdim    Type *ElTy = cast<PointerType>(InpTy->getScalarType())->getElementType();
1121296417Sdim    NewInst = GetElementPtrInst::Create(ElTy, Input, A, "cgep", &*At);
1122321369Sdim    NewInst->setIsInBounds(RN->Flags & GepNode::InBounds);
1123286425Sdim    DEBUG(dbgs() << "new GEP: " << *NewInst << '\n');
1124286425Sdim    Input = NewInst;
1125286425Sdim  } while (nax <= Num);
1126286425Sdim
1127286425Sdim  delete[] IdxList;
1128286425Sdim  return NewInst;
1129286425Sdim}
1130286425Sdim
1131286425Sdimvoid HexagonCommonGEP::getAllUsersForNode(GepNode *Node, ValueVect &Values,
1132286425Sdim      NodeChildrenMap &NCM) {
1133286425Sdim  NodeVect Work;
1134286425Sdim  Work.push_back(Node);
1135286425Sdim
1136286425Sdim  while (!Work.empty()) {
1137286425Sdim    NodeVect::iterator First = Work.begin();
1138286425Sdim    GepNode *N = *First;
1139286425Sdim    Work.erase(First);
1140286425Sdim    if (N->Flags & GepNode::Used) {
1141286425Sdim      NodeToUsesMap::iterator UF = Uses.find(N);
1142286425Sdim      assert(UF != Uses.end() && "No use information for used node");
1143286425Sdim      UseSet &Us = UF->second;
1144286425Sdim      for (UseSet::iterator I = Us.begin(), E = Us.end(); I != E; ++I)
1145286425Sdim        Values.push_back((*I)->getUser());
1146286425Sdim    }
1147286425Sdim    NodeChildrenMap::iterator CF = NCM.find(N);
1148286425Sdim    if (CF != NCM.end()) {
1149286425Sdim      NodeVect &Cs = CF->second;
1150286425Sdim      Work.insert(Work.end(), Cs.begin(), Cs.end());
1151286425Sdim    }
1152286425Sdim  }
1153286425Sdim}
1154286425Sdim
1155286425Sdimvoid HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
1156286425Sdim  DEBUG(dbgs() << "Nodes before materialization:\n" << Nodes << '\n');
1157286425Sdim  NodeChildrenMap NCM;
1158286425Sdim  NodeVect Roots;
1159286425Sdim  // Compute the inversion again, since computing placement could alter
1160286425Sdim  // "parent" relation between nodes.
1161286425Sdim  invert_find_roots(Nodes, NCM, Roots);
1162286425Sdim
1163286425Sdim  while (!Roots.empty()) {
1164286425Sdim    NodeVect::iterator First = Roots.begin();
1165286425Sdim    GepNode *Root = *First, *Last = *First;
1166286425Sdim    Roots.erase(First);
1167286425Sdim
1168286425Sdim    NodeVect NA;  // Nodes to assemble.
1169286425Sdim    // Append to NA all child nodes up to (and including) the first child
1170286425Sdim    // that:
1171286425Sdim    // (1) has more than 1 child, or
1172286425Sdim    // (2) is used, or
1173286425Sdim    // (3) has a child located in a different block.
1174286425Sdim    bool LastUsed = false;
1175286425Sdim    unsigned LastCN = 0;
1176286425Sdim    // The location may be null if the computation failed (it can legitimately
1177286425Sdim    // happen for nodes created from dead GEPs).
1178286425Sdim    Value *LocV = Loc[Last];
1179286425Sdim    if (!LocV)
1180286425Sdim      continue;
1181286425Sdim    BasicBlock *LastB = cast<BasicBlock>(LocV);
1182286425Sdim    do {
1183286425Sdim      NA.push_back(Last);
1184286425Sdim      LastUsed = (Last->Flags & GepNode::Used);
1185286425Sdim      if (LastUsed)
1186286425Sdim        break;
1187286425Sdim      NodeChildrenMap::iterator CF = NCM.find(Last);
1188286425Sdim      LastCN = (CF != NCM.end()) ? CF->second.size() : 0;
1189286425Sdim      if (LastCN != 1)
1190286425Sdim        break;
1191286425Sdim      GepNode *Child = CF->second.front();
1192286425Sdim      BasicBlock *ChildB = cast_or_null<BasicBlock>(Loc[Child]);
1193314564Sdim      if (ChildB != nullptr && LastB != ChildB)
1194286425Sdim        break;
1195286425Sdim      Last = Child;
1196286425Sdim    } while (true);
1197286425Sdim
1198296417Sdim    BasicBlock::iterator InsertAt = LastB->getTerminator()->getIterator();
1199286425Sdim    if (LastUsed || LastCN > 0) {
1200286425Sdim      ValueVect Urs;
1201286425Sdim      getAllUsersForNode(Root, Urs, NCM);
1202286425Sdim      BasicBlock::iterator FirstUse = first_use_of_in_block(Urs, LastB);
1203286425Sdim      if (FirstUse != LastB->end())
1204286425Sdim        InsertAt = FirstUse;
1205286425Sdim    }
1206286425Sdim
1207286425Sdim    // Generate a new instruction for NA.
1208286425Sdim    Value *NewInst = fabricateGEP(NA, InsertAt, LastB);
1209286425Sdim
1210286425Sdim    // Convert all the children of Last node into roots, and append them
1211286425Sdim    // to the Roots list.
1212286425Sdim    if (LastCN > 0) {
1213286425Sdim      NodeVect &Cs = NCM[Last];
1214286425Sdim      for (NodeVect::iterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
1215286425Sdim        GepNode *CN = *I;
1216286425Sdim        CN->Flags &= ~GepNode::Internal;
1217286425Sdim        CN->Flags |= GepNode::Root;
1218286425Sdim        CN->BaseVal = NewInst;
1219286425Sdim        Roots.push_back(CN);
1220286425Sdim      }
1221286425Sdim    }
1222286425Sdim
1223286425Sdim    // Lastly, if the Last node was used, replace all uses with the new GEP.
1224286425Sdim    // The uses reference the original GEP values.
1225286425Sdim    if (LastUsed) {
1226286425Sdim      NodeToUsesMap::iterator UF = Uses.find(Last);
1227286425Sdim      assert(UF != Uses.end() && "No use information found");
1228286425Sdim      UseSet &Us = UF->second;
1229286425Sdim      for (UseSet::iterator I = Us.begin(), E = Us.end(); I != E; ++I) {
1230286425Sdim        Use *U = *I;
1231286425Sdim        U->set(NewInst);
1232286425Sdim      }
1233286425Sdim    }
1234286425Sdim  }
1235286425Sdim}
1236286425Sdim
1237286425Sdimvoid HexagonCommonGEP::removeDeadCode() {
1238286425Sdim  ValueVect BO;
1239286425Sdim  BO.push_back(&Fn->front());
1240286425Sdim
1241286425Sdim  for (unsigned i = 0; i < BO.size(); ++i) {
1242286425Sdim    BasicBlock *B = cast<BasicBlock>(BO[i]);
1243321369Sdim    for (auto DTN : children<DomTreeNode*>(DT->getNode(B)))
1244321369Sdim      BO.push_back(DTN->getBlock());
1245286425Sdim  }
1246286425Sdim
1247286425Sdim  for (unsigned i = BO.size(); i > 0; --i) {
1248286425Sdim    BasicBlock *B = cast<BasicBlock>(BO[i-1]);
1249286425Sdim    BasicBlock::InstListType &IL = B->getInstList();
1250286425Sdim    typedef BasicBlock::InstListType::reverse_iterator reverse_iterator;
1251286425Sdim    ValueVect Ins;
1252286425Sdim    for (reverse_iterator I = IL.rbegin(), E = IL.rend(); I != E; ++I)
1253286425Sdim      Ins.push_back(&*I);
1254286425Sdim    for (ValueVect::iterator I = Ins.begin(), E = Ins.end(); I != E; ++I) {
1255286425Sdim      Instruction *In = cast<Instruction>(*I);
1256286425Sdim      if (isInstructionTriviallyDead(In))
1257286425Sdim        In->eraseFromParent();
1258286425Sdim    }
1259286425Sdim  }
1260286425Sdim}
1261286425Sdim
1262286425Sdimbool HexagonCommonGEP::runOnFunction(Function &F) {
1263309124Sdim  if (skipFunction(F))
1264309124Sdim    return false;
1265309124Sdim
1266286425Sdim  // For now bail out on C++ exception handling.
1267286425Sdim  for (Function::iterator A = F.begin(), Z = F.end(); A != Z; ++A)
1268286425Sdim    for (BasicBlock::iterator I = A->begin(), E = A->end(); I != E; ++I)
1269286425Sdim      if (isa<InvokeInst>(I) || isa<LandingPadInst>(I))
1270286425Sdim        return false;
1271286425Sdim
1272286425Sdim  Fn = &F;
1273286425Sdim  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1274309124Sdim  PDT = &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
1275286425Sdim  LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1276286425Sdim  Ctx = &F.getContext();
1277286425Sdim
1278286425Sdim  Nodes.clear();
1279286425Sdim  Uses.clear();
1280286425Sdim  NodeOrder.clear();
1281286425Sdim
1282286425Sdim  SpecificBumpPtrAllocator<GepNode> Allocator;
1283286425Sdim  Mem = &Allocator;
1284286425Sdim
1285286425Sdim  collect();
1286286425Sdim  common();
1287286425Sdim
1288286425Sdim  NodeToValueMap Loc;
1289286425Sdim  computeNodePlacement(Loc);
1290286425Sdim  materialize(Loc);
1291286425Sdim  removeDeadCode();
1292286425Sdim
1293309124Sdim#ifdef EXPENSIVE_CHECKS
1294286425Sdim  // Run this only when expensive checks are enabled.
1295286425Sdim  verifyFunction(F);
1296286425Sdim#endif
1297286425Sdim  return true;
1298286425Sdim}
1299286425Sdim
1300314564Sdimnamespace llvm {
1301286425Sdim
1302286425Sdim  FunctionPass *createHexagonCommonGEP() {
1303286425Sdim    return new HexagonCommonGEP();
1304286425Sdim  }
1305314564Sdim
1306314564Sdim} // end namespace llvm
1307