aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/riscv/riscv-v.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/riscv/riscv-v.cc')
-rw-r--r--gcc/config/riscv/riscv-v.cc104
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