[llvm] [CodeGenPrepare] don't promote sdiv/srem by -1 (PR #218737)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 22:06:12 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/3] 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/3] 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/3] 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
+}
+



More information about the llvm-commits mailing list