On 12/28/2025 7:42 PM, Bohan Lei wrote:
The assertion in the preparation statements of the split
*branch<X:mode>_mask_twobits_equals_singlebit can be false under rare
circumstances. Moving the conditional to the insn condition seems
reasonable.
gcc/ChangeLog:
* config/riscv/bitmanip.md: Move assertion expression to insn
condition
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zbs-if_then_else-02.c: New test.
If that assert triggers, then it's a sign something has gone wrong
elsewhere. Essentially the condition is a compile-time constant and it
should have been optimized away.
I'm pretty sure the case you're running into looks something like this:
(jump_insn 40 27 41 4 (parallel [
(set (pc)
(if_then_else (eq (and:DI (reg:DI 14 a4 [orig:155 d ]
[155])
(const_int 2176 [0x880]))
(const_int 1 [0x1]))
(label_ref:DI 45)
(pc)))
(clobber (reg:DI 13 a3 [174]))
(clobber (reg:DI 12 a2 [175]))
]) "j.c":28:10 636 {*branchdi_mask_twobits_equals_singlebit}
(int_list:REG_BR_PROB 365072228 (nil))
-> 45)
Which is always false. So we'd very much like to clean that up.
I suspect it looks something like this is gimple:
;; basic block 6, loop depth 0, count 268435456 (estimated locally,
freq 0.2500)
;; prev block 5, next block 7, flags: (NEW, REACHABLE, VISITED)
;; pred: 5 [50.0% (guessed)] count:268435456 (estimated
locally, freq 0.2500) (TRUE_VALUE,EXECUTABLE)
_8 = d;
_14 = _8 & 2176;
_15 = s.a;
_16 = _14 | _15;
if (_16 != 1)
goto <bb 7>; [66.00%]
else
goto <bb 8>; [34.00%]
Nothing obviously optimizable there. I happen to know that s.a is
uninitialized on one path to that block and has the value 0 on the
other. But I wouldn't want to try and focus on optimizing that
uninitialized path. It feels like we need to catch this a bit later.
Before combine we have this block of code:
(insn 30 27 31 4 (set (reg:DI 157)
(const_int 2176 [0x880])) "j.c":28:32 273 {*mvconst_internal}
(nil))
(insn 31 30 38 4 (set (reg:DI 156)
(and:DI (reg:DI 155 [ d ])
(reg:DI 157))) "j.c":28:32 104 {*anddi3}
(expr_list:REG_DEAD (reg:DI 157)
(expr_list:REG_DEAD (reg:DI 155 [ d ])
(expr_list:REG_EQUAL (and:DI (reg:DI 155 [ d ])
(const_int 2176 [0x880]))
(nil)))))
(insn 38 31 39 4 (set (reg:DI 165)
(sign_extend:DI (subreg:SI (reg:DI 156) 0))) "j.c":28:10 125
{*extendsidi2_internal}
(expr_list:REG_DEAD (reg:DI 156)
(nil)))
(insn 39 38 40 4 (set (reg:DI 166)
(const_int 1 [0x1])) "j.c":28:10 275 {*movdi_64bit}
(nil))
(jump_insn 40 39 41 4 (set (pc)
(if_then_else (eq (reg:DI 165)
(reg:DI 166))
(label_ref 45)
(pc))) "j.c":28:10 368 {*branchdi}
(expr_list:REG_DEAD (reg:DI 166)
(expr_list:REG_DEAD (reg:DI 165)
(int_list:REG_BR_PROB 365072228 (nil))))
During combine we have this:
Trying 30, 39, 38 -> 40:
30: r157:DI=0x880
39: r166:DI=0x1
38: r165:DI=r155:DI&r157:DI
REG_DEAD r155:DI
REG_DEAD r157:DI
40: pc={(r165:DI==r166:DI)?L45:pc}
REG_DEAD r166:DI
REG_DEAD r165:DI
REG_BR_PROB 365072228
Successfully matched this instruction:
(set (pc)
(if_then_else (eq (and:DI (reg:DI 155 [ d ])
(const_int 2176 [0x880]))
(const_int 1 [0x1]))
(label_ref 45)
(pc)))
That's where we need to focus. This is what gets passed to
simplify_if_then_else:
(if_then_else (eq (and:DI (reg:DI 155 [ d ])
(const_int 2176 [0x880]))
(const_int 1 [0x1]))
(label_ref 45)
(pc))
I'd try to see if there's a reasonable way to extend
simplify_if_then_else to capture these kinds of cases.
Given this is an ICE, I'm going to go ahead and get a bug report filed
so that it's tracked.
Jeff