Commit a5c7d693 by Richard Sandiford Committed by Richard Sandiford

optabs.h (emit_unop_insn, [...]): Change insn code parameter from "int" to "enum insn_code".

gcc/
	* optabs.h (emit_unop_insn, maybe_emit_unop_insn): Change insn code
	parameter from "int" to "enum insn_code".
	(expand_operand_type): New enum.
	(expand_operand): New structure.
	(create_expand_operand): New function.
	(create_fixed_operand, create_output_operand): Likewise
	(create_input_operand, create_convert_operand_to): Likewise.
	(create_convert_operand_from, create_address_operand): Likewise.
	(create_integer_operand): Likewise.
	(create_convert_operand_from_type, maybe_legitimize_operands): Declare.
	(maybe_gen_insn, maybe_expand_insn, maybe_expand_jump_insn): Likewise.
	(expand_insn, expand_jump_insn): Likewise.
	* builtins.c (expand_builtin_prefetch): Use the new interfaces.
	(expand_builtin_interclass_mathfn, expand_builtin_strlen): Likewise.
	(expand_movstr, expand_builtin___clear_cache): Likewise.
	(expand_builtin_lock_release): Likewise.
	* explow.c (allocate_dynamic_stack_space): Likewise.
	(probe_stack_range): Likewise.  Allow check_stack to FAIL,
	and use the default handling in that case.
	* expmed.c (check_predicate_volatile_ok): Delete.
	(store_bit_field_1, extract_bit_field_1): Use the new interfaces.
	(emit_cstore): Likewise.
	* expr.c (emit_block_move_via_movmem): Likewise.
	(set_storage_via_setmem, expand_assignment): Likewise.
	(emit_storent_insn, try_casesi): Likewise.
	(emit_single_push_insn): Likewise.  Allow the expansion to fail.
	* optabs.c (expand_widen_pattern_expr, expand_ternary_op): Likewise.
	(expand_vec_shift_expr, expand_binop_directly): Likewise.
	(expand_twoval_unop, expand_twoval_binop): Likewise.
	(expand_unop_direct, emit_indirect_jump): Likewise.
	(emit_conditional_move, vector_compare_rtx): Likewise.
	(expand_vec_cond_expr, expand_val_compare_and_swap_1): Likewise.
	(expand_sync_operation, expand_sync_fetch_operation): Likewise.
	(expand_sync_lock_test_and_set): Likewise.
	(maybe_emit_unop_insn): Likewise.  Change icode to an insn_code.
	(emit_unop_insn): Likewise.
	(expand_copysign_absneg): Change icode to an insn_code.
	(create_convert_operand_from_type): New function.
	(maybe_legitimize_operand, maybe_legitimize_operands): Likewise.
	(maybe_gen_insn, maybe_expand_insn, maybe_expand_jump_insn): Likewise.
	(expand_insn, expand_jump_insn): Likewise.
	* config/i386/i386.md (setmem<mode>): Use nonmemory_operand rather
	than const_int_operand for operand 2.

From-SVN: r171341
parent 78fadbab
2011-03-23 Richard Sandiford <richard.sandiford@linaro.org>
* optabs.h (emit_unop_insn, maybe_emit_unop_insn): Change insn code
parameter from "int" to "enum insn_code".
(expand_operand_type): New enum.
(expand_operand): New structure.
(create_expand_operand): New function.
(create_fixed_operand, create_output_operand): Likewise
(create_input_operand, create_convert_operand_to): Likewise.
(create_convert_operand_from, create_address_operand): Likewise.
(create_integer_operand): Likewise.
(create_convert_operand_from_type, maybe_legitimize_operands): Declare.
(maybe_gen_insn, maybe_expand_insn, maybe_expand_jump_insn): Likewise.
(expand_insn, expand_jump_insn): Likewise.
* builtins.c (expand_builtin_prefetch): Use the new interfaces.
(expand_builtin_interclass_mathfn, expand_builtin_strlen): Likewise.
(expand_movstr, expand_builtin___clear_cache): Likewise.
(expand_builtin_lock_release): Likewise.
* explow.c (allocate_dynamic_stack_space): Likewise.
(probe_stack_range): Likewise. Allow check_stack to FAIL,
and use the default handling in that case.
* expmed.c (check_predicate_volatile_ok): Delete.
(store_bit_field_1, extract_bit_field_1): Use the new interfaces.
(emit_cstore): Likewise.
* expr.c (emit_block_move_via_movmem): Likewise.
(set_storage_via_setmem, expand_assignment): Likewise.
(emit_storent_insn, try_casesi): Likewise.
(emit_single_push_insn): Likewise. Allow the expansion to fail.
* optabs.c (expand_widen_pattern_expr, expand_ternary_op): Likewise.
(expand_vec_shift_expr, expand_binop_directly): Likewise.
(expand_twoval_unop, expand_twoval_binop): Likewise.
(expand_unop_direct, emit_indirect_jump): Likewise.
(emit_conditional_move, vector_compare_rtx): Likewise.
(expand_vec_cond_expr, expand_val_compare_and_swap_1): Likewise.
(expand_sync_operation, expand_sync_fetch_operation): Likewise.
(expand_sync_lock_test_and_set): Likewise.
(maybe_emit_unop_insn): Likewise. Change icode to an insn_code.
(emit_unop_insn): Likewise.
(expand_copysign_absneg): Change icode to an insn_code.
(create_convert_operand_from_type): New function.
(maybe_legitimize_operand, maybe_legitimize_operands): Likewise.
(maybe_gen_insn, maybe_expand_insn, maybe_expand_jump_insn): Likewise.
(expand_insn, expand_jump_insn): Likewise.
* config/i386/i386.md (setmem<mode>): Use nonmemory_operand rather
than const_int_operand for operand 2.
2011-03-23 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> 2011-03-23 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* dwarf2out.c (const_ok_for_output_1): Print the unspec enum name * dwarf2out.c (const_ok_for_output_1): Print the unspec enum name
......
...@@ -1143,15 +1143,13 @@ expand_builtin_prefetch (tree exp) ...@@ -1143,15 +1143,13 @@ expand_builtin_prefetch (tree exp)
#ifdef HAVE_prefetch #ifdef HAVE_prefetch
if (HAVE_prefetch) if (HAVE_prefetch)
{ {
if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate) struct expand_operand ops[3];
(op0,
insn_data[(int) CODE_FOR_prefetch].operand[0].mode)) create_address_operand (&ops[0], op0);
|| (GET_MODE (op0) != Pmode)) create_integer_operand (&ops[1], INTVAL (op1));
{ create_integer_operand (&ops[2], INTVAL (op2));
op0 = convert_memory_address (Pmode, op0); if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
op0 = force_reg (Pmode, op0); return;
}
emit_insn (gen_prefetch (op0, op1, op2));
} }
#endif #endif
...@@ -2431,16 +2429,9 @@ expand_builtin_interclass_mathfn (tree exp, rtx target) ...@@ -2431,16 +2429,9 @@ expand_builtin_interclass_mathfn (tree exp, rtx target)
if (icode != CODE_FOR_nothing) if (icode != CODE_FOR_nothing)
{ {
struct expand_operand ops[1];
rtx last = get_last_insn (); rtx last = get_last_insn ();
tree orig_arg = arg; tree orig_arg = arg;
/* Make a suitable register to place result in. */
if (!target
|| GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))
|| !insn_data[icode].operand[0].predicate (target, GET_MODE (target)))
target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
gcc_assert (insn_data[icode].operand[0].predicate
(target, GET_MODE (target)));
/* Wrap the computation of the argument in a SAVE_EXPR, as we may /* Wrap the computation of the argument in a SAVE_EXPR, as we may
need to expand the argument again. This way, we will not perform need to expand the argument again. This way, we will not perform
...@@ -2452,10 +2443,11 @@ expand_builtin_interclass_mathfn (tree exp, rtx target) ...@@ -2452,10 +2443,11 @@ expand_builtin_interclass_mathfn (tree exp, rtx target)
if (mode != GET_MODE (op0)) if (mode != GET_MODE (op0))
op0 = convert_to_mode (mode, op0, 0); op0 = convert_to_mode (mode, op0, 0);
/* Compute into TARGET. create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
Set TARGET to wherever the result comes back. */ if (maybe_legitimize_operands (icode, 0, 1, ops)
if (maybe_emit_unop_insn (icode, target, op0, UNKNOWN)) && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
return target; return ops[0].value;
delete_insns_since (last); delete_insns_since (last);
CALL_EXPR_ARG (exp, 0) = orig_arg; CALL_EXPR_ARG (exp, 0) = orig_arg;
} }
...@@ -3362,11 +3354,12 @@ expand_builtin_strlen (tree exp, rtx target, ...@@ -3362,11 +3354,12 @@ expand_builtin_strlen (tree exp, rtx target,
return NULL_RTX; return NULL_RTX;
else else
{ {
struct expand_operand ops[4];
rtx pat; rtx pat;
tree len; tree len;
tree src = CALL_EXPR_ARG (exp, 0); tree src = CALL_EXPR_ARG (exp, 0);
rtx result, src_reg, char_rtx, before_strlen; rtx src_reg, before_strlen;
enum machine_mode insn_mode = target_mode, char_mode; enum machine_mode insn_mode = target_mode;
enum insn_code icode = CODE_FOR_nothing; enum insn_code icode = CODE_FOR_nothing;
unsigned int align; unsigned int align;
...@@ -3405,14 +3398,6 @@ expand_builtin_strlen (tree exp, rtx target, ...@@ -3405,14 +3398,6 @@ expand_builtin_strlen (tree exp, rtx target,
if (insn_mode == VOIDmode) if (insn_mode == VOIDmode)
return NULL_RTX; return NULL_RTX;
/* Make a place to write the result of the instruction. */
result = target;
if (! (result != 0
&& REG_P (result)
&& GET_MODE (result) == insn_mode
&& REGNO (result) >= FIRST_PSEUDO_REGISTER))
result = gen_reg_rtx (insn_mode);
/* Make a place to hold the source address. We will not expand /* Make a place to hold the source address. We will not expand
the actual source until we are sure that the expansion will the actual source until we are sure that the expansion will
not fail -- there are trees that cannot be expanded twice. */ not fail -- there are trees that cannot be expanded twice. */
...@@ -3422,17 +3407,12 @@ expand_builtin_strlen (tree exp, rtx target, ...@@ -3422,17 +3407,12 @@ expand_builtin_strlen (tree exp, rtx target,
source operand later. */ source operand later. */
before_strlen = get_last_insn (); before_strlen = get_last_insn ();
char_rtx = const0_rtx; create_output_operand (&ops[0], target, insn_mode);
char_mode = insn_data[(int) icode].operand[2].mode; create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx, create_integer_operand (&ops[2], 0);
char_mode)) create_integer_operand (&ops[3], align);
char_rtx = copy_to_mode_reg (char_mode, char_rtx); if (!maybe_expand_insn (icode, 4, ops))
pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
char_rtx, GEN_INT (align));
if (! pat)
return NULL_RTX; return NULL_RTX;
emit_insn (pat);
/* Now that we are assured of success, expand the source. */ /* Now that we are assured of success, expand the source. */
start_sequence (); start_sequence ();
...@@ -3448,12 +3428,12 @@ expand_builtin_strlen (tree exp, rtx target, ...@@ -3448,12 +3428,12 @@ expand_builtin_strlen (tree exp, rtx target,
emit_insn_before (pat, get_insns ()); emit_insn_before (pat, get_insns ());
/* Return the value in the proper mode for this function. */ /* Return the value in the proper mode for this function. */
if (GET_MODE (result) == target_mode) if (GET_MODE (ops[0].value) == target_mode)
target = result; target = ops[0].value;
else if (target != 0) else if (target != 0)
convert_move (target, result, 0); convert_move (target, ops[0].value, 0);
else else
target = convert_to_mode (target_mode, result, 0); target = convert_to_mode (target_mode, ops[0].value, 0);
return target; return target;
} }
...@@ -3674,56 +3654,39 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len, ...@@ -3674,56 +3654,39 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len,
static rtx static rtx
expand_movstr (tree dest, tree src, rtx target, int endp) expand_movstr (tree dest, tree src, rtx target, int endp)
{ {
struct expand_operand ops[3];
rtx end; rtx end;
rtx dest_mem; rtx dest_mem;
rtx src_mem; rtx src_mem;
rtx insn;
const struct insn_data_d * data;
if (!HAVE_movstr) if (!HAVE_movstr)
return NULL_RTX; return NULL_RTX;
dest_mem = get_memory_rtx (dest, NULL); dest_mem = get_memory_rtx (dest, NULL);
src_mem = get_memory_rtx (src, NULL); src_mem = get_memory_rtx (src, NULL);
data = insn_data + CODE_FOR_movstr;
if (!endp) if (!endp)
{ {
target = force_reg (Pmode, XEXP (dest_mem, 0)); target = force_reg (Pmode, XEXP (dest_mem, 0));
dest_mem = replace_equiv_address (dest_mem, target); dest_mem = replace_equiv_address (dest_mem, target);
end = gen_reg_rtx (Pmode);
}
else
{
if (target == 0
|| target == const0_rtx
|| ! (*data->operand[0].predicate) (target, Pmode))
{
end = gen_reg_rtx (Pmode);
if (target != const0_rtx)
target = end;
}
else
end = target;
} }
if (data->operand[0].mode != VOIDmode) create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
end = gen_lowpart (data->operand[0].mode, end); create_fixed_operand (&ops[1], dest_mem);
create_fixed_operand (&ops[2], src_mem);
insn = data->genfun (end, dest_mem, src_mem); expand_insn (CODE_FOR_movstr, 3, ops);
gcc_assert (insn);
emit_insn (insn); if (endp && target != const0_rtx)
/* movstr is supposed to set end to the address of the NUL
terminator. If the caller requested a mempcpy-like return value,
adjust it. */
if (endp == 1 && target != const0_rtx)
{ {
rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1); target = ops[0].value;
emit_move_insn (target, force_operand (tem, NULL_RTX)); /* movstr is supposed to set end to the address of the NUL
terminator. If the caller requested a mempcpy-like return value,
adjust it. */
if (endp == 1)
{
rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
emit_move_insn (target, force_operand (tem, NULL_RTX));
}
} }
return target; return target;
} }
...@@ -5223,7 +5186,6 @@ expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED) ...@@ -5223,7 +5186,6 @@ expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
/* We have a "clear_cache" insn, and it will handle everything. */ /* We have a "clear_cache" insn, and it will handle everything. */
tree begin, end; tree begin, end;
rtx begin_rtx, end_rtx; rtx begin_rtx, end_rtx;
enum insn_code icode;
/* We must not expand to a library call. If we did, any /* We must not expand to a library call. If we did, any
fallback library function in libgcc that might contain a call to fallback library function in libgcc that might contain a call to
...@@ -5236,21 +5198,18 @@ expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED) ...@@ -5236,21 +5198,18 @@ expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
if (HAVE_clear_cache) if (HAVE_clear_cache)
{ {
icode = CODE_FOR_clear_cache; struct expand_operand ops[2];
begin = CALL_EXPR_ARG (exp, 0); begin = CALL_EXPR_ARG (exp, 0);
begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL); begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
begin_rtx = convert_memory_address (Pmode, begin_rtx);
if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
end = CALL_EXPR_ARG (exp, 1); end = CALL_EXPR_ARG (exp, 1);
end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL); end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
end_rtx = convert_memory_address (Pmode, end_rtx);
if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
end_rtx = copy_to_mode_reg (Pmode, end_rtx);
emit_insn (gen_clear_cache (begin_rtx, end_rtx)); create_address_operand (&ops[0], begin_rtx);
create_address_operand (&ops[1], end_rtx);
if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
return const0_rtx;
} }
return const0_rtx; return const0_rtx;
#endif /* HAVE_clear_cache */ #endif /* HAVE_clear_cache */
...@@ -5748,9 +5707,9 @@ expand_builtin_synchronize (void) ...@@ -5748,9 +5707,9 @@ expand_builtin_synchronize (void)
static void static void
expand_builtin_lock_release (enum machine_mode mode, tree exp) expand_builtin_lock_release (enum machine_mode mode, tree exp)
{ {
struct expand_operand ops[2];
enum insn_code icode; enum insn_code icode;
rtx mem, insn; rtx mem;
rtx val = const0_rtx;
/* Expand the operands. */ /* Expand the operands. */
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
...@@ -5759,21 +5718,16 @@ expand_builtin_lock_release (enum machine_mode mode, tree exp) ...@@ -5759,21 +5718,16 @@ expand_builtin_lock_release (enum machine_mode mode, tree exp)
icode = direct_optab_handler (sync_lock_release_optab, mode); icode = direct_optab_handler (sync_lock_release_optab, mode);
if (icode != CODE_FOR_nothing) if (icode != CODE_FOR_nothing)
{ {
if (!insn_data[icode].operand[1].predicate (val, mode)) create_fixed_operand (&ops[0], mem);
val = force_reg (mode, val); create_input_operand (&ops[1], const0_rtx, mode);
if (maybe_expand_insn (icode, 2, ops))
insn = GEN_FCN (icode) (mem, val); return;
if (insn)
{
emit_insn (insn);
return;
}
} }
/* Otherwise we can implement this operation by emitting a barrier /* Otherwise we can implement this operation by emitting a barrier
followed by a store of zero. */ followed by a store of zero. */
expand_builtin_synchronize (); expand_builtin_synchronize ();
emit_move_insn (mem, val); emit_move_insn (mem, const0_rtx);
} }
/* Expand an expression EXP that calls a built-in function, /* Expand an expression EXP that calls a built-in function,
......
...@@ -15793,7 +15793,7 @@ ...@@ -15793,7 +15793,7 @@
(define_expand "setmem<mode>" (define_expand "setmem<mode>"
[(use (match_operand:BLK 0 "memory_operand" "")) [(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:SWI48 1 "nonmemory_operand" "")) (use (match_operand:SWI48 1 "nonmemory_operand" ""))
(use (match_operand 2 "const_int_operand" "")) (use (match_operand:QI 2 "nonmemory_operand" ""))
(use (match_operand 3 "const_int_operand" "")) (use (match_operand 3 "const_int_operand" ""))
(use (match_operand:SI 4 "const_int_operand" "")) (use (match_operand:SI 4 "const_int_operand" ""))
(use (match_operand:SI 5 "const_int_operand" ""))] (use (match_operand:SI 5 "const_int_operand" ""))]
......
...@@ -1379,21 +1379,13 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align, ...@@ -1379,21 +1379,13 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
#ifdef HAVE_allocate_stack #ifdef HAVE_allocate_stack
if (HAVE_allocate_stack) if (HAVE_allocate_stack)
{ {
enum machine_mode mode = STACK_SIZE_MODE; struct expand_operand ops[2];
insn_operand_predicate_fn pred;
/* We don't have to check against the predicate for operand 0 since /* We don't have to check against the predicate for operand 0 since
TARGET is known to be a pseudo of the proper mode, which must TARGET is known to be a pseudo of the proper mode, which must
be valid for the operand. For operand 1, convert to the be valid for the operand. */
proper mode and validate. */ create_fixed_operand (&ops[0], target);
if (mode == VOIDmode) create_convert_operand_to (&ops[1], size, STACK_SIZE_MODE, true);
mode = insn_data[(int) CODE_FOR_allocate_stack].operand[1].mode; expand_insn (CODE_FOR_allocate_stack, 2, ops);
pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
if (pred && ! ((*pred) (size, mode)))
size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
emit_insn (gen_allocate_stack (target, size));
} }
else else
#endif #endif
...@@ -1544,22 +1536,22 @@ probe_stack_range (HOST_WIDE_INT first, rtx size) ...@@ -1544,22 +1536,22 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
plus_constant (size, first))); plus_constant (size, first)));
emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr, emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
Pmode); Pmode);
return;
} }
/* Next see if we have an insn to check the stack. */ /* Next see if we have an insn to check the stack. */
#ifdef HAVE_check_stack #ifdef HAVE_check_stack
else if (HAVE_check_stack) if (HAVE_check_stack)
{ {
struct expand_operand ops[1];
rtx addr = memory_address (Pmode, rtx addr = memory_address (Pmode,
gen_rtx_fmt_ee (STACK_GROW_OP, Pmode, gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
stack_pointer_rtx, stack_pointer_rtx,
plus_constant (size, first))); plus_constant (size, first)));
insn_operand_predicate_fn pred
= insn_data[(int) CODE_FOR_check_stack].operand[0].predicate;
if (pred && !((*pred) (addr, Pmode)))
addr = copy_to_mode_reg (Pmode, addr);
emit_insn (gen_check_stack (addr)); create_input_operand (&ops[0], addr, Pmode);
if (maybe_expand_insn (CODE_FOR_check_stack, 1, ops))
return;
} }
#endif #endif
......
...@@ -791,8 +791,8 @@ extern rtx expand_copysign (rtx, rtx, rtx); ...@@ -791,8 +791,8 @@ extern rtx expand_copysign (rtx, rtx, rtx);
/* Generate an instruction with a given INSN_CODE with an output and /* Generate an instruction with a given INSN_CODE with an output and
an input. */ an input. */
extern void emit_unop_insn (int, rtx, rtx, enum rtx_code); extern void emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
extern bool maybe_emit_unop_insn (int, rtx, rtx, enum rtx_code); extern bool maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
/* An extra flag to control optab_for_tree_code's behavior. This is needed to /* An extra flag to control optab_for_tree_code's behavior. This is needed to
distinguish between machines with a vector shift that takes a scalar for the distinguish between machines with a vector shift that takes a scalar for the
...@@ -926,6 +926,148 @@ extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, ...@@ -926,6 +926,148 @@ extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
extern bool insn_operand_matches (enum insn_code icode, unsigned int opno, extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
rtx operand); rtx operand);
/* Describes the type of an expand_operand. Each value is associated
with a create_*_operand function; see the comments above those
functions for details. */
enum expand_operand_type {
EXPAND_FIXED,
EXPAND_OUTPUT,
EXPAND_INPUT,
EXPAND_CONVERT_TO,
EXPAND_CONVERT_FROM,
EXPAND_ADDRESS,
EXPAND_INTEGER
};
/* Information about an operand for instruction expansion. */
struct expand_operand {
/* The type of operand. */
ENUM_BITFIELD (expand_operand_type) type : 8;
/* True if any conversion should treat VALUE as being unsigned
rather than signed. Only meaningful for certain types. */
unsigned int unsigned_p : 1;
/* Unused; available for future use. */
unsigned int unused : 7;
/* The mode passed to the convert_*_operand function. It has a
type-dependent meaning. */
ENUM_BITFIELD (machine_mode) mode : 16;
/* The value of the operand. */
rtx value;
};
/* Initialize OP with the given fields. Initialise the other fields
to their default values. */
static inline void
create_expand_operand (struct expand_operand *op,
enum expand_operand_type type,
rtx value, enum machine_mode mode,
bool unsigned_p)
{
op->type = type;
op->unsigned_p = unsigned_p;
op->unused = 0;
op->mode = mode;
op->value = value;
}
/* Make OP describe an operand that must use rtx X, even if X is volatile. */
static inline void
create_fixed_operand (struct expand_operand *op, rtx x)
{
create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false);
}
/* 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. */
static inline void
create_output_operand (struct expand_operand *op, rtx x,
enum machine_mode mode)
{
create_expand_operand (op, EXPAND_OUTPUT, x, mode, false);
}
/* 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. */
static inline void
create_input_operand (struct expand_operand *op, rtx value,
enum machine_mode mode)
{
create_expand_operand (op, EXPAND_INPUT, value, mode, false);
}
/* Like create_input_operand, except that VALUE must first be converted
to mode MODE. UNSIGNED_P says whether VALUE is unsigned. */
static inline void
create_convert_operand_to (struct expand_operand *op, rtx value,
enum machine_mode mode, bool unsigned_p)
{
create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p);
}
/* 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. */
static inline void
create_convert_operand_from (struct expand_operand *op, rtx value,
enum machine_mode mode, bool unsigned_p)
{
create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p);
}
extern void create_convert_operand_from_type (struct expand_operand *op,
rtx value, tree type);
/* 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. */
static inline void
create_address_operand (struct expand_operand *op, rtx value)
{
create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false);
}
/* 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. */
static inline void
create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
{
create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
}
extern bool maybe_legitimize_operands (enum insn_code icode,
unsigned int opno, unsigned int nops,
struct expand_operand *ops);
extern rtx maybe_gen_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops);
extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops);
extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops);
extern void expand_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops);
extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
struct expand_operand *ops);
extern rtx prepare_operand (enum insn_code, rtx, int, enum machine_mode, extern rtx prepare_operand (enum insn_code, rtx, int, enum machine_mode,
enum machine_mode, int); enum machine_mode, int);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment