[llvm] [CodeGenPrepare] Do not undo GEP unmerging in AddrSinkUsingGEPs (PR #197685)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 14 06:53:45 PDT 2026
https://github.com/MuellerMP created https://github.com/llvm/llvm-project/pull/197685
Fixes #197684.
Do not sink gep calculation after it has been unmerged to prevent an infinite loop.
>From 661e8057900368268a92cc5fda0f7956ac5b069d Mon Sep 17 00:00:00 2001
From: MuellerMP <mirkomueller97 at live.de>
Date: Thu, 14 May 2026 15:51:24 +0200
Subject: [PATCH] [CodeGenPrepare] Do not undo GEP unmerging in
AddrSinkUsingGEPs
Fixes #197684.
Do not sink gep calculation after it has been unmerged to prevent an infinite loop.
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 9 +++++
.../X86/indirect-br-gep-unmerge-sink.ll | 37 +++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/indirect-br-gep-unmerge-sink.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 74a0502d8cb7c..d5e1957ce0a84 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -6140,6 +6140,13 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
} else {
if (ResultPtr->getType() != I8PtrTy)
ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy);
+
+ if (auto *GEP = dyn_cast<GetElementPtrInst>(Addr)) {
+ // Do not revert the gep unmerging optimization.
+ if (GEP->getMetadata("cgp.unmerged_gep"))
+ return Modified;
+ }
+
SunkAddr = Builder.CreatePtrAdd(ResultPtr, ResultIndex, "sunkaddr",
AddrMode.InBounds);
}
@@ -8824,6 +8831,8 @@ static bool tryUnmergingGEPsAcrossIndirectBr(GetElementPtrInst *GEPI,
if (NewIdx.isNegative() && TargetFlags.hasNoUnsignedWrap())
TargetFlags = TargetFlags.withoutNoUnsignedWrap();
UGEPI->setNoWrapFlags(TargetFlags);
+ UGEPI->setMetadata("cgp.unmerged_gep",
+ MDNode::get(UGEPI->getContext(), {}));
}
// 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-sink.ll b/llvm/test/CodeGen/X86/indirect-br-gep-unmerge-sink.ll
new file mode 100644
index 0000000000000..8728fa51b29d3
--- /dev/null
+++ b/llvm/test/CodeGen/X86/indirect-br-gep-unmerge-sink.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes="require<profile-summary>,function(codegenprepare)" -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s
+ at addrTable = global [2 x ptr] [ptr blockaddress(@testGepUnmergingDoesNotGetUndone, %exit1), ptr blockaddress(@testGepUnmergingDoesNotGetUndone, %exit2)]
+
+define void @testGepUnmergingDoesNotGetUndone() {
+; CHECK-LABEL: define void @testGepUnmergingDoesNotGetUndone() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1
+; CHECK-NEXT: [[BASEGEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 16
+; CHECK-NEXT: indirectbr ptr null, [label %[[EXIT1:.*]], label %[[EXIT2:.*]]]
+; CHECK: [[EXIT1]]:
+; CHECK-NEXT: call void @useOfGEP(ptr [[BASEGEP]])
+; CHECK-NEXT: ret void
+; CHECK: [[EXIT2]]:
+; CHECK-NEXT: [[UNMERGEDGEP:%.*]] = getelementptr i8, ptr [[BASEGEP]], i64 24, !cgp.unmerged_gep [[META0:![0-9]+]]
+; CHECK-NEXT: store i32 0, ptr [[UNMERGEDGEP]], align 8
+; CHECK-NEXT: ret void
+;
+entry:
+ %ptr = alloca i8
+ %baseGEP = getelementptr i8, ptr %ptr, i64 16
+ indirectbr ptr null, [label %exit1, label %exit2]
+
+exit1: ; preds = %entry
+ call void @useOfGEP(ptr %baseGEP)
+ ret void
+
+exit2: ; preds = %entry
+ %unmergedGEP = getelementptr i8, ptr %ptr, i64 40
+ store i32 0, ptr %unmergedGEP, align 8
+ ret void
+}
+
+declare void @useOfGEP(ptr)
+;.
+; CHECK: [[META0]] = !{}
+;.
More information about the llvm-commits
mailing list