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

Reply via email to