[llvm] [CodeGenPrepare] Do not unmerge gep nuw if the new index is minus one (PR #193488)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 22 08:42:10 PDT 2026
https://github.com/MuellerMP updated https://github.com/llvm/llvm-project/pull/193488
>From 604005b5841283fe12e03bab752bb6ba096742c8 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 | 5 +++-
.../X86/indirect-br-gep-unmerge-nuw.ll | 27 +++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
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..b5679a7ef3833 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8801,10 +8801,13 @@ static bool tryUnmergingGEPsAcrossIndirectBr(GetElementPtrInst *GEPI,
}
if (UGEPIs.size() == 0)
return false;
- // Check the materializing cost of (Uidx-Idx).
+ // Check materializing cost of (Uidx-Idx) and drop nuw flag if necessary.
for (GetElementPtrInst *UGEPI : UGEPIs) {
ConstantInt *UGEPIIdx = cast<ConstantInt>(UGEPI->getOperand(1));
APInt NewIdx = UGEPIIdx->getValue() - GEPIIdx->getValue();
+ if (NewIdx.isNegative() && UGEPI->hasNoUnsignedWrap())
+ UGEPI->setNoWrapFlags(GEPNoWrapFlags::none());
+
InstructionCost ImmCost = TTI->getIntImmCost(
NewIdx, GEPIIdx->getType(), TargetTransformInfo::TCK_SizeAndLatency);
if (ImmCost > TargetTransformInfo::TCC_Basic)
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..77a2be538016d
--- /dev/null
+++ b/llvm/test/CodeGen/X86/indirect-br-gep-unmerge-nuw.ll
@@ -0,0 +1,27 @@
+; 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
+ %test = load volatile i8, ptr %unmergedGEP, align 1
+ ret ptr %unmergedGEP
+}
More information about the llvm-commits
mailing list