Skip to content

Commit 44f216a

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 c4617bc commit 44f216a

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"
@@ -3013,8 +3014,11 @@ class VPExpressionRecipe : public VPSingleDefRecipe {
30133014
{Ext0, Ext1, Mul, Red}) {}
30143015

30153016
~VPExpressionRecipe() override {
3016-
for (auto *R : reverse(ExpressionRecipes))
3017-
delete R;
3017+
SmallSet<VPSingleDefRecipe *, 4> ExpressionRecipesSeen;
3018+
for (auto *R : reverse(ExpressionRecipes)) {
3019+
if (ExpressionRecipesSeen.insert(R).second)
3020+
delete R;
3021+
}
30183022
for (VPValue *T : LiveInPlaceholders)
30193023
delete T;
30203024
}

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2761,9 +2761,8 @@ VPExpressionRecipe::VPExpressionRecipe(
27612761
ExpressionTypes ExpressionType,
27622762
ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
27632763
: VPSingleDefRecipe(VPDef::VPExpressionSC, {}, {}),
2764-
ExpressionRecipes(SetVector<VPSingleDefRecipe *>(
2765-
ExpressionRecipes.begin(), ExpressionRecipes.end())
2766-
.takeVector()),
2764+
ExpressionRecipes(SmallVector<VPSingleDefRecipe *>(
2765+
ExpressionRecipes.begin(), ExpressionRecipes.end())),
27672766
ExpressionType(ExpressionType) {
27682767
assert(!ExpressionRecipes.empty() && "Nothing to combine?");
27692768
assert(
@@ -2797,25 +2796,43 @@ VPExpressionRecipe::VPExpressionRecipe(
27972796
R->removeFromParent();
27982797
}
27992798

2799+
// Keep track of how many instances of each recipe occur in the recipe list
2800+
SmallMapVector<VPSingleDefRecipe *, unsigned, 4> ExpressionRecipeCounts;
2801+
for (auto *R : ExpressionRecipes) {
2802+
auto *F = ExpressionRecipeCounts.find(R);
2803+
if (F == ExpressionRecipeCounts.end())
2804+
ExpressionRecipeCounts.insert(std::make_pair(R, 1));
2805+
else
2806+
F->second++;
2807+
}
2808+
28002809
// Internalize all external operands to the expression recipes. To do so,
28012810
// create new temporary VPValues for all operands defined by a recipe outside
28022811
// the expression. The original operands are added as operands of the
28032812
// VPExpressionRecipe itself.
28042813
for (auto *R : ExpressionRecipes) {
2814+
auto *F = ExpressionRecipeCounts.find(R);
2815+
F->second--;
28052816
for (const auto &[Idx, Op] : enumerate(R->operands())) {
28062817
auto *Def = Op->getDefiningRecipe();
28072818
if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
28082819
continue;
28092820
addOperand(Op);
2810-
LiveInPlaceholders.push_back(new VPValue());
2811-
R->setOperand(Idx, LiveInPlaceholders.back());
2821+
auto *Tmp = new VPValue();
2822+
Tmp->setUnderlyingValue(Op->getUnderlyingValue());
2823+
LiveInPlaceholders.push_back(Tmp);
2824+
// Only modify this recipe's operands if it's the last time it occurs in
2825+
// the recipe list
2826+
if (F->second == 0)
2827+
R->setOperand(Idx, Tmp);
28122828
}
28132829
}
28142830
}
28152831

28162832
void VPExpressionRecipe::decompose() {
28172833
for (auto *R : ExpressionRecipes)
2818-
R->insertBefore(this);
2834+
if (!R->getParent())
2835+
R->insertBefore(this);
28192836

28202837
for (const auto &[Idx, Op] : enumerate(operands()))
28212838
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
@@ -632,3 +632,50 @@ exit:
632632
%r.0.lcssa = phi i64 [ %rdx.next, %loop ]
633633
ret i64 %r.0.lcssa
634634
}
635+
636+
define i64 @print_mulacc_duplicate_extends(ptr nocapture readonly %x, ptr nocapture readonly %y, i32 %n) {
637+
; CHECK-LABEL: 'print_mulacc_duplicate_extends'
638+
; CHECK: VPlan 'Initial VPlan for VF={4},UF>=1' {
639+
; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF
640+
; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
641+
; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
642+
; CHECK-NEXT: Live-in ir<%n> = original trip-count
643+
; CHECK-EMPTY:
644+
; CHECK: vector.ph:
645+
; CHECK-NEXT: EMIT vp<[[RDX_START:%.+]]> = reduction-start-vector ir<0>, ir<0>, ir<1>
646+
; CHECK-NEXT: Successor(s): vector loop
647+
; CHECK-EMPTY:
648+
; CHECK-NEXT: <x1> vector loop: {
649+
; CHECK-NEXT: vector.body:
650+
; CHECK-NEXT: EMIT vp<[[IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[IV_NEXT:%.+]]>
651+
; CHECK-NEXT: WIDEN-REDUCTION-PHI ir<[[RDX:%.+]]> = phi vp<[[RDX_START]]>, vp<[[RDX_NEXT:%.+]]>
652+
; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[IV]]>, ir<1>
653+
; CHECK-NEXT: CLONE ir<[[ARRAYIDX0:%.+]]> = getelementptr inbounds ir<%x>, vp<[[STEPS]]>
654+
; CHECK-NEXT: vp<[[ADDR0:%.+]]> = vector-pointer ir<[[ARRAYIDX0]]>
655+
; CHECK-NEXT: WIDEN ir<[[LOAD0:%.+]]> = load vp<[[ADDR0]]>
656+
; CHECK-NEXT: EXPRESSION vp<[[RDX_NEXT:%.+]]> = ir<[[RDX]]> + reduce.sub (mul nsw (ir<[[LOAD0]]> sext to i64), (ir<[[LOAD0]]> sext to i64))
657+
; CHECK-NEXT: EMIT vp<[[IV_NEXT]]> = add nuw vp<[[IV]]>, vp<[[VFxUF]]>
658+
; CHECK-NEXT: EMIT branch-on-count vp<[[IV_NEXT]]>, vp<[[VTC]]>
659+
; CHECK-NEXT: No successors
660+
; CHECK-NEXT: }
661+
;
662+
entry:
663+
br label %loop
664+
665+
loop:
666+
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
667+
%rdx = phi i64 [ %rdx.next, %loop ], [ 0, %entry ]
668+
%arrayidx = getelementptr inbounds i16, ptr %x, i32 %iv
669+
%load0 = load i16, ptr %arrayidx, align 4
670+
%conv0 = sext i16 %load0 to i32
671+
%mul = mul nsw i32 %conv0, %conv0
672+
%conv = sext i32 %mul to i64
673+
%rdx.next = sub nsw i64 %rdx, %conv
674+
%iv.next = add nuw nsw i32 %iv, 1
675+
%exitcond = icmp eq i32 %iv.next, %n
676+
br i1 %exitcond, label %exit, label %loop
677+
678+
exit:
679+
%r.0.lcssa = phi i64 [ %rdx.next, %loop ]
680+
ret i64 %r.0.lcssa
681+
}

0 commit comments

Comments
 (0)