diff options
Diffstat (limited to 'gcc/config/riscv')
| -rw-r--r-- | gcc/config/riscv/autovec.md | 31 | ||||
| -rw-r--r-- | gcc/config/riscv/predicates.md | 2 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv-c.cc | 44 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv-protos.h | 4 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv-target-attr.cc | 96 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv-v.cc | 50 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv.cc | 47 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv.opt | 4 | ||||
| -rw-r--r-- | gcc/config/riscv/riscv.opt.urls | 2 | ||||
| -rw-r--r-- | gcc/config/riscv/vector.md | 8 |
10 files changed, 262 insertions, 26 deletions
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index cec0113..c694684 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -2302,6 +2302,37 @@ }) ;; ------------------------------------------------------------------------- +;; ---- [INT] Mask reductions +;; ------------------------------------------------------------------------- + +(define_expand "reduc_sbool_and_scal_<mode>" + [(match_operand:QI 0 "register_operand") + (match_operand:VB_VLS 1 "register_operand")] + "TARGET_VECTOR" +{ + riscv_vector::expand_mask_reduction (operands, AND); + DONE; +}) + +(define_expand "reduc_sbool_ior_scal_<mode>" + [(match_operand:QI 0 "register_operand") + (match_operand:VB_VLS 1 "register_operand")] + "TARGET_VECTOR" +{ + riscv_vector::expand_mask_reduction (operands, IOR); + DONE; +}) + +(define_expand "reduc_sbool_xor_scal_<mode>" + [(match_operand:QI 0 "register_operand") + (match_operand:VB_VLS 1 "register_operand")] + "TARGET_VECTOR" +{ + riscv_vector::expand_mask_reduction (operands, XOR); + DONE; +}) + +;; ------------------------------------------------------------------------- ;; ---- [FP] Tree reductions ;; ------------------------------------------------------------------------- ;; Includes: diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 3cc954e..5b44165 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -612,7 +612,7 @@ (match_code "eq,ne,le,leu,gt,gtu,lt,ltu")) (define_predicate "comparison_swappable_operator" - (match_code "gtu")) + (match_code "gtu,gt")) (define_predicate "ge_operator" (match_code "ge,geu")) diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc index 4fc0528..24537d5 100644 --- a/gcc/config/riscv/riscv-c.cc +++ b/gcc/config/riscv/riscv-c.cc @@ -213,6 +213,49 @@ riscv_pragma_intrinsic (cpp_reader *) error ("unknown %<#pragma riscv intrinsic%> option %qs", name); } +/* Implement TARGETM.TARGET_OPTION.PRAGMA_PARSE. */ + +static bool +riscv_pragma_target_parse (tree args, tree pop_target) +{ + /* If args is not NULL then process it and setup the target-specific + information that it specifies. */ + if (args) + { + if (!riscv_process_target_attr_for_pragma (args)) + return false; + + riscv_override_options_internal (&global_options); + } + /* args is NULL, restore to the state described in pop_target. */ + else + { + pop_target = pop_target ? pop_target : target_option_default_node; + cl_target_option_restore (&global_options, &global_options_set, + TREE_TARGET_OPTION (pop_target)); + } + + target_option_current_node + = build_target_option_node (&global_options, &global_options_set); + + riscv_reset_previous_fndecl (); + + /* For the definitions, ensure all newly defined macros are considered + as used for -Wunused-macros. There is no point warning about the + compiler predefined macros. */ + cpp_options *cpp_opts = cpp_get_options (parse_in); + unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros; + cpp_opts->warn_unused_macros = 0; + + cpp_force_token_locations (parse_in, BUILTINS_LOCATION); + riscv_cpu_cpp_builtins (parse_in); + cpp_stop_forcing_token_locations (parse_in); + + cpp_opts->warn_unused_macros = saved_warn_unused_macros; + + return true; +} + /* Implement TARGET_CHECK_BUILTIN_CALL. */ static bool riscv_check_builtin_call (location_t loc, vec<location_t> arg_loc, tree fndecl, @@ -272,5 +315,6 @@ riscv_register_pragmas (void) { targetm.resolve_overloaded_builtin = riscv_resolve_overloaded_builtin; targetm.check_builtin_call = riscv_check_builtin_call; + targetm.target_option.pragma_parse = riscv_pragma_target_parse; c_register_pragma ("riscv", "intrinsic", riscv_pragma_intrinsic); } diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 261c25c..abf9df7 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -664,6 +664,7 @@ bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool); void expand_cond_len_unop (unsigned, rtx *); void expand_cond_len_binop (unsigned, rtx *); void expand_reduction (unsigned, unsigned, unsigned, rtx *, rtx); +void expand_mask_reduction (rtx *, rtx_code); void expand_vec_ceil (rtx, rtx, machine_mode, machine_mode); void expand_vec_floor (rtx, rtx, machine_mode, machine_mode); void expand_vec_nearbyint (rtx, rtx, machine_mode, machine_mode); @@ -848,12 +849,15 @@ riscv_option_valid_attribute_p (tree, tree, tree, int); extern bool riscv_option_valid_version_attribute_p (tree, tree, tree, int); extern bool +riscv_process_target_attr_for_pragma (tree); +extern bool riscv_process_target_version_attr (tree, location_t *); extern bool riscv_process_target_version_str (string_slice, location_t *); extern void riscv_override_options_internal (struct gcc_options *); extern void riscv_option_override (void); +extern void riscv_reset_previous_fndecl (void); extern rtx riscv_prefetch_cookie (rtx, rtx); extern bool riscv_prefetch_offset_address_p (rtx, machine_mode); diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc index 94f0a29..eb3e688 100644 --- a/gcc/config/riscv/riscv-target-attr.cc +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -44,6 +44,7 @@ public: , m_cpu_info (nullptr) , m_tune (nullptr) , m_priority (0) + , m_max_vect (false) { } @@ -51,6 +52,7 @@ public: bool handle_cpu (const char *); bool handle_tune (const char *); bool handle_priority (const char *); + bool handle_max_vect (const char *); void update_settings (struct gcc_options *opts) const; private: @@ -66,31 +68,35 @@ private: const riscv_cpu_info *m_cpu_info; const char *m_tune; int m_priority; + bool m_max_vect; }; } /* All the information needed to handle a target attribute. NAME is the name of the attribute. - HANDLER is the function that takes the attribute string as an argument. */ + HANDLER is the function that takes the attribute string as an argument. + REQUIRES_ARG indicates whether this attribute requires an argument value. */ struct riscv_attribute_info { const char *name; bool (riscv_target_attr_parser::*handler) (const char *); + bool requires_arg; }; /* The target attributes that we support. */ static const struct riscv_attribute_info riscv_target_attrs[] - = {{"arch", &riscv_target_attr_parser::handle_arch}, - {"cpu", &riscv_target_attr_parser::handle_cpu}, - {"tune", &riscv_target_attr_parser::handle_tune}, - {NULL, NULL}}; + = {{"arch", &riscv_target_attr_parser::handle_arch, true}, + {"cpu", &riscv_target_attr_parser::handle_cpu, true}, + {"tune", &riscv_target_attr_parser::handle_tune, true}, + {"max-vectorization", &riscv_target_attr_parser::handle_max_vect, false}, + {NULL, NULL, false}}; static const struct riscv_attribute_info riscv_target_version_attrs[] - = {{"arch", &riscv_target_attr_parser::handle_arch}, - {"priority", &riscv_target_attr_parser::handle_priority}, - {NULL, NULL}}; + = {{"arch", &riscv_target_attr_parser::handle_arch, true}, + {"priority", &riscv_target_attr_parser::handle_priority, true}, + {NULL, NULL, false}}; bool riscv_target_attr_parser::parse_arch (const char *str) @@ -254,6 +260,17 @@ riscv_target_attr_parser::handle_priority (const char *str) return true; } +/* Handle max-vectorization. There are no further options, just + enable it. */ + +bool +riscv_target_attr_parser::handle_max_vect (const char *str ATTRIBUTE_UNUSED) +{ + m_max_vect = true; + + return true; +} + void riscv_target_attr_parser::update_settings (struct gcc_options *opts) const { @@ -279,6 +296,9 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const if (m_priority) opts->x_riscv_fmv_priority = m_priority; + + if (m_max_vect) + opts->x_riscv_max_vectorization = true; } /* Parse ARG_STR which contains the definition of one target attribute. @@ -303,33 +323,50 @@ riscv_process_one_target_attr (char *arg_str, char *str_to_check = buf.get(); strcpy (str_to_check, arg_str); + /* Split attribute name from argument (if present). */ char *arg = strchr (str_to_check, '='); - - if (!arg) + if (arg) { - if (loc) - error_at (*loc, "attribute %<target(\"%s\")%> does not " - "accept an argument", str_to_check); - return false; + *arg = '\0'; + ++arg; + /* Check for empty argument after '='. */ + if (*arg == '\0') + { + if (loc) + error_at (*loc, "attribute %<target(\"%s\")%> has empty argument", + str_to_check); + return false; + } } - arg[0] = '\0'; - ++arg; - for (const auto *attr = attrs; - attr->name; - ++attr) + /* Find matching attribute. */ + for (const auto *attr = attrs; attr->name; ++attr) { - /* If the names don't match up, or the user has given an argument - to an attribute that doesn't accept one, or didn't give an argument - to an attribute that expects one, fail to match. */ - if (strncmp (str_to_check, attr->name, strlen (attr->name)) != 0) + if (strcmp (str_to_check, attr->name) != 0) continue; + /* Validate argument presence matches expectations. */ + if (attr->requires_arg && !arg) + { + if (loc) + error_at (*loc, "attribute %<target(\"%s\")%> expects " + "an argument", str_to_check); + return false; + } + + if (!attr->requires_arg && arg) + { + if (loc) + error_at (*loc, "attribute %<target(\"%s\")%> does not " + "accept an argument", str_to_check); + return false; + } + return (&attr_parser->*attr->handler) (arg); } if (loc) - error_at (*loc, "Got unknown attribute %<target(\"%s\")%>", str_to_check); + error_at (*loc, "unknown attribute %<target(\"%s\")%>", str_to_check); return false; } @@ -489,6 +526,17 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int) return ret; } +/* Public wrapper for pragma processing. + Parse ARGS (a TREE_LIST of target attributes) and update global_options. + This is used by #pragma GCC target. */ + +bool +riscv_process_target_attr_for_pragma (tree args) +{ + location_t loc = UNKNOWN_LOCATION; + return riscv_process_target_attr (args, &loc, riscv_target_attrs); +} + /* Parse the tree in ARGS that contains the target_version attribute information and update the global target options space. If LOC is nonnull, report diagnostics against *LOC, otherwise remain silent. */ diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index c0f0b99..f3c4431 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -4885,6 +4885,54 @@ expand_reduction (unsigned unspec, unsigned unspec_for_vl0_safe, emit_insn (gen_pred_extract_first (m1_mode, scalar_dest, m1_tmp2)); } +/* Expand mask reductions. OPS are {dest, src} where DEST's mode + is QImode and SRC's mode is a mask mode. + CODE is one of AND, IOR, XOR. */ + +void +expand_mask_reduction (rtx *ops, rtx_code code) +{ + machine_mode mode = GET_MODE (ops[1]); + rtx dest = ops[0]; + gcc_assert (GET_MODE (dest) == QImode); + + rtx tmp = gen_reg_rtx (Xmode); + rtx cpop_ops[] = {tmp, ops[1]}; + emit_vlmax_insn (code_for_pred_popcount (mode, Xmode), CPOP_OP, cpop_ops); + + bool eq_zero = false; + + /* AND reduction is popcount (mask) == len, + IOR reduction is popcount (mask) != 0, + XOR reduction is popcount (mask) & 1 != 0. */ + if (code == AND) + { + rtx len = gen_int_mode (GET_MODE_NUNITS (mode), HImode); + tmp = expand_binop (Xmode, sub_optab, tmp, len, NULL, true, + OPTAB_DIRECT); + eq_zero = true; + } + else if (code == IOR) + ; + else if (code == XOR) + tmp = expand_binop (Xmode, and_optab, tmp, GEN_INT (1), NULL, true, + OPTAB_DIRECT); + else + gcc_unreachable (); + + rtx els = gen_label_rtx (); + rtx end = gen_label_rtx (); + + riscv_expand_conditional_branch (els, eq_zero ? EQ : NE, tmp, const0_rtx); + emit_move_insn (dest, const0_rtx); + emit_jump_insn (gen_jump (end)); + emit_barrier (); + + emit_label (els); + emit_move_insn (dest, const1_rtx); + emit_label (end); +} + /* Prepare ops for ternary operations. It can be called before or after RA. */ void @@ -5869,6 +5917,8 @@ get_swapped_cmp_rtx_code (rtx_code code) { case GTU: return LTU; + case GT: + return LT; default: gcc_unreachable (); } diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 7b6a29d..96519c9 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -12225,6 +12225,12 @@ riscv_override_options_internal (struct gcc_options *opts) /* Convert -march and -mrvv-vector-bits to a chunks count. */ riscv_vector_chunks = riscv_convert_vector_chunks (opts); + /* Set scalar costing to a high value such that we always pick + vectorization. Increase scalar costing by 100x. */ + if (opts->x_riscv_max_vectorization) + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + param_vect_scalar_cost_multiplier, 10000); + if (opts->x_flag_cf_protection != CF_NONE) { if ((opts->x_flag_cf_protection & CF_RETURN) == CF_RETURN @@ -12462,6 +12468,39 @@ riscv_option_restore (struct gcc_options *opts, static GTY (()) tree riscv_previous_fndecl; +/* Reset the previous function declaration. */ + +void +riscv_reset_previous_fndecl (void) +{ + riscv_previous_fndecl = NULL; +} + +/* Implement TARGET_OPTION_SAVE. */ + +static void +riscv_option_save (struct cl_target_option *ptr, + struct gcc_options *opts, + struct gcc_options * /* opts_set */) +{ + ptr->x_riscv_arch_string = opts->x_riscv_arch_string; + ptr->x_riscv_tune_string = opts->x_riscv_tune_string; + ptr->x_riscv_cpu_string = opts->x_riscv_cpu_string; +} + +/* Implement TARGET_OPTION_PRINT. */ + +static void +riscv_option_print (FILE *file, int indent, struct cl_target_option *ptr) +{ + fprintf (file, "%*sarch = %s\n", indent, "", + ptr->x_riscv_arch_string ? ptr->x_riscv_arch_string : "default"); + fprintf (file, "%*stune = %s\n", indent, "", + ptr->x_riscv_tune_string ? ptr->x_riscv_tune_string : "default"); + if (ptr->x_riscv_cpu_string) + fprintf (file, "%*scpu = %s\n", indent, "", ptr->x_riscv_cpu_string); +} + /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ static void @@ -12798,7 +12837,7 @@ riscv_get_interrupt_type (tree decl) /* Implement `TARGET_SET_CURRENT_FUNCTION'. Unpack the codegen decisions like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET of the function, if such exists. This function may be called multiple - times on a single function so use aarch64_previous_fndecl to avoid + times on a single function so use riscv_previous_fndecl to avoid setting up identical state. */ /* Sanity checking for above function attributes. */ @@ -16309,9 +16348,15 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode) #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE riscv_option_override +#undef TARGET_OPTION_SAVE +#define TARGET_OPTION_SAVE riscv_option_save + #undef TARGET_OPTION_RESTORE #define TARGET_OPTION_RESTORE riscv_option_restore +#undef TARGET_OPTION_PRINT +#define TARGET_OPTION_PRINT riscv_option_print + #undef TARGET_OPTION_VALID_ATTRIBUTE_P #define TARGET_OPTION_VALID_ATTRIBUTE_P riscv_option_valid_attribute_p diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index b334e6c..452062c 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -341,6 +341,10 @@ Target Undocumented RejectNegative Joined Enum(vsetvl_strategy) Var(vsetvl_strat Target Undocumented Uinteger Var(riscv_two_source_permutes) Init(0) -param=riscv-two-source-permutes Enable permutes with two source vectors. +mmax-vectorization +Target Var(riscv_max_vectorization) Save +Override the scalar cost model such that vectorization is always profitable. + Enum Name(stringop_strategy) Type(enum stringop_strategy_enum) Valid arguments to -mstringop-strategy=: diff --git a/gcc/config/riscv/riscv.opt.urls b/gcc/config/riscv/riscv.opt.urls index fe88ec8..bfb1a2d 100644 --- a/gcc/config/riscv/riscv.opt.urls +++ b/gcc/config/riscv/riscv.opt.urls @@ -96,6 +96,8 @@ UrlSuffix(gcc/RISC-V-Options.html#index-minline-strncmp) minline-strlen UrlSuffix(gcc/RISC-V-Options.html#index-minline-strlen) +; skipping UrlSuffix for 'mmax-vectorization' due to finding no URLs + ; skipping UrlSuffix for 'mtls-dialect=' due to finding no URLs mfence-tso diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index c4f60bf..ba4a43b 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -4199,6 +4199,7 @@ "TARGET_VECTOR" "vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1" [(set_attr "type" "vi<widen_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<V_DOUBLE_TRUNC>")]) (define_insn "@pred_single_widen_add<any_extend:su><mode>_extended_scalar" @@ -4465,6 +4466,7 @@ "TARGET_VECTOR" "v<insn>.vx\t%0,%3,%4%p1" [(set_attr "type" "<int_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_insn "@pred_<optab><mode>_scalar" @@ -4486,6 +4488,7 @@ "TARGET_VECTOR" "v<insn>.vx\t%0,%3,%4%p1" [(set_attr "type" "<int_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_expand "@pred_<optab><mode>_scalar" @@ -4540,6 +4543,7 @@ "TARGET_VECTOR" "v<insn>.vx\t%0,%3,%4%p1" [(set_attr "type" "<int_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_insn "*pred_<optab><mode>_extended_scalar" @@ -4562,6 +4566,7 @@ "TARGET_VECTOR && !TARGET_64BIT" "v<insn>.vx\t%0,%3,%4%p1" [(set_attr "type" "<int_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_expand "@pred_<optab><mode>_scalar" @@ -4616,6 +4621,7 @@ "TARGET_VECTOR" "v<insn>.vx\t%0,%3,%z4%p1" [(set_attr "type" "<int_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_insn "*pred_<optab><mode>_extended_scalar" @@ -4638,6 +4644,7 @@ "TARGET_VECTOR && !TARGET_64BIT" "v<insn>.vx\t%0,%3,%z4%p1" [(set_attr "type" "<int_binop_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_insn "@pred_<sat_op><mode>" @@ -4683,6 +4690,7 @@ "TARGET_VECTOR" "v<sat_op>.vx\t%0,%3,%z4%p1" [(set_attr "type" "<sat_insn_type>") + (set_attr "mode_idx" "3") (set_attr "mode" "<MODE>")]) (define_insn "@pred_<sat_op><mode>_scalar" |
