[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