aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h')
-rw-r--r--llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h79
1 files changed, 73 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
index b4c7ab02f928..87c97d1edd7b 100644
--- a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
+++ b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
@@ -13,6 +13,7 @@
#include "VPlan.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm {
@@ -20,6 +21,27 @@ namespace llvm {
class LoopVectorizationLegality;
class LoopVectorizationCostModel;
class TargetLibraryInfo;
+class TargetTransformInfo;
+struct HistogramInfo;
+
+/// A chain of instructions that form a partial reduction.
+/// Designed to match: reduction_bin_op (bin_op (extend (A), (extend (B))),
+/// accumulator).
+struct PartialReductionChain {
+ PartialReductionChain(Instruction *Reduction, Instruction *ExtendA,
+ Instruction *ExtendB, Instruction *BinOp)
+ : Reduction(Reduction), ExtendA(ExtendA), ExtendB(ExtendB), BinOp(BinOp) {
+ }
+ /// The top-level binary operation that forms the reduction to a scalar
+ /// after the loop body.
+ Instruction *Reduction;
+ /// The extension of each of the inner binary operation's operands.
+ Instruction *ExtendA;
+ Instruction *ExtendB;
+
+ /// The binary operation using the extends that is then reduced.
+ Instruction *BinOp;
+};
/// Helper class to create VPRecipies from IR instructions.
class VPRecipeBuilder {
@@ -32,6 +54,9 @@ class VPRecipeBuilder {
/// Target Library Info.
const TargetLibraryInfo *TLI;
+ // Target Transform Info.
+ const TargetTransformInfo *TTI;
+
/// The legality analysis.
LoopVectorizationLegality *Legal;
@@ -61,6 +86,9 @@ class VPRecipeBuilder {
/// created.
SmallVector<VPHeaderPHIRecipe *, 4> PhisToFix;
+ /// A mapping of partial reduction exit instructions to their scaling factor.
+ DenseMap<const Instruction *, unsigned> ScaledReductionMap;
+
/// Check if \p I can be widened at the start of \p Range and possibly
/// decrease the range such that the returned value holds for the entire \p
/// Range. The function should not be called for memory instructions or calls.
@@ -91,9 +119,9 @@ class VPRecipeBuilder {
VPBlendRecipe *tryToBlend(PHINode *Phi, ArrayRef<VPValue *> Operands);
/// Handle call instructions. If \p CI can be widened for \p Range.Start,
- /// return a new VPWidenCallRecipe. Range.End may be decreased to ensure same
- /// decision from \p Range.Start to \p Range.End.
- VPWidenCallRecipe *tryToWidenCall(CallInst *CI, ArrayRef<VPValue *> Operands,
+ /// return a new VPWidenCallRecipe or VPWidenIntrinsicRecipe. Range.End may be
+ /// decreased to ensure same decision from \p Range.Start to \p Range.End.
+ VPSingleDefRecipe *tryToWidenCall(CallInst *CI, ArrayRef<VPValue *> Operands,
VFRange &Range);
/// Check if \p I has an opcode that can be widened and return a VPWidenRecipe
@@ -102,13 +130,44 @@ class VPRecipeBuilder {
VPWidenRecipe *tryToWiden(Instruction *I, ArrayRef<VPValue *> Operands,
VPBasicBlock *VPBB);
+ /// Makes Histogram count operations safe for vectorization, by emitting a
+ /// llvm.experimental.vector.histogram.add intrinsic in place of the
+ /// Load + Add|Sub + Store operations that perform the histogram in the
+ /// original scalar loop.
+ VPHistogramRecipe *tryToWidenHistogram(const HistogramInfo *HI,
+ ArrayRef<VPValue *> Operands);
+
+ /// Examines reduction operations to see if the target can use a cheaper
+ /// operation with a wider per-iteration input VF and narrower PHI VF.
+ /// Each element within Chains is a pair with a struct containing reduction
+ /// information and the scaling factor between the number of elements in
+ /// the input and output.
+ /// Recursively calls itself to identify chained scaled reductions.
+ /// Returns true if this invocation added an entry to Chains, otherwise false.
+ /// i.e. returns false in the case that a subcall adds an entry to Chains,
+ /// but the top-level call does not.
+ bool getScaledReductions(
+ Instruction *PHI, Instruction *RdxExitInstr, VFRange &Range,
+ SmallVectorImpl<std::pair<PartialReductionChain, unsigned>> &Chains);
+
public:
VPRecipeBuilder(VPlan &Plan, Loop *OrigLoop, const TargetLibraryInfo *TLI,
+ const TargetTransformInfo *TTI,
LoopVectorizationLegality *Legal,
LoopVectorizationCostModel &CM,
PredicatedScalarEvolution &PSE, VPBuilder &Builder)
- : Plan(Plan), OrigLoop(OrigLoop), TLI(TLI), Legal(Legal), CM(CM),
- PSE(PSE), Builder(Builder) {}
+ : Plan(Plan), OrigLoop(OrigLoop), TLI(TLI), TTI(TTI), Legal(Legal),
+ CM(CM), PSE(PSE), Builder(Builder) {}
+
+ std::optional<unsigned> getScalingForReduction(const Instruction *ExitInst) {
+ auto It = ScaledReductionMap.find(ExitInst);
+ return It == ScaledReductionMap.end() ? std::nullopt
+ : std::make_optional(It->second);
+ }
+
+ /// Find all possible partial reductions in the loop and track all of those
+ /// that are valid so recipes can be formed later.
+ void collectScaledReductions(VFRange &Range);
/// Create and return a widened recipe for \p I if one can be created within
/// the given VF \p Range.
@@ -116,6 +175,11 @@ public:
ArrayRef<VPValue *> Operands,
VFRange &Range, VPBasicBlock *VPBB);
+ /// Create and return a partial reduction recipe for a reduction instruction
+ /// along with binary operation and reduction phi operands.
+ VPRecipeBase *tryToCreatePartialReduction(Instruction *Reduction,
+ ArrayRef<VPValue *> Operands);
+
/// Set the recipe created for given ingredient.
void setRecipe(Instruction *I, VPRecipeBase *R) {
assert(!Ingredient2Recipe.contains(I) &&
@@ -134,6 +198,9 @@ public:
/// Returns the *entry* mask for the block \p BB.
VPValue *getBlockInMask(BasicBlock *BB) const;
+ /// Create an edge mask for every destination of cases and/or default.
+ void createSwitchEdgeMasks(SwitchInst *SI);
+
/// A helper function that computes the predicate of the edge between SRC
/// and DST.
VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst);
@@ -165,7 +232,7 @@ public:
iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>>
mapToVPValues(User::op_range Operands);
- VPValue *getVPValueOrAddLiveIn(Value *V, VPlan &Plan) {
+ VPValue *getVPValueOrAddLiveIn(Value *V) {
if (auto *I = dyn_cast<Instruction>(V)) {
if (auto *R = Ingredient2Recipe.lookup(I))
return R->getVPSingleValue();