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

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 00:58:42 PDT 2026


Author: ʟᴜɴᴇx
Date: 2026-09-30T07:58:34Z
New Revision: 73a0b12b8ee34b9d2858cf6ca60a6154145a52ca

URL: https://github.com/llvm/llvm-project/commit/73a0b12b8ee34b9d2858cf6ca60a6154145a52ca
DIFF: https://github.com/llvm/llvm-project/commit/73a0b12b8ee34b9d2858cf6ca60a6154145a52ca.diff

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

`store-extract` promotion was widening sdiv/srem to the vector type
without checking if thats safe or not... and INT_MIN lane / -1 is UB.
skip sdiv/srem by -1 in `shouldPromote`, rest still promotes fine.

Fixes #218570

Added: 
    llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll

Modified: 
    llvm/lib/CodeGen/CodeGenPrepare.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index d554a32a5d3ae..5c8fedd45902c 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8411,16 +8411,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 (!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) &&

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..872a527d5de6d
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/store-extract-division-ub.ll
@@ -0,0 +1,114 @@
+; 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"
+
+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 @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:%.*]]) {
+; 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
+}
+
+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