[llvm] [CodeGenPrepare] Drop nuw on gep unmerging if the new index is negative (PR #193488)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 22 10:54:25 PDT 2026
https://github.com/MuellerMP updated https://github.com/llvm/llvm-project/pull/193488
>From 1c28d0fbe8631546fd6869802c2eebc2e87d6632 Mon Sep 17 00:00:00 2001
From: MuellerMP <mirkomueller97 at live.de>
Date: Wed, 22 Apr 2026 14:31:54 +0200
Subject: [PATCH] [CodeGenPrepare] Drop nuw on gep unmerging if the new index
is negative
Fixes #193487.
Drop nuw if unmerging would result in gep with a negative index.
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 9 +++++--
.../X86/indirect-br-gep-unmerge-nuw.ll | 26 +++++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/indirect-br-gep-unmerge-nuw.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 2c232c6158749..0a469e82c8a64 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8814,14 +8814,19 @@ static bool tryUnmergingGEPsAcrossIndirectBr(GetElementPtrInst *GEPI,
for (GetElementPtrInst *UGEPI : UGEPIs) {
UGEPI->setOperand(0, GEPI);
ConstantInt *UGEPIIdx = cast<ConstantInt>(UGEPI->getOperand(1));
- Constant *NewUGEPIIdx = ConstantInt::get(
- GEPIIdx->getType(), UGEPIIdx->getValue() - GEPIIdx->getValue());
+ auto NewIdx = UGEPIIdx->getValue() - GEPIIdx->getValue();
+ Constant *NewUGEPIIdx = ConstantInt::get(GEPIIdx->getType(), NewIdx);
UGEPI->setOperand(1, NewUGEPIIdx);
// If GEPI is not inbounds but UGEPI is inbounds, change UGEPI to not
// inbounds to avoid UB.
if (!GEPI->isInBounds()) {
UGEPI->setIsInBounds(false);
}
+
+ // If UGEPI now has a negative index, drop the nuw flag.
+ auto Flags = UGEPI->getNoWrapFlags();
+ if (NewIdx.isNegative() && Flags.hasNoUnsignedWrap())
+ UGEPI->setNoWrapFlags(Flags.withoutNoUnsignedWrap());
}
// After unmerging, verify that GEPIOp is actually only used in SrcBlock (not
// alive on IndirectBr edges).
diff --git a/llvm/test/CodeGen/X86/indirect-br-gep-unmerge-nuw.ll b/llvm/test/CodeGen/X86/indirect-br-gep-unmerge-nuw.ll
new file mode 100644
index 0000000000000..7c47dec8d029f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/indirect-br-gep-unmerge-nuw.ll
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes="require<profile-summary>,function(codegenprepare)" %s -o - | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+
+define ptr @test(ptr %memory, ptr %blockaddress) {
+; CHECK-LABEL: define ptr @test(
+; CHECK-SAME: ptr [[MEMORY:%.*]], ptr [[BLOCKADDRESS:%.*]]) {
+; CHECK-NEXT: [[BB4:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[MEMORY]], align 8
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP2]], i64 8
+; CHECK-NEXT: indirectbr ptr [[BLOCKADDRESS]], [label %[[EXIT:.*]]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP3]], i64 -1
+; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP3]], align 1
+; CHECK-NEXT: ret ptr [[TMP5]]
+;
+entry:
+ %pointer = load ptr, ptr %memory, align 8
+ %initalGEP = getelementptr i8, ptr %pointer, i64 8
+ indirectbr ptr %blockaddress, [label %exit]
+
+exit:
+ %unmergedGEP = getelementptr nuw i8, ptr %pointer, i64 7
+ %useOfFirstGEP = load i8, ptr %initalGEP, align 1
+ ret ptr %unmergedGEP
+}
More information about the llvm-commits
mailing list