[llvm] [ConstraintElim] Do not model negative nuw-only GEP offset as signed. (PR #203620)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 13:02:36 PDT 2026
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/203620
decomposeGEP added the GEP's constant offset to the unsigned decomposition using its signed value (getSExtValue()). For a GEP that only carries nuw (without nusw/inbounds), the indices must be interpreted as unsigned.
Alive2 Proof of mis-compile https://alive2.llvm.org/ce/z/7G8uE3
>From 4f7a9bee5cb108f4e68dba19029b811a764f60db Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 9 Jun 2026 19:18:23 +0100
Subject: [PATCH] [ConstraintElim] Do not model negative nuw-only GEP offset as
signed.
decomposeGEP added the GEP's constant offset to the unsigned decomposition
using its signed value (getSExtValue()). For a GEP that only carries nuw
(without nusw/inbounds), the indices must be interpreted as unsigned.
Alive2 Proof of mis-compile https://alive2.llvm.org/ce/z/7G8uE3
---
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 6 ++++++
.../ConstraintElimination/geps-unsigned-predicates.ll | 4 ++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 4bb49d61f3617..4974764163c4c 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -462,6 +462,12 @@ static Decomposition decomposeGEP(GEPOperator &GEP,
if (!BasePtr || NW == GEPNoWrapFlags::none())
return &GEP;
+ // For a nuw-only GEP (nuw without nusw/inbounds), the offset must be
+ // interpreted as unsigned.
+ if (NW.hasNoUnsignedWrap() && !NW.hasNoUnsignedSignedWrap() &&
+ ConstantOffset.isNegative())
+ return &GEP;
+
Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
for (auto [Index, Scale] : VariableOffsets) {
auto IdxResult = decompose(Index, Preconditions, IsSigned, DL);
diff --git a/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll b/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll
index 28266857085bc..612bf2f0a8337 100644
--- a/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll
+++ b/llvm/test/Transforms/ConstraintElimination/geps-unsigned-predicates.ll
@@ -650,11 +650,11 @@ trap:
declare void @use(i1)
-; FIXME: Currently incorrectly simplified to true.
define i1 @gep_nuw_negative_offset_unsigned(ptr %p) {
; CHECK-LABEL: @gep_nuw_negative_offset_unsigned(
; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 -100
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[P2]], [[P]]
+; CHECK-NEXT: ret i1 [[C]]
;
%p2 = getelementptr nuw i8, ptr %p, i64 -100
%c = icmp ult ptr %p2, %p
More information about the llvm-commits
mailing list