Skip to content
Snippets Groups Projects
Commit 40ad10f7 authored by Kito Cheng's avatar Kito Cheng
Browse files

RISC-V: Fix code gen for reduction with length 0 [PR118182]

`.MASK_LEN_FOLD_LEFT_PLUS`(or `mask_len_fold_left_plus_m`) is expecting the
return value will be the start value even if the length is 0.

However current code gen in RISC-V backend is not meet that semantic, it will
result a random garbage value if length is 0.

Let example by current code gen for MASK_LEN_FOLD_LEFT_PLUS with f64:
        # _148 = .MASK_LEN_FOLD_LEFT_PLUS (stmp__148.33_134, vect__70.32_138, { -1, ... }, loop_len_161, 0);
        vsetvli zero,a5,e64,m1,ta,ma
        vfmv.s.f        v2,fa5     # insn 1
        vfredosum.vs    v1,v1,v2   # insn 2
        vfmv.f.s        fa5,v1     # insn 3

insn 1:
- vfmv.s.f won't do anything if VL=0, which means v2 will contain garbage value.
insn 2:
- vfredosum.vs won't do anything if VL=0, and keep vd unchanged even TA.
(v-spec say: `If vl=0, no operation is performed and the destination register
 is not updated.`)
insn 3:
- vfmv.f.s will move the value from v1 even VL=0, so this is safe.

So how we fix that? we need two fix for that:

1. insn 1: need always execute with VL=1, so that we can guarantee it will
           always work as expect.
2. insn 2: Add new pattern to force `vd` use same reg as `vs1` (start value) for
           all reduction patterns, then we can guarantee vd[0] will contain the
           start value when vl=0

For 1, it's just a simple change to riscv_vector::expand_reduction, but for 2,
we have to add _VL0_SAFE variant reduction to force `vd` use same reg as `vs1`
(start value).

Change since V3:
- Rename _AV to _VL0_SAFE for readability.
- Use non-VL0_SAFE version if VL is const or VLMAX.
- Only force VL=1 for vfmv.s.f when VL is non-const and non-VLMAX.
- Two more testcase.

gcc/ChangeLog:

	PR target/118182
	* config/riscv/autovec-opt.md (*widen_reduc_plus_scal_<mode>): Adjust
	argument for expand_reduction.
	(*widen_reduc_plus_scal_<mode>): Ditto.
	(*fold_left_widen_plus_<mode>): Ditto.
	(*mask_len_fold_left_widen_plus_<mode>): Ditto.
	(*cond_widen_reduc_plus_scal_<mode>): Ditto.
	(*cond_len_widen_reduc_plus_scal_<mode>): Ditto.
	(*cond_widen_reduc_plus_scal_<mode>): Ditto.
	* config/riscv/autovec.md (reduc_plus_scal_<mode>): Adjust argument for
	expand_reduction.
	(reduc_smax_scal_<mode>): Ditto.
	(reduc_umax_scal_<mode>): Ditto.
	(reduc_smin_scal_<mode>): Ditto.
	(reduc_umin_scal_<mode>): Ditto.
	(reduc_and_scal_<mode>): Ditto.
	(reduc_ior_scal_<mode>): Ditto.
	(reduc_xor_scal_<mode>): Ditto.
	(reduc_plus_scal_<mode>): Ditto.
	(reduc_smax_scal_<mode>): Ditto.
	(reduc_smin_scal_<mode>): Ditto.
	(reduc_fmax_scal_<mode>): Ditto.
	(reduc_fmin_scal_<mode>): Ditto.
	(fold_left_plus_<mode>): Ditto.
	(mask_len_fold_left_plus_<mode>): Ditto.
	* config/riscv/riscv-v.cc (expand_reduction): Add one more
	argument for reduction code for vl0-safe.
	* config/riscv/riscv-protos.h (expand_reduction): Ditto.
	* config/riscv/vector-iterators.md (unspec): Add _VL0_SAFE variant of
	reduction.
	(ANY_REDUC_VL0_SAFE): New.
	(ANY_WREDUC_VL0_SAFE): Ditto.
	(ANY_FREDUC_VL0_SAFE): Ditto.
	(ANY_FREDUC_SUM_VL0_SAFE): Ditto.
	(ANY_FWREDUC_SUM_VL0_SAFE): Ditto.
	(reduc_op): Add _VL0_SAFE variant of reduction.
	(order) Ditto.
	* config/riscv/vector.md (@pred_<reduc_op><mode>): New.

gcc/testsuite/ChangeLog:

	PR target/118182
	* gfortran.target/riscv/rvv/pr118182.f: New.
	* gcc.target/riscv/rvv/autovec/pr118182-1.c: New.
	* gcc.target/riscv/rvv/autovec/pr118182-2.c: New.
parent 21edcb95
No related branches found
No related tags found
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment