Skip to content

Commit 7328e0d

Browse files
committed
[LV] Keep duplicate recipes in VPExpressionRecipe
The VPExpressionRecipe class uses a set to store its bundled recipes. If repeated recipes are bundled then the duplicates will be lost, causing the following recipes to not be at the expected place in the set. When printing a reduce.add(mul(ext, ext)) bundle, if the extends are the same then the 3rd element of the set will the the reduction, rather than the expected mul, causing a cast error. With this change, the recipes are at the expected index in the set. Fixes #156464
1 parent da1eabd commit 7328e0d

File tree

3 files changed

+76
-8
lines changed

3 files changed

+76
-8
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/ADT/DenseMap.h"
3030
#include "llvm/ADT/SmallBitVector.h"
3131
#include "llvm/ADT/SmallPtrSet.h"
32+
#include "llvm/ADT/SmallSet.h"
3233
#include "llvm/ADT/SmallVector.h"
3334
#include "llvm/ADT/Twine.h"
3435
#include "llvm/ADT/ilist.h"
@@ -3039,8 +3040,11 @@ class VPExpressionRecipe : public VPSingleDefRecipe {
30393040
}
30403041

30413042
~VPExpressionRecipe() override {
3042-
for (auto *R : reverse(ExpressionRecipes))
3043-
delete R;
3043+
SmallSet<VPSingleDefRecipe *, 4> ExpressionRecipesSeen;
3044+
for (auto *R : reverse(ExpressionRecipes)) {
3045+
if (ExpressionRecipesSeen.insert(R).second)
3046+
delete R;
3047+
}
30443048
for (VPValue *T : LiveInPlaceholders)
30453049
delete T;
30463050
}

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,9 +2755,8 @@ VPExpressionRecipe::VPExpressionRecipe(
27552755
ExpressionTypes ExpressionType,
27562756
ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
27572757
: VPSingleDefRecipe(VPDef::VPExpressionSC, {}, {}),
2758-
ExpressionRecipes(SetVector<VPSingleDefRecipe *>(
2759-
ExpressionRecipes.begin(), ExpressionRecipes.end())
2760-
.takeVector()),
2758+
ExpressionRecipes(SmallVector<VPSingleDefRecipe *>(
2759+
ExpressionRecipes.begin(), ExpressionRecipes.end())),
27612760
ExpressionType(ExpressionType) {
27622761
assert(!ExpressionRecipes.empty() && "Nothing to combine?");
27632762
assert(
@@ -2791,25 +2790,43 @@ VPExpressionRecipe::VPExpressionRecipe(
27912790
R->removeFromParent();
27922791
}
27932792

2793+
// Keep track of how many instances of each recipe occur in the recipe list
2794+
SmallMapVector<VPSingleDefRecipe *, unsigned, 4> ExpressionRecipeCounts;
2795+
for (auto *R : ExpressionRecipes) {
2796+
auto *F = ExpressionRecipeCounts.find(R);
2797+
if (F == ExpressionRecipeCounts.end())
2798+
ExpressionRecipeCounts.insert(std::make_pair(R, 1));
2799+
else
2800+
F->second++;
2801+
}
2802+
27942803
// Internalize all external operands to the expression recipes. To do so,
27952804
// create new temporary VPValues for all operands defined by a recipe outside
27962805
// the expression. The original operands are added as operands of the
27972806
// VPExpressionRecipe itself.
27982807
for (auto *R : ExpressionRecipes) {
2808+
auto *F = ExpressionRecipeCounts.find(R);
2809+
F->second--;
27992810
for (const auto &[Idx, Op] : enumerate(R->operands())) {
28002811
auto *Def = Op->getDefiningRecipe();
28012812
if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
28022813
continue;
28032814
addOperand(Op);
2804-
LiveInPlaceholders.push_back(new VPValue());
2805-
R->setOperand(Idx, LiveInPlaceholders.back());
2815+
auto *Tmp = new VPValue();
2816+
Tmp->setUnderlyingValue(Op->getUnderlyingValue());
2817+
LiveInPlaceholders.push_back(Tmp);
2818+
// Only modify this recipe's operands if it's the last time it occurs in
2819+
// the recipe list
2820+
if (F->second == 0)
2821+
R->setOperand(Idx, Tmp);
28062822
}
28072823
}
28082824
}
28092825

28102826
void VPExpressionRecipe::decompose() {
28112827
for (auto *R : ExpressionRecipes)
2812-
R->insertBefore(this);
2828+
if (!R->getParent())
2829+
R->insertBefore(this);
28132830

28142831
for (const auto &[Idx, Op] : enumerate(operands()))
28152832
LiveInPlaceholders[Idx]->replaceAllUsesWith(Op);

llvm/test/Transforms/LoopVectorize/vplan-printing-reductions.ll

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,3 +753,50 @@ exit:
753753
%r.0.lcssa = phi i64 [ %rdx.next, %loop ]
754754
ret i64 %r.0.lcssa
755755
}
756+
757+
define i64 @print_mulacc_duplicate_extends(ptr nocapture readonly %x, ptr nocapture readonly %y, i32 %n) {
758+
; CHECK-LABEL: 'print_mulacc_duplicate_extends'
759+
; CHECK: VPlan 'Initial VPlan for VF={4},UF>=1' {
760+
; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF
761+
; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
762+
; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
763+
; CHECK-NEXT: Live-in ir<%n> = original trip-count
764+
; CHECK-EMPTY:
765+
; CHECK: vector.ph:
766+
; CHECK-NEXT: EMIT vp<[[RDX_START:%.+]]> = reduction-start-vector ir<0>, ir<0>, ir<1>
767+
; CHECK-NEXT: Successor(s): vector loop
768+
; CHECK-EMPTY:
769+
; CHECK-NEXT: <x1> vector loop: {
770+
; CHECK-NEXT: vector.body:
771+
; CHECK-NEXT: EMIT vp<[[IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[IV_NEXT:%.+]]>
772+
; CHECK-NEXT: WIDEN-REDUCTION-PHI ir<[[RDX:%.+]]> = phi vp<[[RDX_START]]>, vp<[[RDX_NEXT:%.+]]>
773+
; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[IV]]>, ir<1>
774+
; CHECK-NEXT: CLONE ir<[[ARRAYIDX0:%.+]]> = getelementptr inbounds ir<%x>, vp<[[STEPS]]>
775+
; CHECK-NEXT: vp<[[ADDR0:%.+]]> = vector-pointer ir<[[ARRAYIDX0]]>
776+
; CHECK-NEXT: WIDEN ir<[[LOAD0:%.+]]> = load vp<[[ADDR0]]>
777+
; CHECK-NEXT: EXPRESSION vp<[[RDX_NEXT:%.+]]> = ir<[[RDX]]> + reduce.sub (mul nsw (ir<[[LOAD0]]> sext to i64), (ir<[[LOAD0]]> sext to i64))
778+
; CHECK-NEXT: EMIT vp<[[IV_NEXT]]> = add nuw vp<[[IV]]>, vp<[[VFxUF]]>
779+
; CHECK-NEXT: EMIT branch-on-count vp<[[IV_NEXT]]>, vp<[[VTC]]>
780+
; CHECK-NEXT: No successors
781+
; CHECK-NEXT: }
782+
;
783+
entry:
784+
br label %loop
785+
786+
loop:
787+
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
788+
%rdx = phi i64 [ %rdx.next, %loop ], [ 0, %entry ]
789+
%arrayidx = getelementptr inbounds i16, ptr %x, i32 %iv
790+
%load0 = load i16, ptr %arrayidx, align 4
791+
%conv0 = sext i16 %load0 to i32
792+
%mul = mul nsw i32 %conv0, %conv0
793+
%conv = sext i32 %mul to i64
794+
%rdx.next = sub nsw i64 %rdx, %conv
795+
%iv.next = add nuw nsw i32 %iv, 1
796+
%exitcond = icmp eq i32 %iv.next, %n
797+
br i1 %exitcond, label %exit, label %loop
798+
799+
exit:
800+
%r.0.lcssa = phi i64 [ %rdx.next, %loop ]
801+
ret i64 %r.0.lcssa
802+
}

0 commit comments

Comments
 (0)