Author: Justin Stitt
Date: 2026-01-19T10:03:53Z
New Revision: 2fb8921a7c70b264f670569ac319d1c96e9f5acc

URL: 
https://github.com/llvm/llvm-project/commit/2fb8921a7c70b264f670569ac319d1c96e9f5acc
DIFF: 
https://github.com/llvm/llvm-project/commit/2fb8921a7c70b264f670569ac319d1c96e9f5acc.diff

LOG: [CodeGen] Check BlockAddress users before marking block as taken (#174480)

(cherry picked from commit 404920838836a022b0ae4b9a462befba89ee0cdc)

Added: 
    llvm/test/CodeGen/AArch64/GlobalISel/blockaddress-stale-addresstaken.ll
    llvm/test/CodeGen/X86/blockaddress-stale-addresstaken.ll

Modified: 
    llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
    llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
    llvm/test/CodeGen/X86/speculative-load-hardening-indirect.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp 
b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 12552bce3caaa..e1b7e192939c9 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -4217,8 +4217,14 @@ bool IRTranslator::runOnMachineFunction(MachineFunction 
&CurMF) {
     MBB = MF->CreateMachineBasicBlock(&BB);
     MF->push_back(MBB);
 
-    if (BB.hasAddressTaken())
-      MBB->setAddressTakenIRBlock(const_cast<BasicBlock *>(&BB));
+    // Only mark the block if the BlockAddress actually has users. The
+    // hasAddressTaken flag may be stale if the BlockAddress was optimized away
+    // but the constant still exists in the uniquing table.
+    if (BB.hasAddressTaken()) {
+      if (BlockAddress *BA = BlockAddress::lookup(&BB))
+        if (!BA->hasZeroLiveUses())
+          MBB->setAddressTakenIRBlock(const_cast<BasicBlock *>(&BB));
+    }
 
     if (!HasMustTailInVarArgFn)
       HasMustTailInVarArgFn = checkForMustTailInVarArgFn(IsVarArg, BB);

diff  --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp 
b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index e73743ecbc9fa..dfaabae6e1f97 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/CodeGen/WasmEHFuncInfo.h"
 #include "llvm/CodeGen/WinEHFuncInfo.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
@@ -277,8 +278,14 @@ void FunctionLoweringInfo::set(const Function &fn, 
MachineFunction &mf,
     // Transfer the address-taken flag. This is necessary because there could
     // be multiple MachineBasicBlocks corresponding to one BasicBlock, and only
     // the first one should be marked.
-    if (BB.hasAddressTaken())
-      MBB->setAddressTakenIRBlock(const_cast<BasicBlock *>(&BB));
+    // Only mark the block if the BlockAddress actually has users. The
+    // hasAddressTaken flag may be stale if the BlockAddress was optimized away
+    // but the constant still exists in the uniquing table.
+    if (BB.hasAddressTaken()) {
+      if (BlockAddress *BA = BlockAddress::lookup(&BB))
+        if (!BA->hasZeroLiveUses())
+          MBB->setAddressTakenIRBlock(const_cast<BasicBlock *>(&BB));
+    }
 
     // Mark landing pad blocks.
     if (BB.isEHPad())

diff  --git 
a/llvm/test/CodeGen/AArch64/GlobalISel/blockaddress-stale-addresstaken.ll 
b/llvm/test/CodeGen/AArch64/GlobalISel/blockaddress-stale-addresstaken.ll
new file mode 100644
index 0000000000000..601645e0944f5
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/blockaddress-stale-addresstaken.ll
@@ -0,0 +1,48 @@
+; RUN: llc -O0 -mtriple=aarch64-linux-gnu -global-isel 
-stop-after=irtranslator %s -o - | FileCheck %s
+
+; Test that the GlobalISel IRTranslator correctly marks blocks as address-taken
+; based on whether the BlockAddress actually has users.
+
+; CHECK-LABEL: name: test_indirectbr_blockaddress
+; CHECK: G_BLOCK_ADDR blockaddress(@test_indirectbr_blockaddress, 
%ir-block.target)
+; CHECK: G_BLOCK_ADDR blockaddress(@test_indirectbr_blockaddress, 
%ir-block.other)
+; CHECK: G_BRINDIRECT
+; CHECK: bb.{{[0-9]+}}.target (ir-block-address-taken %ir-block.target):
+; CHECK: bb.{{[0-9]+}}.other (ir-block-address-taken %ir-block.other):
+define i32 @test_indirectbr_blockaddress(i32 %idx) {
+entry:
+  %targets = alloca [2 x ptr], align 8
+  %ptr0 = getelementptr [2 x ptr], ptr %targets, i64 0, i64 0
+  store ptr blockaddress(@test_indirectbr_blockaddress, %target), ptr %ptr0, 
align 8
+  %ptr1 = getelementptr [2 x ptr], ptr %targets, i64 0, i64 1
+  store ptr blockaddress(@test_indirectbr_blockaddress, %other), ptr %ptr1, 
align 8
+  %idx64 = zext i32 %idx to i64
+  %selected = getelementptr [2 x ptr], ptr %targets, i64 0, i64 %idx64
+  %dest = load ptr, ptr %selected, align 8
+  indirectbr ptr %dest, [label %target, label %other]
+
+target:
+  ret i32 42
+
+other:
+  ret i32 -1
+}
+
+; normal conditional branch (no blockaddress).
+; blocks should NOT be marked as address-taken.
+
+; CHECK-LABEL: name: test_normal_branch
+; CHECK: bb.{{[0-9]+}}.target:
+; CHECK-NOT: ir-block-address-taken
+; CHECK: bb.{{[0-9]+}}.other:
+; CHECK-NOT: ir-block-address-taken
+define i32 @test_normal_branch(i1 %cond) {
+entry:
+  br i1 %cond, label %target, label %other
+
+target:
+  ret i32 42
+
+other:
+  ret i32 -1
+}

diff  --git a/llvm/test/CodeGen/X86/blockaddress-stale-addresstaken.ll 
b/llvm/test/CodeGen/X86/blockaddress-stale-addresstaken.ll
new file mode 100644
index 0000000000000..52adca08cb259
--- /dev/null
+++ b/llvm/test/CodeGen/X86/blockaddress-stale-addresstaken.ll
@@ -0,0 +1,39 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+retpoline | 
FileCheck %s
+;
+; verify that blocks are NOT marked as "Block address taken" when the
+; BlockAddress constant has no users (was optimized away).
+;
+; With retpoline enabled, the indirectbr is replaced with direct comparisons
+; against constant integer values. The BlockAddress constants in the global
+; array become unused (constant-folded to integers), so the blocks should NOT
+; be marked as address-taken.
+
+@targets = internal constant [4 x ptr] [
+  ptr blockaddress(@test_stale_addresstaken, %bb0),
+  ptr blockaddress(@test_stale_addresstaken, %bb1),
+  ptr blockaddress(@test_stale_addresstaken, %bb2),
+  ptr blockaddress(@test_stale_addresstaken, %bb3)
+]
+
+define i32 @test_stale_addresstaken(i32 %idx) {
+entry:
+  %ptr = getelementptr [4 x ptr], ptr @targets, i32 0, i32 %idx
+  %dest = load ptr, ptr %ptr
+  indirectbr ptr %dest, [label %bb0, label %bb1, label %bb2, label %bb3]
+
+; CHECK-LABEL: test_stale_addresstaken:
+; CHECK-NOT: Block address taken
+; CHECK-LABEL: .Lfunc_end0:
+
+bb0:
+  ret i32 0
+
+bb1:
+  ret i32 1
+
+bb2:
+  ret i32 2
+
+bb3:
+  ret i32 3
+}

diff  --git a/llvm/test/CodeGen/X86/speculative-load-hardening-indirect.ll 
b/llvm/test/CodeGen/X86/speculative-load-hardening-indirect.ll
index fd5085c8c2ac9..2092fc9cd6e00 100644
--- a/llvm/test/CodeGen/X86/speculative-load-hardening-indirect.ll
+++ b/llvm/test/CodeGen/X86/speculative-load-hardening-indirect.ll
@@ -464,34 +464,34 @@ define dso_local i32 @test_indirectbr_global(i32 %idx) 
nounwind {
 ; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
 ; X64-RETPOLINE-NEXT:    cmpq $4, %rdx
 ; X64-RETPOLINE-NEXT:    jne .LBB6_3
-; X64-RETPOLINE-NEXT:  .Ltmp0: # Block address taken
 ; X64-RETPOLINE-NEXT:  # %bb.6: # %bb3
 ; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
 ; X64-RETPOLINE-NEXT:    shlq $47, %rcx
 ; X64-RETPOLINE-NEXT:    movl $42, %eax
 ; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
 ; X64-RETPOLINE-NEXT:    retq
-; X64-RETPOLINE-NEXT:  .Ltmp1: # Block address taken
 ; X64-RETPOLINE-NEXT:  .LBB6_5: # %bb2
 ; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
 ; X64-RETPOLINE-NEXT:    shlq $47, %rcx
 ; X64-RETPOLINE-NEXT:    movl $13, %eax
 ; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
 ; X64-RETPOLINE-NEXT:    retq
-; X64-RETPOLINE-NEXT:  .Ltmp2: # Block address taken
 ; X64-RETPOLINE-NEXT:  .LBB6_4: # %bb1
 ; X64-RETPOLINE-NEXT:    cmovneq %rax, %rcx
 ; X64-RETPOLINE-NEXT:    shlq $47, %rcx
 ; X64-RETPOLINE-NEXT:    movl $7, %eax
 ; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
 ; X64-RETPOLINE-NEXT:    retq
-; X64-RETPOLINE-NEXT:  .Ltmp3: # Block address taken
 ; X64-RETPOLINE-NEXT:  .LBB6_3: # %bb0
 ; X64-RETPOLINE-NEXT:    cmoveq %rax, %rcx
 ; X64-RETPOLINE-NEXT:    shlq $47, %rcx
 ; X64-RETPOLINE-NEXT:    movl $2, %eax
 ; X64-RETPOLINE-NEXT:    orq %rcx, %rsp
 ; X64-RETPOLINE-NEXT:    retq
+; X64-RETPOLINE-NEXT:  .Ltmp0: # Address of block that was removed by CodeGen
+; X64-RETPOLINE-NEXT:  .Ltmp1: # Address of block that was removed by CodeGen
+; X64-RETPOLINE-NEXT:  .Ltmp2: # Address of block that was removed by CodeGen
+; X64-RETPOLINE-NEXT:  .Ltmp3: # Address of block that was removed by CodeGen
 entry:
   %ptr = getelementptr [4 x ptr], ptr @global_blockaddrs, i32 0, i32 %idx
   %a = load ptr, ptr %ptr


        
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to