[llvm] [LV] Fix stale entry in MinBWs in tryToWiden (PR #136858)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 23 05:50:40 PDT 2025
https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/136858
tryToWiden attempts to replace an Instruction with a Constant from SCEV, but forgets to erase the Instruction from the MinBWs map, leading to a crash in VPlanTransforms::truncateToMinimalBitwidths. Fix this by erasing the stale entry.
Fixes #125278.
>From f63389f08549a7acf520f76a553cb914bb4698c2 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Wed, 23 Apr 2025 13:38:52 +0100
Subject: [PATCH 1/2] [LV] Pre-commit test for #125278
---
.../test/Transforms/LoopVectorize/pr125278.ll | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 llvm/test/Transforms/LoopVectorize/pr125278.ll
diff --git a/llvm/test/Transforms/LoopVectorize/pr125278.ll b/llvm/test/Transforms/LoopVectorize/pr125278.ll
new file mode 100644
index 0000000000000..61c7a924b441f
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/pr125278.ll
@@ -0,0 +1,21 @@
+; REQUIRES: asserts
+; RUN: not --crash opt -passes=loop-vectorize -disable-output %s
+
+define void @pr125278(ptr %dst, i64 %n) {
+entry:
+ %true.ext = zext i1 true to i32
+ br label %cond
+
+cond:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %cond ], [ %iv.next, %loop ]
+ %false.ext = zext i1 false to i32
+ %xor = xor i32 %false.ext, %true.ext
+ %xor.trunc = trunc i32 %xor to i8
+ store i8 %xor.trunc, ptr %dst, align 1
+ %iv.next = add i64 %iv, 1
+ %cmp = icmp ult i64 %iv.next, %n
+ br i1 %cmp, label %loop, label %cond
+}
>From 55fa72f54eafec16044371da38dfe2c6718834af Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Wed, 23 Apr 2025 13:42:00 +0100
Subject: [PATCH 2/2] [LV] Fix stale entry in MinBWs in tryToWiden
tryToWiden attempts to replace an Instruction with a Constant from SCEV,
but forgets to erase the Instruction from the MinBWs map, leading to a
crash in VPlanTransforms::truncateToMinimalBitwidths. Fix this by
erasing the stale entry.
Fixes #125278.
---
.../Transforms/Vectorize/LoopVectorize.cpp | 13 ++++++-----
.../test/Transforms/LoopVectorize/pr125278.ll | 23 +++++++++++++++++--
2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 32c3435ccb38d..1051b4c7bb17a 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -1047,9 +1047,7 @@ class LoopVectorizationCostModel {
/// \returns The smallest bitwidth each instruction can be represented with.
/// The vector equivalents of these instructions should be truncated to this
/// type.
- const MapVector<Instruction *, uint64_t> &getMinimalBitwidths() const {
- return MinBWs;
- }
+ MapVector<Instruction *, uint64_t> &getMinimalBitwidths() { return MinBWs; }
/// \returns True if it is more profitable to scalarize instruction \p I for
/// vectorization factor \p VF.
@@ -8868,12 +8866,15 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I,
auto GetConstantViaSCEV = [this, &SE](VPValue *Op) {
if (!Op->isLiveIn())
return Op;
- Value *V = Op->getUnderlyingValue();
- if (isa<Constant>(V) || !SE.isSCEVable(V->getType()))
+ Instruction *I = dyn_cast<Instruction>(Op->getLiveInIRValue());
+ if (!I || !SE.isSCEVable(I->getType()))
return Op;
- auto *C = dyn_cast<SCEVConstant>(SE.getSCEV(V));
+ auto *C = dyn_cast<SCEVConstant>(SE.getSCEV(I));
if (!C)
return Op;
+ // If we're going to replace an instruction with a constant, erase any
+ // stale entry in MinBWs.
+ CM.getMinimalBitwidths().erase(I);
return Plan.getOrAddLiveIn(C->getValue());
};
// For Mul, the legacy cost model checks both operands.
diff --git a/llvm/test/Transforms/LoopVectorize/pr125278.ll b/llvm/test/Transforms/LoopVectorize/pr125278.ll
index 61c7a924b441f..ec899a3e1f5c2 100644
--- a/llvm/test/Transforms/LoopVectorize/pr125278.ll
+++ b/llvm/test/Transforms/LoopVectorize/pr125278.ll
@@ -1,7 +1,26 @@
-; REQUIRES: asserts
-; RUN: not --crash opt -passes=loop-vectorize -disable-output %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=loop-vectorize -S %s | FileCheck %s
define void @pr125278(ptr %dst, i64 %n) {
+; CHECK-LABEL: define void @pr125278(
+; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TRUE_EXT:%.*]] = zext i1 true to i32
+; CHECK-NEXT: br label %[[COND:.*]]
+; CHECK: [[COND_LOOPEXIT:.*]]:
+; CHECK-NEXT: br label %[[COND]]
+; CHECK: [[COND]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[COND]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT: [[FALSE_EXT:%.*]] = zext i1 false to i32
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[FALSE_EXT]], [[TRUE_EXT]]
+; CHECK-NEXT: [[XOR_TRUNC:%.*]] = trunc i32 [[XOR]] to i8
+; CHECK-NEXT: store i8 [[XOR_TRUNC]], ptr [[DST]], align 1
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV_NEXT]], [[N]]
+; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[COND_LOOPEXIT]]
+;
entry:
%true.ext = zext i1 true to i32
br label %cond
More information about the llvm-commits
mailing list