RISC-V: Fix AVL propagation ICE for vleff/vlsegff

This patch fixes 400 ICEs in full coverage testing:

internal compiler error: in validate_change_or_fail, at config/riscv/riscv-v.cc:4597

The root cause is each operand is used in vleff/vlsegff twice:

(define_insn "@pred_fault_load<mode>"
  [(set (match_operand:V 0 "register_operand"              "=vd,    vd,    vr,    vr")
	(if_then_else:V
	  (unspec:<VM>
	    [(match_operand:<VM> 1 "vector_mask_operand" "   vm,    vm,   Wc1,   Wc1")
	     (match_operand 4 "vector_length_operand"    "   rK,    rK,    rK,    rK")
	     (match_operand 5 "const_int_operand"        "    i,     i,     i,     i")
	     (match_operand 6 "const_int_operand"        "    i,     i,     i,     i")
	     (match_operand 7 "const_int_operand"        "    i,     i,     i,     i")
	     (reg:SI VL_REGNUM)
	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
	  (unspec:V
	    [(match_operand:V 3 "memory_operand"         "    m,     m,     m,     m")] UNSPEC_VLEFF)
	  (match_operand:V 2 "vector_merge_operand"      "   vu,     0,    vu,     0")))
   (set (reg:SI VL_REGNUM)
	  (unspec:SI
	    [(if_then_else:V
	       (unspec:<VM>
		[(match_dup 1) (match_dup 4) (match_dup 5)
		 (match_dup 6) (match_dup 7)
		 (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
	       (unspec:V [(match_dup 3)] UNSPEC_VLEFF)
	       (match_dup 2))] UNSPEC_MODIFY_VL))]

Then later instruction change in AVL propagation change ICE:

      validate_change_or_fail (rinsn, recog_data.operand_loc[index],
			       get_avl_type_rtx (avl_type::NONVLMAX), false);

which is the operand change according to location. Such operand change in 2 locations instead of 1.

So regenerate pattern for such instructions AVL propagation to fix the ICEs.

gcc/ChangeLog:

	* config/riscv/riscv-avlprop.cc (simplify_replace_avl): New function.
	(simplify_replace_vlmax_avl): Fix bug.
	* config/riscv/t-riscv: Add a new include file.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/vsetvl/avl_prop-2.c: New test.
This commit is contained in:
Juzhe-Zhong 2023-12-07 20:08:02 +08:00 committed by Lehua Ding
parent 570d74119d
commit abded9bf3e
3 changed files with 72 additions and 7 deletions

View file

@ -79,6 +79,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgcleanup.h"
#include "insn-attr.h"
#include "tm-constrs.h"
#include "insn-opinit.h"
using namespace rtl_ssa;
using namespace riscv_vector;
@ -142,6 +143,34 @@ get_insn_vtype_mode (rtx_insn *rinsn)
return GET_MODE (recog_data.operand[mode_idx]);
}
/* Return new pattern for AVL propagation.
Normally, we just replace AVL operand only for most
of the instructions. However, for instructions like
fault load which use AVL TYPE twice in the pattern which
will cause ICE in the later AVL TYPE change so we regenerate
the whole pattern for such instructions. */
static rtx
simplify_replace_avl (rtx_insn *rinsn, rtx new_avl)
{
/* Replace AVL operand. */
extract_insn_cached (rinsn);
rtx avl = recog_data.operand[get_attr_vl_op_idx (rinsn)];
int count = count_regno_occurrences (rinsn, REGNO (avl));
gcc_assert (count == 1);
rtx new_pat = simplify_replace_rtx (PATTERN (rinsn), avl, new_avl);
if (get_attr_type (rinsn) == TYPE_VLDFF
|| get_attr_type (rinsn) == TYPE_VLSEGDFF)
new_pat
= gen_pred_fault_load (recog_data.operand_mode[0], recog_data.operand[0],
recog_data.operand[1], recog_data.operand[2],
recog_data.operand[3], new_avl,
recog_data.operand[5], recog_data.operand[6],
get_avl_type_rtx (avl_type::NONVLMAX));
else
new_pat = simplify_replace_rtx (PATTERN (rinsn), avl, new_avl);
return new_pat;
}
static void
simplify_replace_vlmax_avl (rtx_insn *rinsn, rtx new_avl)
{
@ -152,12 +181,7 @@ simplify_replace_vlmax_avl (rtx_insn *rinsn, rtx new_avl)
fprintf (dump_file, "into: ");
print_rtl_single (dump_file, rinsn);
}
/* Replace AVL operand. */
extract_insn_cached (rinsn);
rtx avl = recog_data.operand[get_attr_vl_op_idx (rinsn)];
int count = count_regno_occurrences (rinsn, REGNO (avl));
gcc_assert (count == 1);
rtx new_pat = simplify_replace_rtx (PATTERN (rinsn), avl, new_avl);
rtx new_pat = simplify_replace_avl (rinsn, new_avl);
validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false);
/* Change AVL TYPE into NONVLMAX if it is VLMAX. */

View file

@ -81,7 +81,7 @@ riscv-vector-costs.o: $(srcdir)/config/riscv/riscv-vector-costs.cc \
riscv-avlprop.o: $(srcdir)/config/riscv/riscv-avlprop.cc \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
$(TARGET_H) tree-pass.h df.h rtl-ssa.h cfgcleanup.h insn-attr.h \
tm-constrs.h
tm-constrs.h insn-opinit.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/riscv/riscv-avlprop.cc

View file

@ -0,0 +1,41 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gc_zve32f -mabi=lp64d -O3 --param=riscv-autovec-preference=fixed-vlmax" } */
int d0, sj, v0, rp, zi;
void
zn(void)
{
if (v0 != 0)
{
int *js, *r3;
int pm, gc;
for (gc = 0; gc < 1; ++gc)
{
sj = 1;
while (sj != 0)
;
}
r3 = &pm;
*js = (long)&gc;
ka:
for (d0 = 0; d0 < 2; ++d0)
{
d0 = zi;
if (zi)
for (pm = 2; pm != 0; --pm)
;
}
while (*r3 != 0)
{
while (pm)
;
++r3;
}
}
rp = 0;
goto ka;
}
/* { dg-final { scan-assembler-times {vsetivli\tzero,\s*1} 2 } } */