[llvm] [CodeGenPrepare] Fix crash in tryUnmergingGEPsAcrossIndirectBr with asm goto (PR #201443)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 02:27:33 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Hesam (hesam-oxe)

<details>
<summary>Changes</summary>

This fixes a crash in `tryUnmergingGEPsAcrossIndirectBr` when 
compiling with `asm goto`.

## Problem
When `asm goto` creates an indirect branch, `CodeGenPrepare` calls 
`tryUnmergingGEPsAcrossIndirectBr`, which accesses `getTerminator()` 
on a block that is not yet well-formed (no terminator). This causes 
an assertion failure:

```Assertion `hasTerminator() && "cannot get terminator of non-well-formed block"' failed.```
This affects RISC-V and potentially other targets at -O1 and above 
when `asm goto` is used.

## Fix
Added a guard to check `hasTerminator()` before accessing 
`getTerminator()`. If the block is empty or has no terminator, 
we bail out early and return `false` — which is safe because GEP 
unmerging is not valid across indirect branches anyway.

## Test
Fixes the crash reported in #<!-- -->201252. The original test case from 
@<!-- -->iamanonymouscs now compiles successfully.

Credits to @<!-- -->topperc for identifying the root cause in the issue.

Closes #<!-- -->201252

---
Full diff: https://github.com/llvm/llvm-project/pull/201443.diff


2 Files Affected:

- (modified) llvm/lib/CodeGen/CodeGenPrepare.cpp (+5) 
- (added) llvm/test/CodeGen/RISCV/asm-goto-cgp-crash.ll (+18) 


``````````diff
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index aa14d2586a534..2ca24702d4e4e 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -8732,6 +8732,11 @@ static bool GEPSequentialConstIndexed(GetElementPtrInst *GEP) {
 static bool tryUnmergingGEPsAcrossIndirectBr(GetElementPtrInst *GEPI,
                                              const TargetTransformInfo *TTI) {
   BasicBlock *SrcBlock = GEPI->getParent();
+  // SrcBlock may not be well-formed yet (e.g., asm goto can create blocks
+  // without terminators during CodeGenPrepare). Bail out early to avoid
+  // crashing in getTerminator().
+  if (SrcBlock->empty() || !SrcBlock->hasTerminator())
+    return false;
   // Check that SrcBlock ends with an IndirectBr. If not, give up. The common
   // (non-IndirectBr) cases exit early here.
   if (!isa<IndirectBrInst>(SrcBlock->getTerminator()))
diff --git a/llvm/test/CodeGen/RISCV/asm-goto-cgp-crash.ll b/llvm/test/CodeGen/RISCV/asm-goto-cgp-crash.ll
new file mode 100644
index 0000000000000..b649bd583d8cf
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/asm-goto-cgp-crash.ll
@@ -0,0 +1,18 @@
+; RUN: llc -O1 -mtriple=riscv64 -filetype=null < %s
+; REQUIRES: riscv-registered-target
+; Test that CodeGenPrepare doesn't crash with asm goto
+
+define void @test_asm_goto_crash(i32 %x) {
+entry:
+  switch i32 %x, label %default [
+    i32 0, label %indirect
+  ]
+indirect:
+  %target = phi ptr [ label %default, label %entry ]
+  callbr void asm sideeffect "j ${0:l}", "X"(ptr blockaddress(@test_asm_goto_crash, %default))
+          to label %normal [label %default]
+normal:
+  ret void
+default:
+  ret void
+}
\ No newline at end of file

``````````

</details>


https://github.com/llvm/llvm-project/pull/201443


More information about the llvm-commits mailing list