123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- NaryReassociate.h - Reassociate n-ary expressions --------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This pass reassociates n-ary add expressions and eliminates the redundancy
- // exposed by the reassociation.
- //
- // A motivating example:
- //
- // void foo(int a, int b) {
- // bar(a + b);
- // bar((a + 2) + b);
- // }
- //
- // An ideal compiler should reassociate (a + 2) + b to (a + b) + 2 and simplify
- // the above code to
- //
- // int t = a + b;
- // bar(t);
- // bar(t + 2);
- //
- // However, the Reassociate pass is unable to do that because it processes each
- // instruction individually and believes (a + 2) + b is the best form according
- // to its rank system.
- //
- // To address this limitation, NaryReassociate reassociates an expression in a
- // form that reuses existing instructions. As a result, NaryReassociate can
- // reassociate (a + 2) + b in the example to (a + b) + 2 because it detects that
- // (a + b) is computed before.
- //
- // NaryReassociate works as follows. For every instruction in the form of (a +
- // b) + c, it checks whether a + c or b + c is already computed by a dominating
- // instruction. If so, it then reassociates (a + b) + c into (a + c) + b or (b +
- // c) + a and removes the redundancy accordingly. To efficiently look up whether
- // an expression is computed before, we store each instruction seen and its SCEV
- // into an SCEV-to-instruction map.
- //
- // Although the algorithm pattern-matches only ternary additions, it
- // automatically handles many >3-ary expressions by walking through the function
- // in the depth-first order. For example, given
- //
- // (a + c) + d
- // ((a + b) + c) + d
- //
- // NaryReassociate first rewrites (a + b) + c to (a + c) + b, and then rewrites
- // ((a + c) + b) + d into ((a + c) + d) + b.
- //
- // Finally, the above dominator-based algorithm may need to be run multiple
- // iterations before emitting optimal code. One source of this need is that we
- // only split an operand when it is used only once. The above algorithm can
- // eliminate an instruction and decrease the usage count of its operands. As a
- // result, an instruction that previously had multiple uses may become a
- // single-use instruction and thus eligible for split consideration. For
- // example,
- //
- // ac = a + c
- // ab = a + b
- // abc = ab + c
- // ab2 = ab + b
- // ab2c = ab2 + c
- //
- // In the first iteration, we cannot reassociate abc to ac+b because ab is used
- // twice. However, we can reassociate ab2c to abc+b in the first iteration. As a
- // result, ab2 becomes dead and ab will be used only once in the second
- // iteration.
- //
- // Limitations and TODO items:
- //
- // 1) We only considers n-ary adds and muls for now. This should be extended
- // and generalized.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_TRANSFORMS_SCALAR_NARYREASSOCIATE_H
- #define LLVM_TRANSFORMS_SCALAR_NARYREASSOCIATE_H
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/IR/PassManager.h"
- #include "llvm/IR/ValueHandle.h"
- namespace llvm {
- class AssumptionCache;
- class BinaryOperator;
- class DataLayout;
- class DominatorTree;
- class Function;
- class GetElementPtrInst;
- class Instruction;
- class ScalarEvolution;
- class SCEV;
- class TargetLibraryInfo;
- class TargetTransformInfo;
- class Type;
- class Value;
- class NaryReassociatePass : public PassInfoMixin<NaryReassociatePass> {
- public:
- PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
- // Glue for old PM.
- bool runImpl(Function &F, AssumptionCache *AC_, DominatorTree *DT_,
- ScalarEvolution *SE_, TargetLibraryInfo *TLI_,
- TargetTransformInfo *TTI_);
- private:
- // Runs only one iteration of the dominator-based algorithm. See the header
- // comments for why we need multiple iterations.
- bool doOneIteration(Function &F);
- // Reassociates I for better CSE.
- Instruction *tryReassociate(Instruction *I, const SCEV *&OrigSCEV);
- // Reassociate GEP for better CSE.
- Instruction *tryReassociateGEP(GetElementPtrInst *GEP);
- // Try splitting GEP at the I-th index and see whether either part can be
- // CSE'ed. This is a helper function for tryReassociateGEP.
- //
- // \p IndexedType The element type indexed by GEP's I-th index. This is
- // equivalent to
- // GEP->getIndexedType(GEP->getPointerOperand(), 0-th index,
- // ..., i-th index).
- GetElementPtrInst *tryReassociateGEPAtIndex(GetElementPtrInst *GEP,
- unsigned I, Type *IndexedType);
- // Given GEP's I-th index = LHS + RHS, see whether &Base[..][LHS][..] or
- // &Base[..][RHS][..] can be CSE'ed and rewrite GEP accordingly.
- GetElementPtrInst *tryReassociateGEPAtIndex(GetElementPtrInst *GEP,
- unsigned I, Value *LHS,
- Value *RHS, Type *IndexedType);
- // Reassociate binary operators for better CSE.
- Instruction *tryReassociateBinaryOp(BinaryOperator *I);
- // A helper function for tryReassociateBinaryOp. LHS and RHS are explicitly
- // passed.
- Instruction *tryReassociateBinaryOp(Value *LHS, Value *RHS,
- BinaryOperator *I);
- // Rewrites I to (LHS op RHS) if LHS is computed already.
- Instruction *tryReassociatedBinaryOp(const SCEV *LHS, Value *RHS,
- BinaryOperator *I);
- // Tries to match Op1 and Op2 by using V.
- bool matchTernaryOp(BinaryOperator *I, Value *V, Value *&Op1, Value *&Op2);
- // Gets SCEV for (LHS op RHS).
- const SCEV *getBinarySCEV(BinaryOperator *I, const SCEV *LHS,
- const SCEV *RHS);
- // Returns the closest dominator of \c Dominatee that computes
- // \c CandidateExpr. Returns null if not found.
- Instruction *findClosestMatchingDominator(const SCEV *CandidateExpr,
- Instruction *Dominatee);
- // Try to match \p I as signed/unsigned Min/Max and reassociate it. \p
- // OrigSCEV is set if \I matches Min/Max regardless whether resassociation is
- // done or not. If reassociation was successful newly generated instruction is
- // returned, otherwise nullptr.
- template <typename PredT>
- Instruction *matchAndReassociateMinOrMax(Instruction *I,
- const SCEV *&OrigSCEV);
- // Reassociate Min/Max.
- template <typename MaxMinT>
- Value *tryReassociateMinOrMax(Instruction *I, MaxMinT MaxMinMatch, Value *LHS,
- Value *RHS);
- // GetElementPtrInst implicitly sign-extends an index if the index is shorter
- // than the pointer size. This function returns whether Index is shorter than
- // GEP's pointer size, i.e., whether Index needs to be sign-extended in order
- // to be an index of GEP.
- bool requiresSignExtension(Value *Index, GetElementPtrInst *GEP);
- AssumptionCache *AC;
- const DataLayout *DL;
- DominatorTree *DT;
- ScalarEvolution *SE;
- TargetLibraryInfo *TLI;
- TargetTransformInfo *TTI;
- // A lookup table quickly telling which instructions compute the given SCEV.
- // Note that there can be multiple instructions at different locations
- // computing to the same SCEV, so we map a SCEV to an instruction list. For
- // example,
- //
- // if (p1)
- // foo(a + b);
- // if (p2)
- // bar(a + b);
- DenseMap<const SCEV *, SmallVector<WeakTrackingVH, 2>> SeenExprs;
- };
- } // end namespace llvm
- #endif // LLVM_TRANSFORMS_SCALAR_NARYREASSOCIATE_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|