[llvm] [CodeGenPrepare] don't promote sdiv/srem by -1 (PR #218737)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 00:18:40 PDT 2026
https://github.com/im-lunex updated https://github.com/llvm/llvm-project/pull/218737
>From 3db3b2e179b85fdaba40e6682848f2a717f0e80c Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Tue, 25 Aug 2026 23:50:10 +0600
Subject: [PATCH 1/4] cgp: fix sdiv -1 unobserved-lane miscompile
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 14 ++++
.../X86/store-extract-division-ub.ll | 77 +++++++++++++++++++
2 files changed, 91 insertions(+)
create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 53b7a81537975..09a7935b7aafd 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8349,6 +8349,18 @@ class VectorPromoteHelper {
llvm_unreachable(nullptr);
}
+ static bool
+ canCauseUndefinedBehaviorOnUnobservedLanes(const Instruction *Use) {
+ switch (Use->getOpcode()) {
+ default:
+ return false;
+ case Instruction::SDiv:
+ case Instruction::SRem:
+ return isa<ConstantInt>(Use->getOperand(1)) &&
+ cast<ConstantInt>(Use->getOperand(1))->isMinusOne();
+ }
+ }
+
public:
VectorPromoteHelper(const DataLayout &DL, const TargetLowering &TLI,
const TargetTransformInfo &TTI, Instruction *Transition,
@@ -8367,6 +8379,8 @@ class VectorPromoteHelper {
/// Check if it is profitable to promote \p ToBePromoted
/// by moving downward the transition through.
bool shouldPromote(const Instruction *ToBePromoted) const {
+ if (canCauseUndefinedBehaviorOnUnobservedLanes(ToBePromoted))
+ return false;
// Promote only if all the operands can be statically expanded.
// Indeed, we do not want to introduce any new kind of transitions.
for (const Use &U : ToBePromoted->operands()) {
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
new file mode 100644
index 0000000000000..35978e59a6913
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
@@ -0,0 +1,77 @@
+; test for issue (https://github.com/llvm/llvm-project/issues/218570)
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -stress-cgp-store-extract < %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @no_promote_sdiv_minus_one(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @no_promote_sdiv_minus_one(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V:%.*]] = load <2 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[V]], i32 0
+; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[E]], -1
+; CHECK-NEXT: store i8 [[R]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <2 x i8>, ptr %src, align 1
+ %e = extractelement <2 x i8> %v, i32 0
+ %r = sdiv i8 %e, -1
+ store i8 %r, ptr %dst, align 1
+ ret void
+}
+
+define void @no_promote_srem_minus_one(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @no_promote_srem_minus_one(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V:%.*]] = load <2 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[V]], i32 0
+; CHECK-NEXT: [[R:%.*]] = srem i8 [[E]], -1
+; CHECK-NEXT: store i8 [[R]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <2 x i8>, ptr %src, align 1
+ %e = extractelement <2 x i8> %v, i32 0
+ %r = srem i8 %e, -1
+ store i8 %r, ptr %dst, align 1
+ ret void
+}
+
+define void @promote_sdiv_two(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @promote_sdiv_two(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V:%.*]] = load <2 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[R:%.*]] = sdiv <2 x i8> [[V]], splat (i8 2)
+; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[R]], i32 0
+; CHECK-NEXT: store i8 [[E]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <2 x i8>, ptr %src, align 1
+ %e = extractelement <2 x i8> %v, i32 0
+ %r = sdiv i8 %e, 2
+ store i8 %r, ptr %dst, align 1
+ ret void
+}
+
+define void @promote_udiv_seven(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @promote_udiv_seven(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V:%.*]] = load <2 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[R:%.*]] = udiv <2 x i8> [[V]], splat (i8 7)
+; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[R]], i32 0
+; CHECK-NEXT: store i8 [[E]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <2 x i8>, ptr %src, align 1
+ %e = extractelement <2 x i8> %v, i32 0
+ %r = udiv i8 %e, 7
+ store i8 %r, ptr %dst, align 1
+ ret void
+}
>From 2526b4bee83184a578f1c2ee6c6f0285916a53b5 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Wed, 26 Aug 2026 09:52:05 +0600
Subject: [PATCH 2/4] try new approch with llvms [speculative-execution] safety
check
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 14 +------------
.../X86/store-extract-division-ub.ll | 20 ++++++++++++++++++-
2 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 09a7935b7aafd..fdf5fdf20e66d 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8349,18 +8349,6 @@ class VectorPromoteHelper {
llvm_unreachable(nullptr);
}
- static bool
- canCauseUndefinedBehaviorOnUnobservedLanes(const Instruction *Use) {
- switch (Use->getOpcode()) {
- default:
- return false;
- case Instruction::SDiv:
- case Instruction::SRem:
- return isa<ConstantInt>(Use->getOperand(1)) &&
- cast<ConstantInt>(Use->getOperand(1))->isMinusOne();
- }
- }
-
public:
VectorPromoteHelper(const DataLayout &DL, const TargetLowering &TLI,
const TargetTransformInfo &TTI, Instruction *Transition,
@@ -8379,7 +8367,7 @@ class VectorPromoteHelper {
/// Check if it is profitable to promote \p ToBePromoted
/// by moving downward the transition through.
bool shouldPromote(const Instruction *ToBePromoted) const {
- if (canCauseUndefinedBehaviorOnUnobservedLanes(ToBePromoted))
+ if (!isSafeToSpeculativelyExecute(ToBePromoted))
return false;
// Promote only if all the operands can be statically expanded.
// Indeed, we do not want to introduce any new kind of transitions.
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
index 35978e59a6913..07e65da5b46db 100644
--- a/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
@@ -1,5 +1,5 @@
-; test for issue (https://github.com/llvm/llvm-project/issues/218570)
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; test for issue (https://github.com/llvm/llvm-project/issues/218570)
; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -stress-cgp-store-extract < %s | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
@@ -40,6 +40,24 @@ entry:
ret void
}
+define void @no_promote_sdiv_poison(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @no_promote_sdiv_poison(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V:%.*]] = load <2 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[V]], i32 0
+; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[E]], poison
+; CHECK-NEXT: store i8 [[R]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <2 x i8>, ptr %src, align 1
+ %e = extractelement <2 x i8> %v, i32 0
+ %r = sdiv i8 %e, poison
+ store i8 %r, ptr %dst, align 1
+ ret void
+}
+
define void @promote_sdiv_two(ptr %src, ptr %dst) {
; CHECK-LABEL: define void @promote_sdiv_two(
; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
>From f89ac6913f838eec5e88341e50e88ad45c778c8f Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Thu, 27 Aug 2026 11:05:57 +0600
Subject: [PATCH 3/4] safety and test enhancement
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 5 ++++-
.../X86/store-extract-division-ub.ll | 19 +++++++++++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index fdf5fdf20e66d..2ca29d7b2f243 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8367,7 +8367,10 @@ class VectorPromoteHelper {
/// Check if it is profitable to promote \p ToBePromoted
/// by moving downward the transition through.
bool shouldPromote(const Instruction *ToBePromoted) const {
- if (!isSafeToSpeculativelyExecute(ToBePromoted))
+ if (!isSafeToSpeculativelyExecute(
+ ToBePromoted, /*CtxI=*/nullptr, /*AC=*/nullptr, /*DT=*/nullptr,
+ /*TLI=*/nullptr, /*UseVariableInfo=*/false,
+ /*IgnoreUBImplyingAttrs=*/false))
return false;
// Promote only if all the operands can be statically expanded.
// Indeed, we do not want to introduce any new kind of transitions.
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
index 07e65da5b46db..872a527d5de6d 100644
--- a/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
@@ -93,3 +93,22 @@ entry:
store i8 %r, ptr %dst, align 1
ret void
}
+
+define void @no_promote_sdiv_intmin(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @no_promote_sdiv_intmin(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V:%.*]] = load <2 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[E:%.*]] = extractelement <2 x i8> [[V]], i32 0
+; CHECK-NEXT: [[R:%.*]] = sdiv i8 -128, [[E]]
+; CHECK-NEXT: store i8 [[R]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <2 x i8>, ptr %src, align 1
+ %e = extractelement <2 x i8> %v, i32 0
+ %r = sdiv i8 -128, %e
+ store i8 %r, ptr %dst, align 1
+ ret void
+}
+
>From 0351ea56be8a227b2b2199366eeb1c30d6004a87 Mon Sep 17 00:00:00 2001
From: im-lunex <thisissamir04 at gmail.com>
Date: Sat, 26 Sep 2026 23:52:56 +0600
Subject: [PATCH 4/4] remove the extra check and use
isSafeToSpeculativelyExecuteWithVariableReplaced() insted
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 2ca29d7b2f243..8d03b5edb698e 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8367,21 +8367,13 @@ class VectorPromoteHelper {
/// Check if it is profitable to promote \p ToBePromoted
/// by moving downward the transition through.
bool shouldPromote(const Instruction *ToBePromoted) const {
- if (!isSafeToSpeculativelyExecute(
- ToBePromoted, /*CtxI=*/nullptr, /*AC=*/nullptr, /*DT=*/nullptr,
- /*TLI=*/nullptr, /*UseVariableInfo=*/false,
- /*IgnoreUBImplyingAttrs=*/false))
+ if (!isSafeToSpeculativelyExecuteWithVariableReplaced(ToBePromoted))
return false;
// Promote only if all the operands can be statically expanded.
// Indeed, we do not want to introduce any new kind of transitions.
for (const Use &U : ToBePromoted->operands()) {
const Value *Val = U.get();
if (Val == getEndOfTransition()) {
- // If the use is a division and the transition is on the rhs,
- // we cannot promote the operation, otherwise we may create a
- // division by zero.
- if (canCauseUndefinedBehavior(ToBePromoted, U.getOperandNo()))
- return false;
continue;
}
if (!isa<ConstantInt>(Val) && !isa<UndefValue>(Val) &&
More information about the llvm-commits
mailing list