<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/62726>62726</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[flang] Error when lowering to FIR (Block construct)
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
ceseo
</td>
</tr>
</table>
<pre>
`flang-new version 17.0.0 (fc748408c6436c2a80e372156d53e15b014c6105)`
This issue was found while building SPEC CPU 2017 with Flang. A reduced testcase follows:
```
subroutine foo(mystr, myvar)
character(*), optional :: mystr
integer :: myvar
if (present(mystr)) then
select case (trim(mystr))
case ('my_test')
myvar = 77
case default
myvar = 78
end select
else
myvar = 79
end if
end subroutine
```
This generates:
```
error: loc("/tmp/tests/test.f90":11:7): operation with block successors must terminate its parent block
error: verification of lowering to FIR failed
```
Analyzing the `bbc` output:
```
// -----// IR Dump Before Fortran::lower::VerifierPass () //----- //
"builtin.module"() ({
"func.func"() <{arg_attrs = [{fir.bindc_name = "mystr", fir.optional}, {fir.bindc_name = "myvar"}], function_type = (!fir.boxchar<1>, !fir.ref<i32>) -> (), sym_name = "_QPfoo"}> ({
^bb0(%arg0: !fir.boxchar<1>, %arg1: !fir.ref<i32>):
%0 = "fir.alloca"() {in_type = !fir.box<!fir.heap<!fir.char<1,?>>>, operand_segment_sizes = array<i32: 0, 0>} : () -> !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
%1:2 = "fir.unboxchar"(%arg0) : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
%2 = "fir.is_present"(%1#0) : (!fir.ref<!fir.char<1,?>>) -> i1
"cf.cond_br"(%2)[^bb1, ^bb6] <{operand_segment_sizes = array<i32: 1, 0, 0>}> : (i1) -> ()
^bb1: // pred: ^bb0
%3 = "fir.embox"(%1#0, %1#1) {operand_segment_sizes = array<i32: 1, 0, 0, 1, 0>} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
%4 = "fir.zero_bits"() : () -> !fir.heap<!fir.char<1,?>>
%5 = "arith.constant"() <{value = 0 : index}> : () -> index
%6 = "fir.embox"(%4, %5) {operand_segment_sizes = array<i32: 1, 0, 0, 1, 0>} : (!fir.heap<!fir.char<1,?>>, index) -> !fir.box<!fir.heap<!fir.char<1,?>>>
"fir.store"(%6, %0) : (!fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> ()
%7 = "fir.address_of"() {symbol = @_QQcl.dc297055db257c9785cb588cabc17e6c} : () -> !fir.ref<!fir.char<1,36>>
%8 = "arith.constant"() <{value = 6 : i32}> : () -> i32
%9 = "fir.convert"(%0) : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>>
%10 = "fir.convert"(%3) : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
%11 = "fir.convert"(%7) : (!fir.ref<!fir.char<1,36>>) -> !fir.ref<i8>
%12 = "fir.call"(%9, %10, %11, %8) {callee = @_FortranATrim, fastmath = #arith.fastmath<contract>} : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
%13 = "fir.load"(%0) : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.box<!fir.heap<!fir.char<1,?>>>
%14 = "fir.box_elesize"(%13) : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index
%15 = "fir.box_addr"(%13) : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
%16 = "fir.convert"(%15) : (!fir.heap<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,?>>
%17 = "fir.address_of"() {symbol = @_QQcl.6D795F74657374} : () -> !fir.ref<!fir.char<1,7>>
%18 = "arith.constant"() <{value = 7 : index}> : () -> index
%19 = "fir.convert"(%17) : (!fir.ref<!fir.char<1,7>>) -> !fir.ref<!fir.char<1,?>>
%20 = "fir.convert"(%16) : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
%21 = "fir.convert"(%19) : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
%22 = "fir.convert"(%14) : (index) -> i64
%23 = "fir.convert"(%18) : (index) -> i64
%24 = "fir.call"(%20, %21, %22, %23) {callee = @_FortranACharacterCompareScalar1, fastmath = #arith.fastmath<contract>} : (!fir.ref<i8>, !fir.ref<i8>, i64, i64) -> i32
%25 = "arith.constant"() <{value = 0 : i32}> : () -> i32
%26 = "arith.cmpi"(%24, %25) <{predicate = 0 : i64}> : (i32, i32) -> i1
"cf.cond_br"(%26)[^bb3, ^bb2] <{operand_segment_sizes = array<i32: 1, 0, 0>}> : (i1) -> ()
^bb2: // pred: ^bb1
"cf.br"()[^bb4] : () -> ()
^bb3: // pred: ^bb1
%27 = "arith.constant"() <{value = 77 : i32}> : () -> i32
"fir.store"(%27, %arg1) : (i32, !fir.ref<i32>) -> ()
"cf.br"()[^bb5] : () -> ()
^bb4: // pred: ^bb2
%28 = "arith.constant"() <{value = 78 : i32}> : () -> i32
"fir.store"(%28, %arg1) : (i32, !fir.ref<i32>) -> ()
"cf.br"()[^bb5] : () -> ()
^bb5: // 2 preds: ^bb3, ^bb4
"cf.br"()[^bb7] : () -> ()
"fir.freemem"(%15) : (!fir.heap<!fir.char<1,?>>) -> ()
"cf.br"()[^bb7] : () -> ()
^bb6: // pred: ^bb0
%29 = "arith.constant"() <{value = 79 : i32}> : () -> i32
"fir.store"(%29, %arg1) : (i32, !fir.ref<i32>) -> ()
"cf.br"()[^bb7] : () -> ()
^bb7: // 3 preds: ^bb5, ^bb5, ^bb6
"func.return"() : () -> ()
}) : () -> ()
"func.func"() <{function_type = (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none, sym_name = "_FortranATrim", sym_visibility = "private"}> ({
}) {fir.runtime} : () -> ()
"fir.global"() ({
%0 = "fir.string_lit"() {size = 36 : i64, value = "/home/carlos.seo/Downloads/test.f90\00"} : () -> !fir.char<1,36>
"fir.has_value"(%0) : (!fir.char<1,36>) -> ()
}) {constant, linkName = "internal", sym_name = "_QQcl.dc297055db257c9785cb588cabc17e6c", symref = @_QQcl.dc297055db257c9785cb588cabc17e6c, type = !fir.char<1,36>} : () -> ()
"fir.global"() ({
%0 = "fir.string_lit"() {size = 7 : i64, value = "my_test"} : () -> !fir.char<1,7>
"fir.has_value"(%0) : (!fir.char<1,7>) -> ()
}) {constant, linkName = "internal", sym_name = "_QQcl.6D795F74657374", symref = @_QQcl.6D795F74657374, type = !fir.char<1,7>} : () -> ()
"func.func"() <{function_type = (!fir.ref<i8>, !fir.ref<i8>, i64, i64) -> i32, sym_name = "_FortranACharacterCompareScalar1", sym_visibility = "private"}> ({
}) {fir.runtime} : () -> ()
}) {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.target_triple = "aarch64-unknown-linux-gnu"} : () -> ()
error: loc("/tmp/tests/test.f90":11:7): operation with block successors must terminate its parent block
oops, pass manager reported failure
```
This particular bit is interesting:
```
^bb5: // 2 preds: ^bb3, ^bb4
"cf.br"()[^bb7] : () -> ()
"fir.freemem"(%15) : (!fir.heap<!fir.char<1,?>>) -> ()
"cf.br"()[^bb7] : () -> ()
^bb6: // pred: ^bb0
%29 = "arith.constant"() <{value = 79 : i32}> : () -> i32
"fir.store"(%29, %arg1) : (i32, !fir.ref<i32>) -> ()
"cf.br"()[^bb7] : () -> ()
^bb7: // 3 preds: ^bb5, ^bb5, ^bb6
"func.return"() : () -> ()
```
When closing the `SELECT CASE` statement (`^bb5`), it is generating two unconditional branches.
My investigation shows that this problem started after patch `2c1433453d1670f668220670b8f2df60f9dc9949`. Apparently, this new block construct design doesn't handle well these nested blocks (btw, if I remove either the `trim` or `present` calls, it works fine).
I'm working on a fix for this.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWttu4zjSfhrlhoghUeeLXDhOAjTw_4ue6dndS4OiSja3KdIgqbjdT78gdbDk2I7i7p7dBSYIfFKRVfzqqyqWRKI12wiABy9-9OKnO9KYrVQPFDTIu0KWhwcv8StOxOZewB69gtJMChSkC3_hIw9nFU2jLPIzmkRhQjHJfAhTHMRJGYcQxIUfRDQJ_NjDuZf4nv_k-cv29Y8t04hp3QDaE40q2YgS7beMAyoaxksmNujL5-cVWn3-O8J-kKI9M1v0Yo1ZoCVSUDYUSmRAG0o0oEpyLvfaC5djNVZr----6qZQsjFMWHnp4aw-aKM8vEL14ZUoD-eoFUQIIbolilADysOZh5d2DXiF5M4wKQhHVlO4RG6G0SgmDGxAHS-_kuHySKqy8O0UaBDmaEduLTBbECNRhDRwoAa5ZXo4M4rVJ0M--tfN3s_o4bQ-rC2UHk5vmW86bbfm8Aml6WQhqNVYQkUabk4uofG4bHIRRNmDcPwZuDV-JDUaPnajHWzhnrrATTmw4SxZRkTdgABFDLxDL1BKKut1LqmDFXv4xdQ7-wra6O59UeW-vRYug8ALlxZxO0jurA4bYI7qBZf0K9INpaC1VBrVjTbIgKqZIAYQMxrtiAJhWtETE15BsYrRdkJZIS73oGxUGYlePv2OKsI4lFcWvhSEH767EVtAXuIXBfUSH8nG7BpzHQgPv3j4Bd3bv-7zp9_RU1Pv0CNUUgF6kcooItoocba1H__hzAb1mWjdUjNH7Qxusu5zrwXbXGGYWNSybDg4wLshmZc-9s72MK4aQRf2ZSQTrrz0kajNmhijtGOOTYTpY8XUomCipGtBamgvYNwFHLZZwEr0mcBLn-xPV8a51IKtXOxErR127Nocdr1Y5uHAjZffbOLxwlXghc9u4vaCgsoLVyzE7ucc3Xvhc4eQldKHeqJ1_dtnl-Kc2k5yhEj8XBS-Gx0TtfEtY64YYGWCkcyJLQMZrKjfW2AFCeeSkhHm6SObLLtXaZ3RftkC2R2_DabglRe-WHXtv8vEoIgo1xo2NQiz1uw7tF4kSpFDb-AS-Vbat6PSJ9SuIhshOFrR7faEz8eM4-HYgoXHQDSix7XDooXd0XB5xf1jP7819Kw1eIWYKOGbdczYpok9TK-H6tMZFHg4PGPRDIWdkSwY68O0WlApynVxXDO2Ntm9xnNRBI5a9lPixU9dNM72adD69OhYh1JrOAtO42PMesfjLo-gnYLSjWrjYQxXOIYLasuJE6RWqPscdNS-yXq86r-eEPTj7p4wekLisyPHq43Gq_0OSq4LZgvWMVmeDZsZwTHWEvdaiGJma-mhDTlSsM_Jr4Q3bYLwneJ2fRMfH0nnro2VJJcdF3VOi3-dw2YgMstj89JOn3XdWrWRaqiBcdKt9XySuSHf_rxMeT46nfPSSfUoSwVar2U1qSD6UBeSt4KRv_7tN8oXJcV56sdxWeA4pXmaxbSIs4ySggYpJHRu6h9ZHSZnGJx9lMFJy-AQX-JviCcK8jEAVIpXUMcU_V56_lF3XJpRSAHnqpx_zdjwHeJdrSVn1U90B9d0p_Pr2ODmszCw7I3iSR2lhPNBa97XhKE4BN2HnrpWHGCgbrcLXv7hWroVqog2NTHbTkPYkqz_1QtXVApjm9L3a8Ubxx0jeHrpzQ4z63NUiAdMnPCwxQsmtZFLUv65DL05UXYenBS7Qn5bAweb-o8F_j3uzkyaF2tUEJ-aYHPdr9J_W7EOkmsRFsRvTZxT--bl3gsW3Vodkqc0j1_SKInTMI1uqAXpOWs-XAvSG3YzwdWCEHwg0aU_wwX4asoPkh_pH95JvPhqxg_yX6La6sVX9UYjvdNtHUui6QLCqxNl8yeKLpYg3Jce3Jee9oaFU3-9CK36-50rWe-Igi-UcKKCn1WXhrpyodok0fB2YWuEb20fZm--cHKiod6xI7R994Djoy7bQDJKzERfEp00pCE-LahDr3yhUU5GnXI4dMr4T-2U8cVO-U2jfzR9sDpqbT1Ns2-0hPO0xDj9cLpNP-b-M00UTsc3wEbxGeKZt-beByqeCVR0EagTEn-8LmWzgTqPUvZzUPphiOIxRNiBpAeUjmEUvacvfV_fQJhKAdRQ_7yN0UzavG9jd3Nt3u0unH-YNfmPh1f-i4kzw5Gd3Ail8IQ48UCceHTP8hgPjaALBaZR4tr9sonO9GmG0JWnFteeIPzqNvDcw4ZpI4t7mVemWcE4M4decqfYKzFw8blEB0z7LEU1wrAazu_XT6FiarHhsiD80lMg9ObphDaKic2aMzPtINj3dmVhMtRzvEJH5rcP9rayBg-_UKK41AsN0sMvT3IvbD88edQXr3y_XfCltuPN7YhJst0SvXbKr3XZb6a4zrz08RjgK8SZ-Pq3kT-ZMKBEB-W5Z0uzbrkNgxVUH7xbh1fo9CHRmwX-p1iRXiTF8BB9pq_TkxbnJm-nf4qzTzroy649FbzqyHS2H29PhLf1HdeS3MVG6ea8d1Pamw7qDlV8ZaIcCnlAozJjEY9UNHpubUVqsjtmMneF89d6YYjagFkbxXZ8WDchim6T6L4RX4Xci3vORPPtfiOaizwf2Th6_S84HSHlTtvF7ojWqCaCbEAhBTupDJTuSESj4Nq5huORkB1RhtGGE4UKZhDT7uSPAm2Y2Fw_HfHXZvWvzer_zGb1hLv_3IJAlEs9Ohj05fn_nld_oNXyy7OX-EgbYqC2kWfnSfzOmMTvTqq00dIdqXLT7CVqBJWiZN3ZukIRQbegF-Mo-v8DYuLVBtimTQR6K_camS0xyLiQVLLgUFsDXDyTyoBCO2Lo1pqJaRCFYRSHZZCkfpUkGcZ-kvpFVuGySvwqL2meR7mX-Au03LXZgx9cCbPTC9h3acfRTTXUoBI02whUStDCw6lBWyJKDmgPnFt4NCAB2hrjRrojTYXZOxgq9AkpqOUrIGBmC6rH0x3wS3wklf3WH9NIfEQJ57qDcC_VV40qZjfk-QSnTx5Oa3fdgisFIqhi31AllVvH4q58CMs8zMkdPARJFgV5FPvJ3fahiqvKT8u0xEVeBVmZ0wCnfhRAjqOqiMgde8A-Dv04iHEYZThZVDgtMj9LqjgNqxB8L_KhJowvXDWRanPnjng-JDjFyR0nBXDtDptibNF0Fy0N46c79WDH3BfNRnuRz5k2-jiLYYa7U6ruMKoNk2dbTNDesvH0ZJuHs8epmzyc3zWKP2yN2bkjfC50Nsxsm2JBZe3hF6uqe7vfKfkvsKNenIG2MLkF_DsAAP__jWc1Lw">