[all-commits] [llvm/llvm-project] 82134c: [CIR] Terminate conditional regions after creation...

Akshay K via All-commits all-commits at lists.llvm.org
Fri Jul 17 13:52:03 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 82134c708f7ec224d86e2096d9b53c76640a490f
      https://github.com/llvm/llvm-project/commit/82134c708f7ec224d86e2096d9b53c76640a490f
  Author: Akshay K <iit.akshay at gmail.com>
  Date:   2026-07-17 (Fri, 17 Jul 2026)

  Changed paths:
    M clang/lib/CIR/CodeGen/CIRGenExpr.cpp
    M clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
    M clang/test/CIR/CodeGen/ternary-throw.cpp

  Log Message:
  -----------
  [CIR] Terminate conditional regions after creation; fix glvalue conditional with a throw arm (#210384)

Follow-up to #208850: @andykaylor's comments about
`CIRGenFunction::emitConditionalBlocks` also have a similar
insertion-point problem.

The PR addresses the two related problems found while looking into the
conditional branch emission path:

**1. Terminate conditional regions after creation instead of patching
yields**
`CIRGenFunction::emitConditionalBlocks` still had the save-and-patch
insertion-point machinery removed from the scalar path in #208850. The
path is unreachable, and its guard is saved only after
`cir.unreachable`, where a patched yield would generate the dead code.
The machinery is removed; regions are closed with
`terminateStructuredRegionBody` after creation.

The aggregate emitter had the reverse problem: an unconditional
cir.yield after each arm lands in the dead block a throw leaves behind
and keeps it in the final CIR:

```
struct test_s { int x; int y; };
void test_throw(bool flag) {
  test_s a = flag ? throw 0 : test_s{1, 2};
}
mlir
cir.if %2 {
  ...
  cir.throw %3 : !cir.ptr<!s32i>, @_ZTIi
  cir.unreachable
^bb1:  // no predecessors      <-- dead block kept alive by the yield
  cir.yield
} else {
  ...
}
```
The explicit yields are removed; `emitIfOnBoolExpr` already terminates
each region, adding a yield only where one is missing. Tests pin the
dead block's absence with CIR-NEXT after `cir.unreachable`.

**2. Fix glvalue conditionals with a throw arm using a region-local
pointer**

```
int &ref_cond(bool c, int &x) { return c ? x : throw 0; }
// error: operand #0 does not dominate this use
// fatal error: CIR module verification error
```
With one arm throwing, `emitConditionalOperatorLValue` returned the
surviving arm's LValue directly, valid in OG CodeGen's flat CFG, invalid
in CIR where the pointer is materialized inside the ternary's region:

```
%4 = cir.ternary(%3, true {
  %8 = cir.load %1 ...          // pointer loaded inside the region
  cir.yield %8 : !cir.ptr<!s32i>
}, false { ... cir.unreachable })
cir.store %8, %2 ...            // region-local %8 used outside the region
```

Existing tests missed it because a local's pointer is a function-entry
`alloca`, so dominance held by accident. The fix addresses the result
through the ternary's result value, which the yield carries out. New
tests cover a reference parameter, assignment via the conditional, and
member access, all of which previously failed verification.

Assisted-by: Cursor/Codex



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list