diff options
Diffstat (limited to 'gcc/config/riscv/riscv-v.cc')
-rw-r--r-- | gcc/config/riscv/riscv-v.cc | 104 |
1 files changed, 100 insertions, 4 deletions
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 66c8b29..ce1633c 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -1598,7 +1598,7 @@ expand_const_vector_interleaved_stepped_npatterns (rtx target, rtx src, shifted_vid = gen_reg_rtx (mode); rtx shift = gen_int_mode (1, Xmode); rtx shift_ops[] = {shifted_vid, vid, shift}; - emit_vlmax_insn (code_for_pred_scalar (ASHIFT, mode), BINARY_OP, + emit_vlmax_insn (code_for_pred_scalar (LSHIFTRT, mode), BINARY_OP, shift_ops); } else @@ -2821,6 +2821,28 @@ autovectorize_vector_modes (vector_modes *modes, bool) i++; size = base_size / (1U << i); } + + /* If the user specified the exact mode to use look if it is available and + remove all other ones before returning. */ + if (riscv_autovec_mode) + { + auto_vector_modes ms; + ms.safe_splice (*modes); + modes->truncate (0); + + for (machine_mode mode : ms) + { + if (!strcmp (GET_MODE_NAME (mode), riscv_autovec_mode)) + { + modes->safe_push (mode); + return 0; + } + } + + /* Nothing found, fall back to regular handling. */ + modes->safe_splice (ms); + } + /* Enable LOOP_VINFO comparison in COST model. */ return VECT_COMPARE_COSTS; } @@ -4701,7 +4723,7 @@ prepare_ternary_operands (rtx *ops) ops[4], ops[1], ops[6], ops[7], ops[9])); ops[5] = ops[4] = ops[0]; } - else + else if (VECTOR_MODE_P (GET_MODE (ops[2]))) { /* Swap the multiplication ops if the fallback value is the second of the two. */ @@ -4711,8 +4733,10 @@ prepare_ternary_operands (rtx *ops) /* TODO: ??? Maybe we could support splitting FMA (a, 4, b) into PLUS (ASHIFT (a, 2), b) according to uarchs. */ } - gcc_assert (rtx_equal_p (ops[5], RVV_VUNDEF (mode)) - || rtx_equal_p (ops[5], ops[2]) || rtx_equal_p (ops[5], ops[4])); + gcc_assert ( + rtx_equal_p (ops[5], RVV_VUNDEF (mode)) || rtx_equal_p (ops[5], ops[2]) + || (!VECTOR_MODE_P (GET_MODE (ops[2])) && rtx_equal_p (ops[5], ops[3])) + || rtx_equal_p (ops[5], ops[4])); } /* Expand VEC_MASK_LEN_{LOAD_LANES,STORE_LANES}. */ @@ -5498,6 +5522,78 @@ expand_vec_oct_sstrunc (rtx op_0, rtx op_1, machine_mode vec_mode, expand_vec_double_sstrunc (op_0, quad_rtx, quad_mode); } +/* Expand the binary vx combine with the format like v2 = vop(vec_dup(x), v1). + Aka the first op comes from the vec_duplicate, and the second op is + the vector reg. */ + +void +expand_vx_binary_vec_dup_vec (rtx op_0, rtx op_1, rtx op_2, + rtx_code code, machine_mode mode) +{ + enum insn_code icode; + + switch (code) + { + case PLUS: + case AND: + case IOR: + case XOR: + case MULT: + case SMAX: + case UMAX: + case SMIN: + case UMIN: + case US_PLUS: + icode = code_for_pred_scalar (code, mode); + break; + case MINUS: + icode = code_for_pred_sub_reverse_scalar (mode); + break; + default: + gcc_unreachable (); + } + + rtx ops[] = {op_0, op_1, op_2}; + emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops); +} + +/* Expand the binary vx combine with the format like v2 = vop(v1, vec_dup(x)). + Aka the second op comes from the vec_duplicate, and the first op is + the vector reg. */ + +void +expand_vx_binary_vec_vec_dup (rtx op_0, rtx op_1, rtx op_2, + rtx_code code, machine_mode mode) +{ + enum insn_code icode; + + switch (code) + { + case MINUS: + case AND: + case IOR: + case XOR: + case MULT: + case DIV: + case UDIV: + case MOD: + case UMOD: + case SMAX: + case UMAX: + case SMIN: + case UMIN: + case US_PLUS: + case US_MINUS: + icode = code_for_pred_scalar (code, mode); + break; + default: + gcc_unreachable (); + } + + rtx ops[] = {op_0, op_1, op_2}; + emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops); +} + /* Vectorize popcount by the Wilkes-Wheeler-Gill algorithm that libgcc uses as well. */ void |