|
|
|||
File indexing completed on 2026-05-10 08:44:42
0001 //===- NaryReassociate.h - Reassociate n-ary expressions --------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // This pass reassociates n-ary add expressions and eliminates the redundancy 0010 // exposed by the reassociation. 0011 // 0012 // A motivating example: 0013 // 0014 // void foo(int a, int b) { 0015 // bar(a + b); 0016 // bar((a + 2) + b); 0017 // } 0018 // 0019 // An ideal compiler should reassociate (a + 2) + b to (a + b) + 2 and simplify 0020 // the above code to 0021 // 0022 // int t = a + b; 0023 // bar(t); 0024 // bar(t + 2); 0025 // 0026 // However, the Reassociate pass is unable to do that because it processes each 0027 // instruction individually and believes (a + 2) + b is the best form according 0028 // to its rank system. 0029 // 0030 // To address this limitation, NaryReassociate reassociates an expression in a 0031 // form that reuses existing instructions. As a result, NaryReassociate can 0032 // reassociate (a + 2) + b in the example to (a + b) + 2 because it detects that 0033 // (a + b) is computed before. 0034 // 0035 // NaryReassociate works as follows. For every instruction in the form of (a + 0036 // b) + c, it checks whether a + c or b + c is already computed by a dominating 0037 // instruction. If so, it then reassociates (a + b) + c into (a + c) + b or (b + 0038 // c) + a and removes the redundancy accordingly. To efficiently look up whether 0039 // an expression is computed before, we store each instruction seen and its SCEV 0040 // into an SCEV-to-instruction map. 0041 // 0042 // Although the algorithm pattern-matches only ternary additions, it 0043 // automatically handles many >3-ary expressions by walking through the function 0044 // in the depth-first order. For example, given 0045 // 0046 // (a + c) + d 0047 // ((a + b) + c) + d 0048 // 0049 // NaryReassociate first rewrites (a + b) + c to (a + c) + b, and then rewrites 0050 // ((a + c) + b) + d into ((a + c) + d) + b. 0051 // 0052 // Finally, the above dominator-based algorithm may need to be run multiple 0053 // iterations before emitting optimal code. One source of this need is that we 0054 // only split an operand when it is used only once. The above algorithm can 0055 // eliminate an instruction and decrease the usage count of its operands. As a 0056 // result, an instruction that previously had multiple uses may become a 0057 // single-use instruction and thus eligible for split consideration. For 0058 // example, 0059 // 0060 // ac = a + c 0061 // ab = a + b 0062 // abc = ab + c 0063 // ab2 = ab + b 0064 // ab2c = ab2 + c 0065 // 0066 // In the first iteration, we cannot reassociate abc to ac+b because ab is used 0067 // twice. However, we can reassociate ab2c to abc+b in the first iteration. As a 0068 // result, ab2 becomes dead and ab will be used only once in the second 0069 // iteration. 0070 // 0071 // Limitations and TODO items: 0072 // 0073 // 1) We only considers n-ary adds and muls for now. This should be extended 0074 // and generalized. 0075 // 0076 //===----------------------------------------------------------------------===// 0077 0078 #ifndef LLVM_TRANSFORMS_SCALAR_NARYREASSOCIATE_H 0079 #define LLVM_TRANSFORMS_SCALAR_NARYREASSOCIATE_H 0080 0081 #include "llvm/ADT/DenseMap.h" 0082 #include "llvm/ADT/SmallVector.h" 0083 #include "llvm/IR/PassManager.h" 0084 #include "llvm/IR/ValueHandle.h" 0085 0086 namespace llvm { 0087 0088 class AssumptionCache; 0089 class BinaryOperator; 0090 class DataLayout; 0091 class DominatorTree; 0092 class Function; 0093 class GetElementPtrInst; 0094 class Instruction; 0095 class ScalarEvolution; 0096 class SCEV; 0097 class TargetLibraryInfo; 0098 class TargetTransformInfo; 0099 class Type; 0100 class Value; 0101 0102 class NaryReassociatePass : public PassInfoMixin<NaryReassociatePass> { 0103 public: 0104 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 0105 0106 // Glue for old PM. 0107 bool runImpl(Function &F, AssumptionCache *AC_, DominatorTree *DT_, 0108 ScalarEvolution *SE_, TargetLibraryInfo *TLI_, 0109 TargetTransformInfo *TTI_); 0110 0111 private: 0112 // Runs only one iteration of the dominator-based algorithm. See the header 0113 // comments for why we need multiple iterations. 0114 bool doOneIteration(Function &F); 0115 0116 // Reassociates I for better CSE. 0117 Instruction *tryReassociate(Instruction *I, const SCEV *&OrigSCEV); 0118 0119 // Reassociate GEP for better CSE. 0120 Instruction *tryReassociateGEP(GetElementPtrInst *GEP); 0121 0122 // Try splitting GEP at the I-th index and see whether either part can be 0123 // CSE'ed. This is a helper function for tryReassociateGEP. 0124 // 0125 // \p IndexedType The element type indexed by GEP's I-th index. This is 0126 // equivalent to 0127 // GEP->getIndexedType(GEP->getPointerOperand(), 0-th index, 0128 // ..., i-th index). 0129 GetElementPtrInst *tryReassociateGEPAtIndex(GetElementPtrInst *GEP, 0130 unsigned I, Type *IndexedType); 0131 0132 // Given GEP's I-th index = LHS + RHS, see whether &Base[..][LHS][..] or 0133 // &Base[..][RHS][..] can be CSE'ed and rewrite GEP accordingly. 0134 GetElementPtrInst *tryReassociateGEPAtIndex(GetElementPtrInst *GEP, 0135 unsigned I, Value *LHS, 0136 Value *RHS, Type *IndexedType); 0137 0138 // Reassociate binary operators for better CSE. 0139 Instruction *tryReassociateBinaryOp(BinaryOperator *I); 0140 0141 // A helper function for tryReassociateBinaryOp. LHS and RHS are explicitly 0142 // passed. 0143 Instruction *tryReassociateBinaryOp(Value *LHS, Value *RHS, 0144 BinaryOperator *I); 0145 // Rewrites I to (LHS op RHS) if LHS is computed already. 0146 Instruction *tryReassociatedBinaryOp(const SCEV *LHS, Value *RHS, 0147 BinaryOperator *I); 0148 0149 // Tries to match Op1 and Op2 by using V. 0150 bool matchTernaryOp(BinaryOperator *I, Value *V, Value *&Op1, Value *&Op2); 0151 0152 // Gets SCEV for (LHS op RHS). 0153 const SCEV *getBinarySCEV(BinaryOperator *I, const SCEV *LHS, 0154 const SCEV *RHS); 0155 0156 // Returns the closest dominator of \c Dominatee that computes 0157 // \c CandidateExpr. Returns null if not found. 0158 Instruction *findClosestMatchingDominator(const SCEV *CandidateExpr, 0159 Instruction *Dominatee); 0160 0161 // Try to match \p I as signed/unsigned Min/Max and reassociate it. \p 0162 // OrigSCEV is set if \I matches Min/Max regardless whether resassociation is 0163 // done or not. If reassociation was successful newly generated instruction is 0164 // returned, otherwise nullptr. 0165 template <typename PredT> 0166 Instruction *matchAndReassociateMinOrMax(Instruction *I, 0167 const SCEV *&OrigSCEV); 0168 0169 // Reassociate Min/Max. 0170 template <typename MaxMinT> 0171 Value *tryReassociateMinOrMax(Instruction *I, MaxMinT MaxMinMatch, Value *LHS, 0172 Value *RHS); 0173 0174 // GetElementPtrInst implicitly sign-extends an index if the index is shorter 0175 // than the pointer size. This function returns whether Index is shorter than 0176 // GEP's pointer size, i.e., whether Index needs to be sign-extended in order 0177 // to be an index of GEP. 0178 bool requiresSignExtension(Value *Index, GetElementPtrInst *GEP); 0179 0180 AssumptionCache *AC; 0181 const DataLayout *DL; 0182 DominatorTree *DT; 0183 ScalarEvolution *SE; 0184 TargetLibraryInfo *TLI; 0185 TargetTransformInfo *TTI; 0186 0187 // A lookup table quickly telling which instructions compute the given SCEV. 0188 // Note that there can be multiple instructions at different locations 0189 // computing to the same SCEV, so we map a SCEV to an instruction list. For 0190 // example, 0191 // 0192 // if (p1) 0193 // foo(a + b); 0194 // if (p2) 0195 // bar(a + b); 0196 DenseMap<const SCEV *, SmallVector<WeakTrackingVH, 2>> SeenExprs; 0197 }; 0198 0199 } // end namespace llvm 0200 0201 #endif // LLVM_TRANSFORMS_SCALAR_NARYREASSOCIATE_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|