https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92263

--- Comment #5 from Jim Wilson <wilson at gcc dot gnu.org> ---
The patch adds a RISC-V mov<mode>cc pattern.  This causes toplev.c to enable
flag_tree_cselim.  This optimization pass creates a complex long double
conditional move via a phi node.
  complex long double cstore_31;
  ...
  <bb 5> [local count: 27903866]:
  cstore_30 = MEM <complex long double> [(void *)_8];

  <bb 6> [local count: 55807731]:
  # cstore_31 = PHI <__complex__ (0.0, 0.0)(4), cstore_30(5)>
  MEM <complex long double> [(void *)_8] = cstore_31;
When we try to convert gimple to rtl, eliminate_phi calls
insert_value_copy_on_edge for the 32-byte long double 0 value.  The constant
then gets forced to memory, and we end up calling emit_block_move with
BLOCK_OP_NO_LIBCALL, which ends up emitting a loop to do the memory to memory
copy.  Then later in commit_one_edge_insertion we split the edge, insert the
code containing the loop, and then trigger an abort because the last
instruction inserted is the loop back branch.

I don't see where the RISC-V port did anything wrong.  The load hoisting code
is checking the movcc optab to see if the target supports the operation, but I
don't see anything obvious like that in the cselim pass.  The only obvious fix
I see in the RISC-V back end is to modify riscv_expand_block_move to emit
inline non-loop code for a 32-byte memory to memory copy, even when optimizing
for size, which I'd rather not do.  Maybe it can be fixed in
commit_one_edge_insertion by allowing conditional branches but not
unconditional branches, but it isn't clear why this is refusing to allow
branches here in the first place.  I will have to look at other targets to see
why they aren't failing.

Reply via email to