[llvm] [CodeGenPrepare] Fix infinite loop with same-type bitcasts (PR #176694)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 18 22:13:24 PST 2026


https://github.com/nataliakokoromyti created https://github.com/llvm/llvm-project/pull/176694

OptimizeNoopCopyExpression was sinking same-type bitcasts (e.g. bitcast i32 to i32) which would then be reintroduced by optimizePhiType, causing an infinite loop.

Fix this by detecting casts where source and destination types are identical and replacing them with their operand instead of sinking.

Fixes #176688

>From ec73487aba41f6e63c46f07555ebe11a81deccfa Mon Sep 17 00:00:00 2001
From: nataliakokoromyti <nataliakokoromyti at gmail.com>
Date: Sun, 18 Jan 2026 22:10:34 -0800
Subject: [PATCH] [CodeGenPrepare] Fix infinite loop with same-type bitcasts

OptimizeNoopCopyExpression was sinking same-type bitcasts (e.g. bitcast
i32 to i32) which would then be reintroduced by optimizePhiType, causing
an infinite loop.

Fix this by detecting casts where source and destination types are
identical and replacing them with their operand instead of sinking.

Fixes #176688
---
 llvm/lib/CodeGen/CodeGenPrepare.cpp           |  8 +++
 .../X86/codegenprepare-hang-bitcast-phi.ll    | 52 +++++++++++++++++++
 2 files changed, 60 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/codegenprepare-hang-bitcast-phi.ll

diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 1b3fbe45bdb55..cc40cd0315273 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1468,6 +1468,14 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI,
       return false;
   }
 
+  // If the cast is between identical types, just replace it with its operand.
+  // This avoids infinite loops with optimizePhiType which may reintroduce such casts.
+  if (CI->getOperand(0)->getType() == CI->getType()) {
+    CI->replaceAllUsesWith(CI->getOperand(0));
+    CI->eraseFromParent();
+    return true;
+  }
+
   // If this is a noop copy,
   EVT SrcVT = TLI.getValueType(DL, CI->getOperand(0)->getType());
   EVT DstVT = TLI.getValueType(DL, CI->getType());
diff --git a/llvm/test/CodeGen/X86/codegenprepare-hang-bitcast-phi.ll b/llvm/test/CodeGen/X86/codegenprepare-hang-bitcast-phi.ll
new file mode 100644
index 0000000000000..5fe5170bb8ffd
--- /dev/null
+++ b/llvm/test/CodeGen/X86/codegenprepare-hang-bitcast-phi.ll
@@ -0,0 +1,52 @@
+; RUN: llc -O2 -march=x86-64 -o /dev/null %s
+; Check that CodeGenPrepare does not hang on this input.
+; This was caused by an infinite loop between OptimizeNoopCopyExpression
+; and optimizePhiType when handling same-type bitcasts.
+
+define void @foo(i64 %r8) {
+  %r11 = alloca i8, i32 180, align 1
+  br label %BB0
+
+BB0:
+  %r101 = sext i32 0 to i64
+  %r100 = add i64 %r8, %r101
+  %r102 = inttoptr i64 %r100 to ptr
+  %r24 = load i32, ptr %r102, align 4
+  %r143 = getelementptr i8, ptr %r11, i32 128
+  %r144 = load i8, ptr %r143, align 1
+  %r53 = zext i8 %r144 to i32
+  %r145 = icmp ne i32 %r53, 0
+  br i1 %r145, label %BB1, label %BB2
+
+BB1:
+  %r64 = bitcast i32 %r24 to i32
+  br label %BB6
+
+BB2:
+  %r58 = add i32 0, 0
+  %r146 = icmp ne i32 %r58, 0
+  br i1 %r146, label %BB3, label %BB4
+
+BB3:
+  %r147 = getelementptr i8, ptr %r11, i32 148
+  %r148 = bitcast ptr %r147 to ptr
+  %r62 = load i32, ptr %r148, align 4
+  br label %BB5
+
+BB4:
+  %r61 = bitcast i32 %r24 to i32
+  br label %BB5
+
+BB5:
+  %r59 = phi i32 [%r61, %BB4], [%r62, %BB3]
+  %r60 = bitcast i32 %r59 to i32
+  br label %BB6
+
+BB6:
+  %r46 = phi i32 [%r60, %BB5], [%r64, %BB1]
+  %r48 = bitcast i32 %r46 to i32
+  %r149 = getelementptr i8, ptr %r11, i32 140
+  %r150 = bitcast ptr %r149 to ptr
+  store i32 %r48, ptr %r150, align 4
+  ret void
+}



More information about the llvm-commits mailing list