GCC Middle and Back End API Reference
|
Go to the source code of this file.
Data Structures | |
struct | optab_libcall_d |
struct | convert_optab_libcall_d |
struct | target_optabs |
struct | extraction_insn |
struct | expand_operand |
Typedefs | |
typedef enum optab_tag | optab |
typedef enum optab_tag | convert_optab |
typedef enum optab_tag | direct_optab |
Enumerations | |
enum | optab_subtype { optab_default, optab_scalar, optab_vector } |
enum | can_compare_purpose { ccp_jump, ccp_cmov, ccp_store_flag } |
enum | extraction_pattern { EP_insv, EP_extv, EP_extzv } |
enum | expand_operand_type { EXPAND_FIXED, EXPAND_OUTPUT, EXPAND_INPUT, EXPAND_CONVERT_TO, EXPAND_CONVERT_FROM, EXPAND_ADDRESS, EXPAND_INTEGER } |
Functions | |
static optab | code_to_optab () |
static enum rtx_code | optab_to_code () |
enum insn_code | raw_optab_handler (unsigned) |
bool | swap_optab_enable (optab, enum machine_mode, bool) |
rtx | expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, rtx target, int unsignedp) |
rtx | expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0, rtx op1, rtx op2, rtx target, int unsignedp) |
rtx | expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int, enum optab_methods) |
rtx | simplify_expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods) |
bool | force_expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int, enum optab_methods) |
rtx | sign_expand_binop (enum machine_mode, optab, optab, rtx, rtx, rtx, int, enum optab_methods) |
int | expand_twoval_unop (optab, rtx, rtx, rtx, int) |
int | expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int) |
bool | expand_twoval_binop_libfunc (optab, rtx, rtx, rtx, rtx, enum rtx_code) |
rtx | expand_unop (enum machine_mode, optab, rtx, rtx, int) |
rtx | expand_abs_nojump (enum machine_mode, rtx, rtx, int) |
rtx | expand_abs (enum machine_mode, rtx, rtx, int, int) |
rtx | expand_one_cmpl_abs_nojump (enum machine_mode, rtx, rtx) |
rtx | expand_copysign (rtx, rtx, rtx) |
void | emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code) |
bool | maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code) |
enum insn_code | find_widening_optab_handler_and_mode (optab, enum machine_mode, enum machine_mode, int, enum machine_mode *) |
optab | optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype) |
int | can_compare_p (enum rtx_code, enum machine_mode, enum can_compare_purpose) |
enum insn_code | can_extend_p (enum machine_mode, enum machine_mode, int) |
rtx | gen_extend_insn (rtx, rtx, enum machine_mode, enum machine_mode, int) |
void | set_optab_libfunc (optab, enum machine_mode, const char *) |
void | set_conv_libfunc (convert_optab, enum machine_mode, enum machine_mode, const char *) |
void | init_sync_libfuncs (int max) |
void | expand_fixed_convert (rtx, rtx, int, int) |
void | expand_float (rtx, rtx, int) |
enum insn_code | can_float_p (enum machine_mode, enum machine_mode, int) |
bool | can_compare_and_swap_p (enum machine_mode, bool) |
bool | can_atomic_exchange_p (enum machine_mode, bool) |
bool | expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool, enum memmodel, enum memmodel) |
void | expand_mem_thread_fence (enum memmodel) |
void | expand_mem_signal_fence (enum memmodel) |
bool | supportable_convert_operation (enum tree_code, tree, tree, tree *, enum tree_code *) |
void | expand_fix (rtx, rtx, int) |
bool | expand_sfix_optab (rtx, rtx, convert_optab) |
rtx | expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab) |
bool | expand_vec_cond_expr_p (tree, tree) |
rtx | expand_vec_cond_expr (tree, tree, tree, tree, rtx) |
rtx | expand_vec_shift_expr (sepops, rtx) |
bool | can_vec_perm_p (enum machine_mode, bool, const unsigned char *) |
rtx | expand_vec_perm (enum machine_mode, rtx, rtx, rtx, rtx) |
int | can_mult_highpart_p (enum machine_mode, bool) |
rtx | expand_mult_highpart (enum machine_mode, rtx, rtx, rtx, bool) |
static enum insn_code | optab_handler () |
static enum insn_code | convert_optab_handler (convert_optab op, enum machine_mode to_mode, enum machine_mode from_mode) |
static enum insn_code | widening_optab_handler (optab op, enum machine_mode to_mode, enum machine_mode from_mode) |
static enum insn_code | direct_optab_handler () |
static bool | trapv_unoptab_p () |
static bool | trapv_binoptab_p () |
rtx | optab_libfunc (optab optab, enum machine_mode mode) |
rtx | convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, enum machine_mode mode2) |
bool | get_best_reg_extraction_insn (extraction_insn *, enum extraction_pattern, unsigned HOST_WIDE_INT, enum machine_mode) |
bool | get_best_mem_extraction_insn (extraction_insn *, enum extraction_pattern, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode) |
bool | insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand) |
static void | create_expand_operand (struct expand_operand *op, enum expand_operand_type type, rtx value, enum machine_mode mode, bool unsigned_p) |
static void | create_fixed_operand () |
static void | create_output_operand (struct expand_operand *op, rtx x, enum machine_mode mode) |
static void | create_input_operand (struct expand_operand *op, rtx value, enum machine_mode mode) |
static void | create_convert_operand_to (struct expand_operand *op, rtx value, enum machine_mode mode, bool unsigned_p) |
static void | create_convert_operand_from (struct expand_operand *op, rtx value, enum machine_mode mode, bool unsigned_p) |
void | create_convert_operand_from_type (struct expand_operand *op, rtx value, tree type) |
static void | create_address_operand () |
static void | create_integer_operand () |
bool | valid_multiword_target_p (rtx) |
bool | maybe_legitimize_operands (enum insn_code icode, unsigned int opno, unsigned int nops, struct expand_operand *ops) |
rtx | maybe_gen_insn (enum insn_code icode, unsigned int nops, struct expand_operand *ops) |
bool | maybe_expand_insn (enum insn_code icode, unsigned int nops, struct expand_operand *ops) |
bool | maybe_expand_jump_insn (enum insn_code icode, unsigned int nops, struct expand_operand *ops) |
void | expand_insn (enum insn_code icode, unsigned int nops, struct expand_operand *ops) |
void | expand_jump_insn (enum insn_code icode, unsigned int nops, struct expand_operand *ops) |
rtx | prepare_operand (enum insn_code, rtx, int, enum machine_mode, enum machine_mode, int) |
void | gen_int_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_fp_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_signed_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_unsigned_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_int_fp_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_intv_fp_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_int_fp_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_int_fp_signed_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_int_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_int_signed_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_int_unsigned_fixed_libfunc (optab, const char *, char, enum machine_mode) |
void | gen_interclass_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_int_to_fp_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_ufloat_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_int_to_fp_nondecimal_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_fp_to_int_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_intraclass_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_trunc_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_extend_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_fract_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_fractuns_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_satfract_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
void | gen_satfractuns_conv_libfunc (convert_optab, const char *, enum machine_mode, enum machine_mode) |
Variables | |
const optab | code_to_optab_ [NUM_RTX_CODE] |
enum rtx_code | optab_to_code_ [NUM_OPTABS] |
struct convert_optab_libcall_d | convlib_def [NUM_CONVLIB_OPTABS] |
struct optab_libcall_d | normlib_def [NUM_NORMLIB_OPTABS] |
struct target_optabs | default_target_optabs |
struct target_optabs * | this_fn_optabs |
struct target_optabs * | this_target_optabs |
typedef enum optab_tag convert_optab |
typedef enum optab_tag direct_optab |
enum can_compare_purpose |
enum expand_operand_type |
enum extraction_pattern |
enum optab_subtype |
bool can_atomic_exchange_p | ( | enum | machine_mode, |
bool | |||
) |
Return true if there is an inline atomic exchange pattern.
bool can_compare_and_swap_p | ( | enum | machine_mode, |
bool | |||
) |
Return true if there is an inline compare and swap pattern.
int can_compare_p | ( | enum rtx_code | code, |
enum machine_mode | mode, | ||
enum can_compare_purpose | purpose | ||
) |
Nonzero if a compare of mode MODE can be done straightforwardly (without splitting it into pieces).
Nonzero if we can perform a comparison of mode MODE straightforwardly. PURPOSE describes how this comparison will be used. CODE is the rtx comparison code we will be using. ??? Actually, CODE is slightly weaker than that. A target is still required to implement all of the normal bcc operations, but not required to implement all (or any) of the unordered bcc operations.
Referenced by emit_cstore().
enum insn_code can_extend_p | ( | enum machine_mode | to_mode, |
enum machine_mode | from_mode, | ||
int | unsignedp | ||
) |
Return the INSN_CODE to use for an extend operation.
Return the insn code used to extend FROM_MODE to TO_MODE. UNSIGNEDP specifies zero-extension instead of sign-extension. If no such operation exists, CODE_FOR_nothing will be returned.
Referenced by can_conditionally_move_p().
enum insn_code can_float_p | ( | enum | machine_mode, |
enum | machine_mode, | ||
int | |||
) |
Return the insn_code for a FLOAT_EXPR.
Referenced by have_add2_insn().
int can_mult_highpart_p | ( | enum | machine_mode, |
bool | |||
) |
Return non-zero if target supports a given highpart multiplication.
bool can_vec_perm_p | ( | enum machine_mode | mode, |
bool | variable, | ||
const unsigned char * | sel | ||
) |
Return tree if target supports vector operations for VEC_PERM_EXPR.
Return true if VEC_PERM_EXPR can be expanded using SIMD extensions of the CPU. SEL may be NULL, which stands for an unknown constant.
If the target doesn't implement a vector mode for the vector type, then no operations are supported.
We allow fallback to a QI vector mode, and adjust the mask.
??? For completeness, we ought to check the QImode version of vec_perm_const_optab. But all users of this implicit lowering feature implement the variable vec_perm_optab.
In order to support the lowering of variable permutations, we need to support shifts and adds.
Referenced by vect_get_mask_element().
|
inlinestatic |
Referenced by expand_fix(), and noce_emit_store_flag().
|
inlinestatic |
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.
rtx convert_optab_libfunc | ( | convert_optab | optab, |
enum machine_mode | mode1, | ||
enum machine_mode | mode2 | ||
) |
Return libfunc corresponding operation defined by OPTAB converting from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL if no libfunc is available.
??? This ought to be an assert, but not all of the places that we expand optabs know about the optabs that got moved to being direct.
References convlib_def, convert_optab_libcall_d::libcall_basename, and convert_optab_libcall_d::libcall_gen.
|
inlinestatic |
Make OP describe an input Pmode address operand. VALUE is the value of the address, but it may need to be converted to Pmode first.
Referenced by expand_builtin_update_setjmp_buf().
|
inlinestatic |
Make OP describe an input operand that should have the same value as VALUE, after any mode conversion that the backend might request. If VALUE is a CONST_INT, it should be treated as having mode MODE. UNSIGNED_P says whether VALUE is unsigned.
Referenced by clear_storage_hints().
void create_convert_operand_from_type | ( | struct expand_operand * | op, |
rtx | value, | ||
tree | type | ||
) |
Make OP describe an input operand that should have the same value as VALUE, after any mode conversion that the target might request. TYPE is the type of VALUE.
|
inlinestatic |
Like create_input_operand, except that VALUE must first be converted to mode MODE. UNSIGNED_P says whether VALUE is unsigned.
Referenced by block_move_libcall_safe_for_call_parm(), and clear_storage_hints().
|
inlinestatic |
Initialize OP with the given fields. Initialise the other fields to their default values.
Referenced by create_fixed_operand().
|
inlinestatic |
Make OP describe an operand that must use rtx X, even if X is volatile.
References create_expand_operand(), and EXPAND_INTEGER.
Referenced by block_move_libcall_safe_for_call_parm(), clear_storage_hints(), and expand_sync_lock_test_and_set().
|
inlinestatic |
Make OP describe an input operand that must have mode MODE and value VALUE; MODE cannot be VOIDmode. The backend may request that VALUE be copied into a different kind of rtx before being passed as an operand.
Referenced by expand_sync_lock_test_and_set(), and push_block().
|
inlinestatic |
Make OP describe an input operand that has value INTVAL and that has no inherent mode. This function should only be used for operands that are always expand-time constants. The backend may request that INTVAL be copied into a different kind of rtx, but it must specify the mode of that rtx if so.
Referenced by block_move_libcall_safe_for_call_parm(), clear_storage_hints(), and expand_builtin_update_setjmp_buf().
|
inlinestatic |
Make OP describe an output operand that must have mode MODE. X, if nonnull, is a suggestion for where the output should be stored. It is OK for VALUE to be inconsistent with MODE, although it will just be ignored in that case.
|
inlinestatic |
Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing if the target does not have such an insn.
Referenced by emit_block_move(), and init_optabs().
Generate an instruction with a given INSN_CODE with an output and an input.
If that does not win, use conditional jump and negate.
It is safe to use the target if it is the same as the source if this is also a pseudo register
References gen_reg_rtx(), int_mode_for_mode(), operand_subword(), operand_subword_force(), double_int::set_bit(), start_sequence(), valid_multiword_target_p(), and word_mode.
Referenced by expand_builtin_va_start().
Expand the absolute value operation.
Emit code to compute the absolute value of OP0, with result to TARGET if convenient. (TARGET may be 0.) The return value says where the result actually is to be found. MODE is the mode of the operand; the mode of the result is different but can be deduced from MODE.
First try to do it with a special abs instruction.
For floating point modes, try clearing the sign bit.
If we have a MAX insn, we can do this as MAX (x, -x).
If this machine has expensive jumps, we can do integer absolute value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)), where W is the width of MODE.
References insn_data.
bool expand_atomic_compare_and_swap | ( | rtx * | ptarget_bool, |
rtx * | ptarget_oval, | ||
rtx | mem, | ||
rtx | expected, | ||
rtx | desired, | ||
bool | is_weak, | ||
enum memmodel | succ_model, | ||
enum memmodel | fail_model | ||
) |
Generate code for a compare and swap.
This function expands the atomic compare exchange operation: *PTARGET_BOOL is an optional place to store the boolean success/failure. *PTARGET_OVAL is an optional place to store the old value from memory. Both target parameters may be NULL to indicate that we do not care about that return value. Both target parameters are updated on success to the actual location of the corresponding result. MEMMODEL is the memory model variant to use. The return value of the function is true for success.
Load expected into a register for the compare and swap.
Make sure we always have some place to put the return oldval. Further, make sure that place is distinct from the input expected, just in case we need that path down below.
Make sure we always have a place for the bool operand.
Emit the compare_and_swap.
Return success/failure.
Otherwise fall back to the original __sync_val_compare_and_swap which is always seq-cst.
If the caller isn't interested in the boolean return value, skip the computation of it.
Otherwise, work out if the compare-and-swap succeeded.
Also check for library support for __sync_val_compare_and_swap.
Compute the boolean return value only if requested.
Failure.
Make sure that the oval output winds up where the caller asked.
References gen_reg_rtx(), and maybe_emit_atomic_exchange().
rtx expand_binop | ( | enum machine_mode | mode, |
optab | binoptab, | ||
rtx | op0, | ||
rtx | op1, | ||
rtx | target, | ||
int | unsignedp, | ||
enum optab_methods | methods | ||
) |
Expand a binary operation given optab and rtx operands.
Generate code to perform an operation specified by BINOPTAB on operands OP0 and OP1, with result having machine-mode MODE. UNSIGNEDP is for the case where we have to widen the operands to perform the operation. It says to use zero-extension. If TARGET is nonzero, the value is generated there, if it is convenient to do so. In all cases an rtx is returned for the locus of the value; this may or may not be TARGET.
If subtracting an integer constant, convert this into an addition of the negated constant.
Record where to delete back to if we backtrack.
If we can do it with a three-operand insn, do so.
If we were trying to rotate, and that didn't work, try rotating the other direction before falling back to shifts and bitwise-or.
If this is a multiply, see if we can do a widening operation that takes operands of this mode and makes a wider mode.
If this is a vector shift by a scalar, see if we can do a vector shift by a vector. If so, broadcast the scalar into a vector.
Look for a wider mode of the same class for which we think we can open-code the operation. Check for a widening multiply at the wider mode as well.
For certain integer operations, we need not actually extend the narrow operands, as long as we will truncate the results to the same narrowness.
The second operand of a shift must always be extended.
If operation is commutative, try to make the first operand a register. Even better, try to make it the same as the target. Also try to make the last operand a constant.
These can be done a word at a time.
If TARGET is the same as one of the operands, the REG_EQUAL note won't be accurate, so use a new target.
Do the actual arithmetic.
Synthesize double word shifts from single word shifts.
Apply the truncation to constant shifts.
Make sure that this is a combination that expand_doubleword_shift can handle. See the comments there for details.
If TARGET is the same as one of the operands, the REG_EQUAL note won't be accurate, so use a new target.
OUTOF_* is the word we are shifting bits away from, and INTO_* is the word that we are shifting bits towards, thus they differ depending on the direction of the shift and WORDS_BIG_ENDIAN.
Synthesize double word rotates from single word shifts.
If TARGET is the same as one of the operands, the REG_EQUAL note won't be accurate, so use a new target. Do this also if target is not a REG, first because having a register instead may open optimization opportunities, and second because if target and op0 happen to be MEMs designating the same location, we would risk clobbering it too early in the code sequence we generate below.
OUTOF_* is the word we are shifting bits away from, and INTO_* is the word that we are shifting bits towards, thus they differ depending on the direction of the shift and WORDS_BIG_ENDIAN.
This is just a word swap.
These can be done a word at a time by propagating carries.
We can handle either a 1 or -1 value for the carry. If STORE_FLAG value is one of those, use it. Otherwise, use 1 since it is the one easiest to get.
Prepare the operands.
Indicate for flow that the entire target reg is being set.
Do the actual arithmetic.
Main add/subtract of the input operands.
Store carry from main add/subtract.
Add/subtract previous carry to main result.
Get out carry from adding/subtracting carry in.
Logical-ior the two poss. carry together.
Attempt to synthesize double word multiplies using a sequence of word mode multiplications. We first attempt to generate a sequence using a more efficient unsigned widening multiply, and if that fails we then try using a signed widening multiply.
It can't be open-coded in this mode. Use a library call if one is available and caller says that's ok.
Specify unsigned here, since negative shift counts are meaningless.
Pass 1 for NO_QUEUE so we don't lose any increments if the libcall is cse'd or moved.
It can't be done in this mode. Can we do it in a wider mode?
Caller says, don't even try.
Compute the value of METHODS to pass to recursive calls. Don't allow widening to be tried recursively.
Look for a wider mode of the same class for which it appears we can do the operation.
For certain integer operations, we need not actually extend the narrow operands, as long as we will truncate the results to the same narrowness.
The second operand of a shift must always be extended.
References convert_to_mode(), expand_binop(), and OPTAB_DIRECT.
Referenced by emit_cstore(), expand_binop(), expand_doubleword_clz(), expand_ffs(), expand_float(), expand_mult(), expand_widening_mult(), extract_high_half(), and push_block().
void expand_insn | ( | enum insn_code | icode, |
unsigned int | nops, | ||
struct expand_operand * | ops | ||
) |
Emit instruction ICODE, using operands [OPS, OPS + NOPS) as its operands.
void expand_jump_insn | ( | enum insn_code | icode, |
unsigned int | nops, | ||
struct expand_operand * | ops | ||
) |
Like expand_insn, but for jumps.
void expand_mem_signal_fence | ( | enum | memmodel | ) |
void expand_mem_thread_fence | ( | enum | memmodel | ) |
Generate memory barriers.
Expand the one's complement absolute value operation.
bool expand_sfix_optab | ( | rtx | , |
rtx | , | ||
convert_optab | |||
) |
Generate code for float to integral conversion.
rtx expand_ternary_op | ( | enum machine_mode | mode, |
optab | ternary_optab, | ||
rtx | op0, | ||
rtx | op1, | ||
rtx | op2, | ||
rtx | target, | ||
int | unsignedp | ||
) |
Generate code to perform an operation specified by TERNARY_OPTAB on operands OP0, OP1 and OP2, with result having machine-mode MODE. UNSIGNEDP is for the case where we have to widen the operands to perform the operation. It says to use zero-extension. If TARGET is nonzero, the value is generated there, if it is convenient to do so. In all cases an rtx is returned for the locus of the value; this may or may not be TARGET.
Generate code to perform an operation on two operands with two results.
Generate code to perform an operation specified by BINOPTAB on operands OP0 and OP1, with two results to TARG1 and TARG2. We assume that the order of the operands for the instruction is TARG0, OP0, OP1, TARG1, which would fit a pattern like [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))]. Either TARG0 or TARG1 may be zero, but what that means is that the result is not actually wanted. We will generate it into a dummy pseudo-reg and discard it. They may not both be zero. Returns 1 if this operation can be performed; 0 if not.
Record where to go back to if we fail.
If we are optimizing, force expensive constants into a register.
It can't be done in this mode. Can we do it in a wider mode?
bool expand_twoval_binop_libfunc | ( | optab | binoptab, |
rtx | op0, | ||
rtx | op1, | ||
rtx | targ0, | ||
rtx | targ1, | ||
enum rtx_code | code | ||
) |
Generate code to perform an operation on two operands with two results, using a library function.
Expand the two-valued library call indicated by BINOPTAB, but preserve only one of the values. If TARG0 is non-NULL, the first value is placed into TARG0; otherwise the second value is placed into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1). This routine assumes that the value returned by the library call is as if the return value was of an integral mode twice as wide as the mode of OP0. Returns 1 if the call was successful.
Exactly one of TARG0 or TARG1 should be non-NULL.
The value returned by the library function will have twice as many bits as the nominal MODE.
Get the part of VAL containing the value that we want.
Move the into the desired location.
Generate code to perform an operation on one operand with two results.
Generate code to perform an operation specified by UNOPPTAB on operand OP0, with two results to TARG0 and TARG1. We assume that the order of the operands for the instruction is TARG0, TARG1, OP0. Either TARG0 or TARG1 may be zero, but what that means is that the result is not actually wanted. We will generate it into a dummy pseudo-reg and discard it. They may not both be zero. Returns 1 if this operation can be performed; 0 if not.
Record where to go back to if we fail.
It can't be done in this mode. Can we do it in a wider mode?
Expand a unary arithmetic operation given optab rtx operand.
Generate code to perform an operation specified by UNOPTAB on operand OP0, with result having machine-mode MODE. UNSIGNEDP is for the case where we have to widen the operands to perform the operation. It says to use zero-extension. If TARGET is nonzero, the value is generated there, if it is convenient to do so. In all cases an rtx is returned for the locus of the value; this may or may not be TARGET.
It can't be done in this mode. Can we open-code it in a wider mode?
Widening (or narrowing) clz needs special treatment.
Widening (or narrowing) bswap needs special treatment.
HImode is special because in this mode BSWAP is equivalent to ROTATE or ROTATERT. First try these directly; if this fails, then try the obvious pair of shifts with allowed widening, as this will probably be always more efficient than the other fallback methods.
For certain operations, we need not actually extend the narrow operand, as long as we will truncate the results to the same narrowness.
These can be done a word at a time.
Do the actual arithmetic.
Try negating floating point values by flipping the sign bit.
If there is no negation pattern, and we have no negative zero, try subtracting from zero.
Try calculating parity (x) as popcount (x) % 2.
Try implementing ffs (x) in terms of clz (x).
Try implementing ctz (x) in terms of clz (x).
Now try a library call in this mode.
All of these functions return small values. Thus we choose to have them return something that isn't a double-word.
Pass 1 for NO_QUEUE so we don't lose any increments if the libcall is cse'd or moved.
It can't be done in this mode. Can we do it in a wider mode?
For certain operations, we need not actually extend the narrow operand, as long as we will truncate the results to the same narrowness.
If we are generating clz using wider mode, adjust the result. Similarly for clrsb.
Likewise for bswap.
One final attempt at implementing negation via subtraction, this time allowing widening of the operand.
Referenced by expand_doubleword_clz(), noce_emit_store_flag(), stabilize_va_list_loc(), and supportable_convert_operation().
Generate code for VEC_COND_EXPR.
Generate insns for a VEC_COND_EXPR, given its TYPE and its three operands.
Fake op0 < 0.
Return tree if target supports vector operations for COND_EXPR.
rtx expand_widen_pattern_expr | ( | sepops | ops, |
rtx | op0, | ||
rtx | op1, | ||
rtx | wide_op, | ||
rtx | target, | ||
int | unsignedp | ||
) |
Define functions given in optabs.c.
Expand vector widening operations. There are two different classes of operations handled here: 1) Operations whose result is wider than all the arguments to the operation. Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR In this case OP0 and optionally OP1 would be initialized, but WIDE_OP wouldn't (not relevant for this case). 2) Operations whose result is of the same size as the last argument to the operation, but wider than all the other arguments to the operation. Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR. In the case WIDE_OP, OP0 and optionally OP1 would be initialized. E.g, when called to expand the following operations, this is how the arguments will be initialized: nops OP0 OP1 WIDE_OP widening-sum 2 oprnd0 - oprnd1 widening-dot-product 3 oprnd0 oprnd1 oprnd2 widening-mult 2 oprnd0 oprnd1 - type-promotion (vec-unpack) 1 oprnd0 - -
The last operand is of a wider mode than the rest of the operands.
rtx expand_widening_mult | ( | enum machine_mode | mode, |
rtx | op0, | ||
rtx | op1, | ||
rtx | target, | ||
int | unsignedp, | ||
optab | this_optab | ||
) |
Generate code for a widening multiply.
Perform a widening multiplication and return an rtx for the result. MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); TARGET is a suggestion for where to store the result (an rtx). THIS_OPTAB is the optab we should use, it must be either umul_widen_optab or smul_widen_optab. We check specially for a constant integer as OP1, comparing the cost of a widening multiply against the cost of a sequence of shifts and adds.
Special case powers of two.
Exclude cost of op0 from max_cost to match the cost calculation of the synth_mult.
References expand_binop(), expand_mult_highpart_adjust(), extract_high_half(), gen_int_mode(), mul_cost(), mul_highpart_cost(), mul_widen_cost(), OPTAB_DIRECT, optab_handler(), OPTAB_WIDEN, optimize_insn_for_speed_p(), shift_cost(), and widening_optab_handler().
enum insn_code find_widening_optab_handler_and_mode | ( | optab | op, |
enum machine_mode | to_mode, | ||
enum machine_mode | from_mode, | ||
int | permit_non_widening, | ||
enum machine_mode * | found_mode | ||
) |
Find a widening optab even if it doesn't widen as much as we want. E.g. if from_mode is HImode, and to_mode is DImode, and there is no direct HI->SI insn, then return SI->DI, if that exists. If PERMIT_NON_WIDENING is non-zero then this can be used with non-widening optabs also.
bool force_expand_binop | ( | enum machine_mode | mode, |
optab | binoptab, | ||
rtx | op0, | ||
rtx | op1, | ||
rtx | target, | ||
int | unsignedp, | ||
enum optab_methods | methods | ||
) |
Like simplify_expand_binop, but always put the result in TARGET. Return true if the expansion succeeded.
Referenced by expand_vector_broadcast().
void gen_extend_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Pick proper libcall for extend_optab. We need to chose if we do truncation or extension and interclass or intraclass.
Generate the body of an insn to extend Y (with mode MFROM) into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero.
void gen_fixed_libfunc | ( | optab | optable, |
const char * | opname, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that fixed-point operation is involved.
References targetm.
void gen_fp_libfunc | ( | optab | optable, |
const char * | opname, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that FP and set decimal prefix if needed.
For BID support, change the name to have either a bid_ or dpd_ prefix depending on the low level floating format used.
void gen_fp_to_int_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Same as gen_interclass_conv_libfunc but verify that we are producing fp->int conversion with no decimal floating point involved.
References init_one_libfunc(), libfunc_entry::mode1, libfunc_entry::mode2, and libfunc_entry::op.
void gen_fract_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Pick proper libcall for fract_optab. We need to chose if we do interclass or intraclass.
void gen_fractuns_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Pick proper libcall for fractuns_optab.
One mode must be a fixed-point mode, and the other must be an integer mode.
References set_optab_libfunc().
void gen_int_fixed_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that INT or FIXED operation is involved.
void gen_int_fp_fixed_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that FP or INT or FIXED operation is involved.
void gen_int_fp_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that FP or INT operation is involved.
void gen_int_fp_signed_fixed_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that FP or INT or signed FIXED operation is involved.
References gen_interclass_conv_libfunc().
void gen_int_libfunc | ( | optab | optable, |
const char * | opname, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that integer operation is involved.
References gen_interclass_conv_libfunc().
void gen_int_signed_fixed_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that INT or signed FIXED operation is involved.
References gen_interclass_conv_libfunc(), and gen_intraclass_conv_libfunc().
void gen_int_to_fp_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Same as gen_interclass_conv_libfunc but verify that we are producing int->fp conversion.
void gen_int_to_fp_nondecimal_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Same as gen_interclass_conv_libfunc but verify that we are producing fp->int conversion.
References get_identifier(), and set_user_assembler_name().
void gen_int_unsigned_fixed_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that INT or unsigned FIXED operation is involved.
References gen_interclass_conv_libfunc().
void gen_interclass_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Initialize the libfunc fields of an entire group of entries of an inter-mode-class conversion optab. The string formation rules are similar to the ones for init_libfuncs, above, but instead of having a mode name and an operand count these functions have two mode names and no operand count.
If this is a decimal conversion, add the current BID vs. DPD prefix that depends on which underlying decimal floating point format is used.
Referenced by gen_int_fp_signed_fixed_libfunc(), gen_int_libfunc(), gen_int_signed_fixed_libfunc(), gen_int_unsigned_fixed_libfunc(), and gen_libfunc().
void gen_intraclass_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Initialize the libfunc fields of an of an intra-mode-class conversion optab. The string formation rules are similar to the ones for init_libfunc, above.
If this is a decimal conversion, add the current BID vs. DPD prefix that depends on which underlying decimal floating point format is used.
Referenced by gen_int_signed_fixed_libfunc().
void gen_intv_fp_libfunc | ( | optab | optable, |
const char * | name, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that FP or INT operation is involved and add 'v' suffix for integer operation.
void gen_satfract_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Pick proper libcall for satfract_optab. We need to chose if we do interclass or intraclass.
TMODE must be a fixed-point mode.
void gen_satfractuns_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Pick proper libcall for satfractuns_optab.
TMODE must be a fixed-point mode, and FMODE must be an integer mode.
References gdbhooks::GET_RTX_NAME(), optab_libfunc(), and optab_to_code().
void gen_signed_fixed_libfunc | ( | optab | optable, |
const char * | opname, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that signed fixed-point operation is involved.
void gen_trunc_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
Pick proper libcall for trunc_optab. We need to chose if we do truncation or extension and interclass or intraclass.
References targetm.
void gen_ufloat_conv_libfunc | ( | convert_optab | tab, |
const char * | opname, | ||
enum machine_mode | tmode, | ||
enum machine_mode | fmode | ||
) |
ufloat_optab is special by using floatun for FP and floatuns decimal fp naming scheme.
void gen_unsigned_fixed_libfunc | ( | optab | optable, |
const char * | opname, | ||
char | suffix, | ||
enum machine_mode | mode | ||
) |
Like gen_libfunc, but verify that unsigned fixed-point operation is involved.
bool get_best_mem_extraction_insn | ( | extraction_insn * | insn, |
enum extraction_pattern | pattern, | ||
HOST_WIDE_INT | bitsize, | ||
HOST_WIDE_INT | bitnum, | ||
enum machine_mode | field_mode | ||
) |
Return true if an instruction exists to access a field of BITSIZE bits starting BITNUM bits into a memory structure. Describe the "best" such instruction in *INSN if so. PATTERN describes the type of insertion or extraction we want to perform and FIELDMODE is the natural mode of the extracted field. The instructions considered here only access bytes that overlap the bitfield; they do not touch any surrounding bytes.
bool get_best_reg_extraction_insn | ( | extraction_insn * | insn, |
enum extraction_pattern | pattern, | ||
unsigned HOST_WIDE_INT | struct_bits, | ||
enum machine_mode | field_mode | ||
) |
Return true if an instruction exists to access a field of mode FIELDMODE in a register structure that has STRUCT_BITS significant bits. Describe the "best" such instruction in *INSN if so. PATTERN describes the type of insertion or extraction we want to perform. For an insertion, the number of significant structure bits includes all bits of the target. For an extraction, it need only include the most significant bit of the field. Larger widths are acceptable in both cases.
void init_sync_libfuncs | ( | int | max | ) |
Call this to install all of the __sync libcalls up to size MAX.
bool insn_operand_matches | ( | enum insn_code | icode, |
unsigned int | opno, | ||
rtx | operand | ||
) |
Generate an instruction whose insn-code is INSN_CODE, with two operands: an output TARGET and an input OP0. TARGET *must* be nonzero, and the output is always stored there. CODE is an rtx code such that (CODE OP0) is an rtx that describes the value that is stored into TARGET. Return false if expansion failed.
References ccp_cmov, ccp_jump, ccp_store_flag, insn_operand_matches(), and optab_handler().
Referenced by supportable_convert_operation().
bool maybe_expand_insn | ( | enum insn_code | icode, |
unsigned int | nops, | ||
struct expand_operand * | ops | ||
) |
Try to emit instruction ICODE, using operands [OPS, OPS + NOPS) as its operands. Return true on success and emit no code on failure.
Referenced by block_move_libcall_safe_for_call_parm(), clear_storage_hints(), expand_builtin_update_setjmp_buf(), expand_sync_lock_test_and_set(), and push_block().
bool maybe_expand_jump_insn | ( | enum insn_code | icode, |
unsigned int | nops, | ||
struct expand_operand * | ops | ||
) |
Like maybe_expand_insn, but for jumps.
rtx maybe_gen_insn | ( | enum insn_code | icode, |
unsigned int | nops, | ||
struct expand_operand * | ops | ||
) |
Try to generate instruction ICODE, using operands [OPS, OPS + NOPS) as its operands. Return the instruction pattern on success, and emit any necessary set-up code. Return null and emit no code on failure.
Referenced by expand_atomic_fetch_op_no_fallback().
bool maybe_legitimize_operands | ( | enum insn_code | icode, |
unsigned int | opno, | ||
unsigned int | nops, | ||
struct expand_operand * | ops | ||
) |
Try to make operands [OPS, OPS + NOPS) match operands [OPNO, OPNO + NOPS) of instruction ICODE. Return true on success, leaving the new operand values in the OPS themselves. Emit no code on failure.
optab optab_for_tree_code | ( | enum tree_code | code, |
const_tree | type, | ||
enum optab_subtype | subtype | ||
) |
Return the optab used for computing the given operation on the type given by the second argument. The third argument distinguishes between the types of vector shifts and rotates
Return the optab used for computing the operation given by the tree code, CODE and the tree EXP. This function is not always usable (for example, it cannot give complete results for multiplication or division) but probably ought to be relied on more widely throughout the expander.
The signedness is determined from input operand.
The signedness is determined from input operand.
The signedness is determined from output operand.
References optab_scalar, optab_vector, and unknown_optab.
Referenced by add_rshift(), supportable_widening_operation(), vect_build_slp_tree_1(), and vect_recog_rotate_pattern().
|
inlinestatic |
Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing if the target does not have such an insn.
Referenced by add_rshift(), build_libfunc_function(), default_mangle_decl_assembler_name(), do_output_reload(), emit_move_change_mode(), expand_absneg_bit(), expand_doubleword_clz(), expand_fix(), expand_float(), expand_widening_mult(), fold_builtin_strcpy(), init_optabs(), maybe_emit_unop_insn(), push_block(), supportable_widening_operation(), vect_build_slp_tree_1(), vect_permute_load_chain(), and vect_recog_rotate_pattern().
|
inlinestatic |
Referenced by gen_satfractuns_conv_libfunc().
rtx prepare_operand | ( | enum insn_code | icode, |
rtx | x, | ||
int | opnum, | ||
enum machine_mode | mode, | ||
enum machine_mode | wider_mode, | ||
int | unsignedp | ||
) |
Before emitting an insn with code ICODE, make sure that X, which is going to be used for operand OPNUM of the insn, is converted from mode MODE to WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and that it is accepted by the operand predicate. Return the new value.
enum insn_code raw_optab_handler | ( | unsigned | ) |
Returns the active icode for the given (encoded) optab.
void set_conv_libfunc | ( | convert_optab | optab, |
enum machine_mode | tmode, | ||
enum machine_mode | fmode, | ||
const char * | name | ||
) |
Call this to reset the function entry for one conversion optab (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be either 0 or a string constant.
void set_optab_libfunc | ( | optab | , |
enum | machine_mode, | ||
const char * | |||
) |
Call this to reset the function entry for one optab.
rtx sign_expand_binop | ( | enum machine_mode | mode, |
optab | uoptab, | ||
optab | soptab, | ||
rtx | op0, | ||
rtx | op1, | ||
rtx | target, | ||
int | unsignedp, | ||
enum optab_methods | methods | ||
) |
Expand a binary operation with both signed and unsigned forms.
Expand a binary operator which has both signed and unsigned forms. UOPTAB is the optab for unsigned operations, and SOPTAB is for signed operations. If we widen unsigned operands, we may use a signed wider operation instead of an unsigned wider operation, since the result would be the same.
Do it without widening, if possible.
Try widening to a signed int. Disable any direct use of any signed insn in the current mode.
For unsigned operands, try widening to an unsigned int.
Use the right width libcall if that exists.
Must widen and use a libcall, use either signed or unsigned.
Undo the fiddling above.
rtx simplify_expand_binop | ( | enum machine_mode | mode, |
optab | binoptab, | ||
rtx | op0, | ||
rtx | op1, | ||
rtx | target, | ||
int | unsignedp, | ||
enum optab_methods | methods | ||
) |
Like expand_binop, but return a constant rtx if the result can be calculated at compile time. The arguments and return value are otherwise the same as for expand_binop.
Referenced by expand_doubleword_shift(), expand_subword_shift(), and expand_superword_shift().
bool supportable_convert_operation | ( | enum tree_code | code, |
tree | vectype_out, | ||
tree | vectype_in, | ||
tree * | decl, | ||
enum tree_code * | code1 | ||
) |
Check whether an operation represented by the code CODE is a convert operation that is supported by the target platform in vector form
Function supportable_convert_operation Check whether an operation represented by the code CODE is a convert operation that is supported by the target platform in vector form (i.e., when operating on arguments of type VECTYPE_IN producing a result of type VECTYPE_OUT). Convert operations we currently support directly are FIX_TRUNC and FLOAT. This function checks if these operations are supported by the target platform either directly (via vector tree-codes), or via target builtins. Output: - CODE1 is code of vector operation to be used when vectorizing the operation, if available. - DECL is decl of target builtin functions to be used when vectorizing the operation, if available. In this case, CODE1 is CALL_EXPR.
First check if we can done conversion directly.
Now check for builtin.
References can_fix_p(), convert_move(), convert_to_mode(), delete_insns_since(), expand_unop(), gen_reg_rtx(), get_last_insn(), and maybe_emit_unop_insn().
bool swap_optab_enable | ( | optab | , |
enum | machine_mode, | ||
bool | |||
) |
|
inlinestatic |
Return true if BINOPTAB is for a trapping-on-overflow operation.
|
inlinestatic |
Return true if UNOPTAB is for a trapping-on-overflow operation.
bool valid_multiword_target_p | ( | rtx | ) |
|
inlinestatic |
Like optab_handler, but for widening_operations that have a TO_MODE and a FROM_MODE.
??? Why does find_widening_optab_handler_and_mode attempt to widen things that can't be widened? E.g. add_optab...
References extraction_insn::field_mode, extraction_insn::icode, extraction_insn::pos_mode, and extraction_insn::struct_mode.
Referenced by expand_widening_mult().
const optab code_to_optab_[NUM_RTX_CODE] |
Contains the optab used for each rtx code, and vice-versa.
struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS] |
Referenced by convert_optab_libfunc().
struct target_optabs default_target_optabs |
@verbatim
Expand the basic unary and binary arithmetic operations, for GNU compiler. Copyright (C) 1987-2013 Free Software Foundation, Inc.
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/.
Include insn-config.h before expr.h so that HAVE_conditional_move is properly defined.
struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS] |
Referenced by optab_libfunc().
enum rtx_code optab_to_code_[NUM_OPTABS] |
struct target_optabs* this_fn_optabs |
Referenced by blocks_nreverse_all(), and save_target_globals().
struct target_optabs* this_target_optabs |