2015-09-17 16:28:59 +02:00
|
|
|
/* IR-agnostic target query functions relating to optabs
|
2017-01-01 13:07:43 +01:00
|
|
|
Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
2015-09-17 16:28:59 +02:00
|
|
|
|
|
|
|
This file is part of GCC.
|
|
|
|
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with GCC; see the file COPYING3. If not see
|
|
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#ifndef GCC_OPTABS_QUERY_H
|
|
|
|
#define GCC_OPTABS_QUERY_H
|
|
|
|
|
|
|
|
#include "insn-opinit.h"
|
|
|
|
|
|
|
|
/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
|
|
|
|
if the target does not have such an insn. */
|
|
|
|
|
|
|
|
inline enum insn_code
|
|
|
|
optab_handler (optab op, machine_mode mode)
|
|
|
|
{
|
|
|
|
unsigned scode = (op << 16) | mode;
|
|
|
|
gcc_assert (op > LAST_CONV_OPTAB);
|
|
|
|
return raw_optab_handler (scode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the insn used to perform conversion OP from mode FROM_MODE
|
|
|
|
to mode TO_MODE; return CODE_FOR_nothing if the target does not have
|
|
|
|
such an insn. */
|
|
|
|
|
|
|
|
inline enum insn_code
|
|
|
|
convert_optab_handler (convert_optab op, machine_mode to_mode,
|
|
|
|
machine_mode from_mode)
|
|
|
|
{
|
|
|
|
unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
|
|
|
|
gcc_assert (op > unknown_optab && op <= LAST_CONV_OPTAB);
|
|
|
|
return raw_optab_handler (scode);
|
|
|
|
}
|
|
|
|
|
PR 68432: Add a target hook to control size/speed optab choices
The problem in the PR is that some i386 optabs FAIL when
optimising for size rather than speed. The gimple level generally
needs access to this information before calling the generator,
so this patch adds a new hook to say whether an optab should
be used when optimising for size or speed. It also has a "both"
option for cases where we want code that is optimised for both
size and speed.
I've passed the optab to the target hook because I think in most
cases that's more useful than the instruction code. We could pass
both if there's a use for it though.
At the moment the match-and-simplify code doesn't have direct access
to the target block, so for now I've used "both" there.
Tested on x86_64-linux-gnu and powerpc64-linux-gnu.
gcc/
PR tree-optimization/68432
* coretypes.h (optimization_type): New enum.
* doc/tm.texi.in (TARGET_OPTAB_SUPPORTED_P): New hook.
* doc/tm.texi: Regenerate.
* target.def (optab_supported_p): New hook.
* targhooks.h (default_optab_supported_p): Declare.
* targhooks.c (default_optab_supported_p): New function.
* predict.h (function_optimization_type): Declare.
(bb_optimization_type): Likewise.
* predict.c (function_optimization_type): New function.
(bb_optimization_type): Likewise.
* optabs-query.h (convert_optab_handler): Define an overload
that takes an optimization type.
(direct_optab_handler): Likewise.
* optabs-query.c (convert_optab_handler): Likewise.
(direct_optab_handler): Likewise.
* internal-fn.h (direct_internal_fn_supported_p): Take an
optimization_type argument.
* internal-fn.c (direct_optab_supported_p): Likewise.
(multi_vector_optab_supported_p): Likewise.
(direct_internal_fn_supported_p): Likewise.
* builtins.c (replacement_internal_fn): Update call to
direct_internal_fn_supported_p.
* gimple-match-head.c (build_call_internal): Likewise.
* tree-vect-patterns.c (vect_recog_pow_pattern): Likewise.
* tree-vect-stmts.c (vectorizable_internal_function): Likewise.
* tree.c (maybe_build_call_expr_loc): Likewise.
* config/i386/i386.c (ix86_optab_supported_p): New function.
(TARGET_OPTAB_SUPPORTED_P): Define.
* config/i386/i386.md (asinxf2): Remove optimize_insn_for_size_p check.
(asin<mode>2, acosxf2, acos<mode>2, log1pxf2, log1p<mode>2)
(expNcorexf3, expxf2, exp<mode>2, exp10xf2, exp10<mode>2, exp2xf2)
(exp2<mode>2, expm1xf2, expm1<mode>2, ldexpxf3, ldexp<mode>3)
(scalbxf3, scalb<mode>3, rint<mode>2, round<mode>2)
(<rounding_insn>xf2, <rounding_insn><mode>2): Likewise.
gcc/testsuite/
* gcc.target/i386/pr68432-1.c: New test.
* gcc.target/i386/pr68432-2.c: Likewise.
* gcc.target/i386/pr68432-3.c: Likewise.
From-SVN: r231161
2015-12-02 10:08:49 +01:00
|
|
|
enum insn_code convert_optab_handler (convert_optab, machine_mode,
|
|
|
|
machine_mode, optimization_type);
|
|
|
|
|
2015-09-17 16:28:59 +02:00
|
|
|
/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
|
|
|
|
if the target does not have such an insn. */
|
|
|
|
|
|
|
|
inline enum insn_code
|
|
|
|
direct_optab_handler (direct_optab op, machine_mode mode)
|
|
|
|
{
|
|
|
|
return optab_handler (op, mode);
|
|
|
|
}
|
|
|
|
|
PR 68432: Add a target hook to control size/speed optab choices
The problem in the PR is that some i386 optabs FAIL when
optimising for size rather than speed. The gimple level generally
needs access to this information before calling the generator,
so this patch adds a new hook to say whether an optab should
be used when optimising for size or speed. It also has a "both"
option for cases where we want code that is optimised for both
size and speed.
I've passed the optab to the target hook because I think in most
cases that's more useful than the instruction code. We could pass
both if there's a use for it though.
At the moment the match-and-simplify code doesn't have direct access
to the target block, so for now I've used "both" there.
Tested on x86_64-linux-gnu and powerpc64-linux-gnu.
gcc/
PR tree-optimization/68432
* coretypes.h (optimization_type): New enum.
* doc/tm.texi.in (TARGET_OPTAB_SUPPORTED_P): New hook.
* doc/tm.texi: Regenerate.
* target.def (optab_supported_p): New hook.
* targhooks.h (default_optab_supported_p): Declare.
* targhooks.c (default_optab_supported_p): New function.
* predict.h (function_optimization_type): Declare.
(bb_optimization_type): Likewise.
* predict.c (function_optimization_type): New function.
(bb_optimization_type): Likewise.
* optabs-query.h (convert_optab_handler): Define an overload
that takes an optimization type.
(direct_optab_handler): Likewise.
* optabs-query.c (convert_optab_handler): Likewise.
(direct_optab_handler): Likewise.
* internal-fn.h (direct_internal_fn_supported_p): Take an
optimization_type argument.
* internal-fn.c (direct_optab_supported_p): Likewise.
(multi_vector_optab_supported_p): Likewise.
(direct_internal_fn_supported_p): Likewise.
* builtins.c (replacement_internal_fn): Update call to
direct_internal_fn_supported_p.
* gimple-match-head.c (build_call_internal): Likewise.
* tree-vect-patterns.c (vect_recog_pow_pattern): Likewise.
* tree-vect-stmts.c (vectorizable_internal_function): Likewise.
* tree.c (maybe_build_call_expr_loc): Likewise.
* config/i386/i386.c (ix86_optab_supported_p): New function.
(TARGET_OPTAB_SUPPORTED_P): Define.
* config/i386/i386.md (asinxf2): Remove optimize_insn_for_size_p check.
(asin<mode>2, acosxf2, acos<mode>2, log1pxf2, log1p<mode>2)
(expNcorexf3, expxf2, exp<mode>2, exp10xf2, exp10<mode>2, exp2xf2)
(exp2<mode>2, expm1xf2, expm1<mode>2, ldexpxf3, ldexp<mode>3)
(scalbxf3, scalb<mode>3, rint<mode>2, round<mode>2)
(<rounding_insn>xf2, <rounding_insn><mode>2): Likewise.
gcc/testsuite/
* gcc.target/i386/pr68432-1.c: New test.
* gcc.target/i386/pr68432-2.c: Likewise.
* gcc.target/i386/pr68432-3.c: Likewise.
From-SVN: r231161
2015-12-02 10:08:49 +01:00
|
|
|
enum insn_code direct_optab_handler (convert_optab, machine_mode,
|
|
|
|
optimization_type);
|
|
|
|
|
2015-09-17 16:28:59 +02:00
|
|
|
/* Return true if UNOPTAB is for a trapping-on-overflow operation. */
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
trapv_unoptab_p (optab unoptab)
|
|
|
|
{
|
|
|
|
return (unoptab == negv_optab
|
|
|
|
|| unoptab == absv_optab);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return true if BINOPTAB is for a trapping-on-overflow operation. */
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
trapv_binoptab_p (optab binoptab)
|
|
|
|
{
|
|
|
|
return (binoptab == addv_optab
|
|
|
|
|| binoptab == subv_optab
|
|
|
|
|| binoptab == smulv_optab);
|
|
|
|
}
|
|
|
|
|
2015-11-10 12:57:34 +01:00
|
|
|
/* Return insn code for a comparison operator with VMODE
|
|
|
|
resultin MASK_MODE, unsigned if UNS is true. */
|
|
|
|
|
|
|
|
static inline enum insn_code
|
|
|
|
get_vec_cmp_icode (machine_mode vmode, machine_mode mask_mode, bool uns)
|
|
|
|
{
|
|
|
|
optab tab = uns ? vec_cmpu_optab : vec_cmp_optab;
|
|
|
|
return convert_optab_handler (tab, vmode, mask_mode);
|
|
|
|
}
|
|
|
|
|
re PR target/78102 (GCC refuses to generate PCMPEQQ instruction for SSE4.1)
PR target/78102
* optabs.def (vcondeq_optab, vec_cmpeq_optab): New optabs.
* optabs.c (expand_vec_cond_expr): For comparison codes
EQ_EXPR and NE_EXPR, attempt vcondeq_optab as fallback.
(expand_vec_cmp_expr): For comparison codes
EQ_EXPR and NE_EXPR, attempt vec_cmpeq_optab as fallback.
* optabs-tree.h (expand_vec_cmp_expr_p, expand_vec_cond_expr_p):
Add enum tree_code argument.
* optabs-query.h (get_vec_cmp_eq_icode, get_vcond_eq_icode): New
inline functions.
* optabs-tree.c (expand_vec_cmp_expr_p): Add CODE argument. For
CODE EQ_EXPR or NE_EXPR, attempt to use vec_cmpeq_optab as
fallback.
(expand_vec_cond_expr_p): Add CODE argument. For CODE EQ_EXPR or
NE_EXPR, attempt to use vcondeq_optab as fallback.
* tree-vect-generic.c (expand_vector_comparison,
expand_vector_divmod, expand_vector_condition): Adjust
expand_vec_cmp_expr_p and expand_vec_cond_expr_p callers.
* tree-vect-stmts.c (vectorizable_condition,
vectorizable_comparison): Likewise.
* tree-vect-patterns.c (vect_recog_mixed_size_cond_pattern,
check_bool_pattern, search_type_for_mask_1): Likewise.
* expr.c (do_store_flag): Likewise.
* doc/md.texi (@code{vec_cmpeq@var{m}@var{n}},
@code{vcondeq@var{m}@var{n}}): Document.
* config/i386/sse.md (vec_cmpeqv2div2di, vcondeq<VI8F_128:mode>v2di):
New expanders.
testsuite/
* gcc.target/i386/pr78102.c: New test.
From-SVN: r241525
2016-10-25 18:26:12 +02:00
|
|
|
/* Return insn code for a comparison operator with VMODE
|
|
|
|
resultin MASK_MODE (only for EQ/NE). */
|
|
|
|
|
|
|
|
static inline enum insn_code
|
|
|
|
get_vec_cmp_eq_icode (machine_mode vmode, machine_mode mask_mode)
|
|
|
|
{
|
|
|
|
return convert_optab_handler (vec_cmpeq_optab, vmode, mask_mode);
|
|
|
|
}
|
|
|
|
|
2015-09-17 16:28:59 +02:00
|
|
|
/* Return insn code for a conditional operator with a comparison in
|
|
|
|
mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
|
|
|
|
|
|
|
|
inline enum insn_code
|
|
|
|
get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
|
|
|
|
{
|
|
|
|
enum insn_code icode = CODE_FOR_nothing;
|
|
|
|
if (uns)
|
|
|
|
icode = convert_optab_handler (vcondu_optab, vmode, cmode);
|
|
|
|
else
|
|
|
|
icode = convert_optab_handler (vcond_optab, vmode, cmode);
|
|
|
|
return icode;
|
|
|
|
}
|
|
|
|
|
2015-11-10 13:14:19 +01:00
|
|
|
/* Return insn code for a conditional operator with a mask mode
|
|
|
|
MMODE resulting in a value of mode VMODE. */
|
|
|
|
|
|
|
|
static inline enum insn_code
|
|
|
|
get_vcond_mask_icode (machine_mode vmode, machine_mode mmode)
|
|
|
|
{
|
|
|
|
return convert_optab_handler (vcond_mask_optab, vmode, mmode);
|
|
|
|
}
|
|
|
|
|
re PR target/78102 (GCC refuses to generate PCMPEQQ instruction for SSE4.1)
PR target/78102
* optabs.def (vcondeq_optab, vec_cmpeq_optab): New optabs.
* optabs.c (expand_vec_cond_expr): For comparison codes
EQ_EXPR and NE_EXPR, attempt vcondeq_optab as fallback.
(expand_vec_cmp_expr): For comparison codes
EQ_EXPR and NE_EXPR, attempt vec_cmpeq_optab as fallback.
* optabs-tree.h (expand_vec_cmp_expr_p, expand_vec_cond_expr_p):
Add enum tree_code argument.
* optabs-query.h (get_vec_cmp_eq_icode, get_vcond_eq_icode): New
inline functions.
* optabs-tree.c (expand_vec_cmp_expr_p): Add CODE argument. For
CODE EQ_EXPR or NE_EXPR, attempt to use vec_cmpeq_optab as
fallback.
(expand_vec_cond_expr_p): Add CODE argument. For CODE EQ_EXPR or
NE_EXPR, attempt to use vcondeq_optab as fallback.
* tree-vect-generic.c (expand_vector_comparison,
expand_vector_divmod, expand_vector_condition): Adjust
expand_vec_cmp_expr_p and expand_vec_cond_expr_p callers.
* tree-vect-stmts.c (vectorizable_condition,
vectorizable_comparison): Likewise.
* tree-vect-patterns.c (vect_recog_mixed_size_cond_pattern,
check_bool_pattern, search_type_for_mask_1): Likewise.
* expr.c (do_store_flag): Likewise.
* doc/md.texi (@code{vec_cmpeq@var{m}@var{n}},
@code{vcondeq@var{m}@var{n}}): Document.
* config/i386/sse.md (vec_cmpeqv2div2di, vcondeq<VI8F_128:mode>v2di):
New expanders.
testsuite/
* gcc.target/i386/pr78102.c: New test.
From-SVN: r241525
2016-10-25 18:26:12 +02:00
|
|
|
/* Return insn code for a conditional operator with a comparison in
|
|
|
|
mode CMODE (only EQ/NE), resulting in a value of mode VMODE. */
|
|
|
|
|
|
|
|
static inline enum insn_code
|
|
|
|
get_vcond_eq_icode (machine_mode vmode, machine_mode cmode)
|
|
|
|
{
|
|
|
|
return convert_optab_handler (vcondeq_optab, vmode, cmode);
|
|
|
|
}
|
|
|
|
|
2015-09-17 16:28:59 +02:00
|
|
|
/* Enumerates the possible extraction_insn operations. */
|
|
|
|
enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
|
|
|
|
|
|
|
|
/* Describes an instruction that inserts or extracts a bitfield. */
|
|
|
|
struct extraction_insn
|
|
|
|
{
|
|
|
|
/* The code of the instruction. */
|
|
|
|
enum insn_code icode;
|
|
|
|
|
|
|
|
/* The mode that the structure operand should have. This is byte_mode
|
|
|
|
when using the legacy insv, extv and extzv patterns to access memory. */
|
|
|
|
machine_mode struct_mode;
|
|
|
|
|
|
|
|
/* The mode of the field to be inserted or extracted, and by extension
|
|
|
|
the mode of the insertion or extraction itself. */
|
|
|
|
machine_mode field_mode;
|
|
|
|
|
|
|
|
/* The mode of the field's bit position. This is only important
|
|
|
|
when the position is variable rather than constant. */
|
|
|
|
machine_mode pos_mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool get_best_reg_extraction_insn (extraction_insn *,
|
|
|
|
enum extraction_pattern,
|
|
|
|
unsigned HOST_WIDE_INT, machine_mode);
|
|
|
|
bool get_best_mem_extraction_insn (extraction_insn *,
|
|
|
|
enum extraction_pattern,
|
|
|
|
HOST_WIDE_INT, HOST_WIDE_INT, machine_mode);
|
|
|
|
|
|
|
|
enum insn_code can_extend_p (machine_mode, machine_mode, int);
|
|
|
|
enum insn_code can_float_p (machine_mode, machine_mode, int);
|
|
|
|
enum insn_code can_fix_p (machine_mode, machine_mode, int, bool *);
|
|
|
|
bool can_conditionally_move_p (machine_mode mode);
|
|
|
|
bool can_vec_perm_p (machine_mode, bool, const unsigned char *);
|
|
|
|
enum insn_code widening_optab_handler (optab, machine_mode, machine_mode);
|
|
|
|
/* Find a widening optab even if it doesn't widen as much as we want. */
|
|
|
|
#define find_widening_optab_handler(A,B,C,D) \
|
|
|
|
find_widening_optab_handler_and_mode (A, B, C, D, NULL)
|
|
|
|
enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode,
|
|
|
|
machine_mode, int,
|
|
|
|
machine_mode *);
|
|
|
|
int can_mult_highpart_p (machine_mode, bool);
|
2015-11-10 13:06:05 +01:00
|
|
|
bool can_vec_mask_load_store_p (machine_mode, machine_mode, bool);
|
2015-09-17 16:28:59 +02:00
|
|
|
bool can_compare_and_swap_p (machine_mode, bool);
|
|
|
|
bool can_atomic_exchange_p (machine_mode, bool);
|
2017-02-01 18:21:59 +01:00
|
|
|
bool can_atomic_load_p (machine_mode);
|
2015-09-17 16:28:59 +02:00
|
|
|
bool lshift_cheap_p (bool);
|
|
|
|
|
|
|
|
#endif
|