[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