<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56794>56794</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [C++20] [Modules] Named Module Units would generate initializers unconditionally
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            c++20,
            clang:modules
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ChuanqiXu9
      </td>
    </tr>
</table>

<pre>
    For, the following line

```
//--- A.cpp
export module A;
```

and option

```
clang++ -std=c++20 A.cppm --precompile -o A.pcm
clang++ -std=c++20 A.pcm -S -emit-llvm -o A.ll
```

It would generate:
```
@_ZGIW1A__in_chrg = internal global i8 0, align 1
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_ZGIW1A, ptr null }]

define void @_ZGIW1A() #0 section ".text.startup" {
entry:
  %0 = load i8, ptr @_ZGIW1A__in_chrg, align 1
  %guard.uninitialized = icmp eq i8 %0, 0
  br i1 %guard.uninitialized, label %init, label %exit, !prof !4

init:                                             ; preds = %entry
  store i8 1, ptr @_ZGIW1A__in_chrg, align 1
  br label %exit

exit:                                             ; preds = %init, %entry
  ret void
}
```

This is bad. A.cppm has nothing but it generates actual codes. It would be worse if we import something:
```
//--- B.cppm
export module B;
import A;
```

Then the generated code would be:
```
@_ZGIW1B__in_chrg = internal global i8 0, align 1
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_ZGIW1B, ptr null }]

declare void @_ZGIW1A()

define void @_ZGIW1B() #0 section ".text.startup" {
entry:
  %0 = load i8, ptr @_ZGIW1B__in_chrg, align 1
  %guard.uninitialized = icmp eq i8 %0, 0
  br i1 %guard.uninitialized, label %init, label %exit, !prof !4

init:                                             ; preds = %entry
  store i8 1, ptr @_ZGIW1B__in_chrg, align 1
  call void @_ZGIW1A()
  br label %exit

exit:                                             ; preds = %init, %entry
  ret void
}
```

Yeah, it calls the initializer from A. This is a call across TUs so it can't be inlined without LTO. As a result, the startup performance may decrease if there are many many imports.

This is not about the correctness, though.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztVsmO2zgQ_Rr5UpCgxfJy0MFqowcBZjlMB7NcDEqkJQ4oUiGpdHu-forUMt1J250gmEOAsQVKXIpV9arqoSpFL8W90kF6B7ZlcFZCqEcuGxBcsiA-BvFhGjfx9IzT9B6fMAzhENV9Py6yp15pC52ig2BwCLLydVk_EklB9ZYreUNNLYhsgrTEB0JjaZAd63GaxqPmDsKw16xWXc9Raahwua-7LxLHcxD-CiHruA2F-NiN4kLcMPudhUc1CAoNk0wTy4LsCkLr-PTnD-9-Sw6nE5enutUNoH7g0jItiYBGqApffAexg58I3khIFmFnTzSeOdVWaeOlSd8zSV2AJvEgLxN4gmBbAs9Sd1Fv9fTC1WOQH92Zq_uzJGzyPMuXjcX4eUUOQkz3PYeDsjMmCnxUnL4Q2gXpHoI0i8Gw2gUZJ2lk2ZONjCXaDj3One4pc6TVlwVJwMN57P0VilCE6HO7FlA_w85LNwPRNBokl9xy3P6b0RH9uuuBfXCoOx1OOJ7FKg08uSLsDgpSMeH23fqLBfY0LgRp0mt1du_1c5S8QIYqvuKH1QOY2HSMu1PiMZpsNZgRzHmRfB006ONLq59Z6effauWMzacGa2Z9lkwKt8cbNfbQcgP4VIRGc5W3xIBUtnWpXw0WuF0q0ACp7YC1UCvKTARLiVYMP7RBnM7wiGPn6cmojvl7rlbuwm2l1_0auZULuU23vsF2Dy2TnmFno6m3djH0TRYpv2cWKd9kEWRqfYVG3qSb8r-nm_J_urlGNzehqQnG-0ZUvxNC-oOR1t2BpOM8Mr6S_w2XhrNWHTIVzMxFRs9JrZUx8PDeIOuM0jJIt9YxE5euxaLwyG2rkNB-fPgFyc6JamYGYeeWbMpf6Jk-K90RWTPoyAWwZjQjI7nhOQyPqyDcv4zDyEsmeo1YkUiBVE6r01ArjQ2UlcyYUakamnaSW7Ei2eT7eJfGebyiRUb32Z6sLLeCFcgId3M7NTHET54ejZv9TDp0b1yA9wiW-aRzeo6ggUHWCjnJFS9Cd1kNWhSttb1xdeoZuUGkhirCVg8njtimF_Z_6i90AKfcmAG1p_f5Zrtfr9oijs91nK3rNaHrhBC63e03LCebbLPGf8JWPvmMcwUZYmkO8XvMmXRsIbNDNzmGG_lxxYs0TtN4myIyboySfHcm53W22WTJblttMd1ZR7iIPAEr3ax04W2thsY4XuYGY7NsEmOwbpiH1N1PBoyCLu7agcgP_Pdhv_KeFd6tfwAWwlPe">