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.
Thanks. But when the assert trips, that means the insn wasn't optimized
in the way it should. I see it tripping on an insn that looks 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 678 {*branchdi_mask_twobits_equals_singlebit}
(int_list:REG_BR_PROB 365072225 (nil))
Given the mask (0x880) does not include any bits in the equality
constant (0x1), this test can never be true, so in theory we should have
removed it earlier. If we look into the .combine dump we see 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 365072225
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 the point where we likely should have cleaned things up. Probably
would need to be fixed in simplify-rtx.cc or combine.cc.
If I put a breakpoint in simplify_if_then_else, it eventually triggers with:
(if_then_else (eq (and:DI (reg:DI 155 [ d ])
(const_int 2176 [0x880]))
(const_int 1 [0x1]))
(label_ref 45)
(pc))
Given the test is always false, returning the false arm's value, (pc) in
this case, should result in all the right things happening. I don't see
a lot of cases in simplify_if_then_else though.
You can also look at simplify_ternary_operation which after a while
calls simplify_relational_operation_1 with a code of EQ and op0/op1 being:
(gdb) p debug_rtx (op0)
(and:DI (reg:DI 155 [ d ])
(const_int 2176 [0x880]))
$121 = void
(gdb) p debug_rtx (op1)
(const_int 1 [0x1])
$122 = void
That should be pretty easy to clean up.
Jeff