Commit fcdd52b7 by Richard Sandiford Committed by Richard Sandiford

Makefile.in (recog.o): Add insn-codes.h.

gcc/
	* Makefile.in (recog.o): Add insn-codes.h.
	* expr.h (extraction_pattern): Move to optabs.h.
	(mode_for_extraction): Delete.
	* optabs.h (extraction_insn): New structure.
	(extraction_pattern): Moved from expr.h.
	(get_best_reg_extraction_insn, get_best_mem_extraction_insn): Declare.
	* optabs.c (HAVE_insv, CODE_FOR_insv, HAVE_extv, CODE_FOR_extv)
	(HAVE_extzv, CODE_FOR_extzv): Provide defaults.
	(extraction_type): New enum.
	(get_traditional_extraction_insn, get_extraction_insn)
	(get_best_reg_extraction_insn, get_best_mem_extraction_insn):
	New functions.
	* combine.c (make_extraction): Use get_best_reg_extraction_insn
	instead of mode_for_extraction.
	* expmed.c (HAVE_insv, CODE_FOR_insv, gen_insv, HAVE_extv)
	(CODE_FOR_extv, gen_extv, HAVE_extzv, CODE_FOR_extzv, gen_extzv):
	Remove fallback definitions.
	(mode_for_extraction): Delete.
	(adjust_bit_field_mem_for_reg): New function.
	(store_bit_field_using_insv): Replace OP_MODE parameter with
	an extraction_insn.  Pass struct_mode to narrow_bit_field_mem.
	(extract_bit_field_using_extv): Likewise EXT_MODE.
	(store_bit_field_1): Use get_best_reg_extraction_insn and
	get_best_mem_extraction_insn instead of mode_for_extraction.
	Use adjust_bit_field_mem_for_reg when forcing memory to a
	register and doing a register insertion.  Update calls to
	store_bit_field_using_insv.
	(extract_bit_field_1): Likewise extractions and calls to
	extract_bit_field_using_extv.
	(store_Bit_field): When narrowing to a bitregion, don't use the
	insv mode as a limit.
	* recog.c: (HAVE_extv, CODE_FOR_extv, HAVE_extzv, CODE_FOR_extzv):
	Provide defaults.
	(simplify_while_replacing): Use insn_data instead of
	mode_for_extraction.

From-SVN: r193605
parent 8b7d5dab
2012-11-18 Richard Sandiford <rdsandiford@googlemail.com>
* Makefile.in (recog.o): Add insn-codes.h.
* expr.h (extraction_pattern): Move to optabs.h.
(mode_for_extraction): Delete.
* optabs.h (extraction_insn): New structure.
(extraction_pattern): Moved from expr.h.
(get_best_reg_extraction_insn, get_best_mem_extraction_insn): Declare.
* optabs.c (HAVE_insv, CODE_FOR_insv, HAVE_extv, CODE_FOR_extv)
(HAVE_extzv, CODE_FOR_extzv): Provide defaults.
(extraction_type): New enum.
(get_traditional_extraction_insn, get_extraction_insn)
(get_best_reg_extraction_insn, get_best_mem_extraction_insn):
New functions.
* combine.c (make_extraction): Use get_best_reg_extraction_insn
instead of mode_for_extraction.
* expmed.c (HAVE_insv, CODE_FOR_insv, gen_insv, HAVE_extv)
(CODE_FOR_extv, gen_extv, HAVE_extzv, CODE_FOR_extzv, gen_extzv):
Remove fallback definitions.
(mode_for_extraction): Delete.
(adjust_bit_field_mem_for_reg): New function.
(store_bit_field_using_insv): Replace OP_MODE parameter with
an extraction_insn. Pass struct_mode to narrow_bit_field_mem.
(extract_bit_field_using_extv): Likewise EXT_MODE.
(store_bit_field_1): Use get_best_reg_extraction_insn and
get_best_mem_extraction_insn instead of mode_for_extraction.
Use adjust_bit_field_mem_for_reg when forcing memory to a
register and doing a register insertion. Update calls to
store_bit_field_using_insv.
(extract_bit_field_1): Likewise extractions and calls to
extract_bit_field_using_extv.
(store_Bit_field): When narrowing to a bitregion, don't use the
insv mode as a limit.
* recog.c: (HAVE_extv, CODE_FOR_extv, HAVE_extzv, CODE_FOR_extzv):
Provide defaults.
(simplify_while_replacing): Use insn_data instead of
mode_for_extraction.
2012-11-18 Richard Sandiford <rdsandiford@googlemail.com>
* stor-layout.c (bit_field_mode_iterator::bit_field_mode_iterator):
Set up a default value of bitregion_end_.
(bit_field_mode_iterator::next_mode): Always apply bitregion_end_
......@@ -3355,7 +3355,7 @@ recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
$(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
$(FLAGS_H) insn-config.h $(INSN_ATTR_H) reload.h \
addresses.h $(TM_P_H) $(TREE_PASS_H) hard-reg-set.h \
$(DF_H) $(DBGCNT_H) $(TARGET_H) $(DIAGNOSTIC_CORE_H)
$(DF_H) $(DBGCNT_H) $(TARGET_H) $(DIAGNOSTIC_CORE_H) insn-codes.h
reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_ERROR_H) $(TREE_H) $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
insn-config.h reload.h $(FUNCTION_H) $(TM_P_H) $(GGC_H) \
......
......@@ -7179,29 +7179,24 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
|| (pos_rtx != 0 && len != 1)))
return 0;
/* Get the mode to use should INNER not be a MEM, the mode for the position,
and the mode for the result. */
if (in_dest && mode_for_extraction (EP_insv, -1) != MAX_MACHINE_MODE)
{
wanted_inner_reg_mode = mode_for_extraction (EP_insv, 0);
pos_mode = mode_for_extraction (EP_insv, 2);
extraction_mode = mode_for_extraction (EP_insv, 3);
}
enum extraction_pattern pattern = (in_dest ? EP_insv
: unsignedp ? EP_extzv : EP_extv);
if (! in_dest && unsignedp
&& mode_for_extraction (EP_extzv, -1) != MAX_MACHINE_MODE)
{
wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1);
pos_mode = mode_for_extraction (EP_extzv, 3);
extraction_mode = mode_for_extraction (EP_extzv, 0);
}
/* If INNER is not from memory, we want it to have the mode of a register
extraction pattern's structure operand, or word_mode if there is no
such pattern. The same applies to extraction_mode and pos_mode
and their respective operands.
if (! in_dest && ! unsignedp
&& mode_for_extraction (EP_extv, -1) != MAX_MACHINE_MODE)
For memory, assume that the desired extraction_mode and pos_mode
are the same as for a register operation, since at present we don't
have named patterns for aligned memory structures. */
struct extraction_insn insn;
if (get_best_reg_extraction_insn (&insn, pattern,
GET_MODE_BITSIZE (inner_mode), mode))
{
wanted_inner_reg_mode = mode_for_extraction (EP_extv, 1);
pos_mode = mode_for_extraction (EP_extv, 3);
extraction_mode = mode_for_extraction (EP_extv, 0);
wanted_inner_reg_mode = insn.struct_mode;
pos_mode = insn.pos_mode;
extraction_mode = insn.field_mode;
}
/* Never narrow an object, since that might not be safe. */
......@@ -7210,9 +7205,6 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
&& GET_MODE_SIZE (extraction_mode) < GET_MODE_SIZE (mode))
extraction_mode = mode;
/* If this is not from memory, the desired mode is the preferred mode
for an extraction pattern's first input operand, or word_mode if there
is none. */
if (!MEM_P (inner))
wanted_inner_mode = wanted_inner_reg_mode;
else
......
......@@ -698,14 +698,6 @@ extern void probe_stack_range (HOST_WIDE_INT, rtx);
in its original home. This becomes invalid if any more code is emitted. */
extern rtx hard_libcall_value (enum machine_mode, rtx);
/* Return the mode desired by operand N of a particular bitfield
insert/extract insn, or MAX_MACHINE_MODE if no such insn is
available. */
enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
extern enum machine_mode
mode_for_extraction (enum extraction_pattern, int);
extern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
......
......@@ -8239,4 +8239,177 @@ expand_jump_insn (enum insn_code icode, unsigned int nops,
gcc_unreachable ();
}
/* Reduce conditional compilation elsewhere. */
#ifndef HAVE_insv
#define HAVE_insv 0
#define CODE_FOR_insv CODE_FOR_nothing
#endif
#ifndef HAVE_extv
#define HAVE_extv 0
#define CODE_FOR_extv CODE_FOR_nothing
#endif
#ifndef HAVE_extzv
#define HAVE_extzv 0
#define CODE_FOR_extzv CODE_FOR_nothing
#endif
/* Enumerates the possible types of structure operand to an
extraction_insn. */
enum extraction_type { ET_unaligned_mem, ET_reg };
/* Check whether insv, extv or extzv pattern ICODE can be used for an
insertion or extraction of type TYPE on a structure of mode MODE.
Return true if so and fill in *INSN accordingly. STRUCT_OP is the
operand number of the structure (the first sign_extract or zero_extract
operand) and FIELD_OP is the operand number of the field (the other
side of the set from the sign_extract or zero_extract). */
static bool
get_traditional_extraction_insn (extraction_insn *insn,
enum extraction_type type,
enum machine_mode mode,
enum insn_code icode,
int struct_op, int field_op)
{
const struct insn_data_d *data = &insn_data[icode];
enum machine_mode struct_mode = data->operand[struct_op].mode;
if (struct_mode == VOIDmode)
struct_mode = word_mode;
if (mode != struct_mode)
return false;
enum machine_mode field_mode = data->operand[field_op].mode;
if (field_mode == VOIDmode)
field_mode = word_mode;
enum machine_mode pos_mode = data->operand[struct_op + 2].mode;
if (pos_mode == VOIDmode)
pos_mode = word_mode;
insn->icode = icode;
insn->field_mode = field_mode;
insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
insn->pos_mode = pos_mode;
return true;
}
/* Return true if an instruction exists to perform an insertion or
extraction (PATTERN says which) of type TYPE in mode MODE.
Describe the instruction in *INSN if so. */
static bool
get_extraction_insn (extraction_insn *insn,
enum extraction_pattern pattern,
enum extraction_type type,
enum machine_mode mode)
{
switch (pattern)
{
case EP_insv:
if (HAVE_insv
&& get_traditional_extraction_insn (insn, type, mode,
CODE_FOR_insv, 0, 3))
return true;
return false;
case EP_extv:
if (HAVE_extv
&& get_traditional_extraction_insn (insn, type, mode,
CODE_FOR_extv, 1, 0))
return true;
return false;
case EP_extzv:
if (HAVE_extzv
&& get_traditional_extraction_insn (insn, type, mode,
CODE_FOR_extzv, 1, 0))
return true;
return false;
default:
gcc_unreachable ();
}
}
/* Return true if an instruction exists to access a field of mode
FIELDMODE in a structure that has STRUCT_BITS significant bits.
Describe the "best" such instruction in *INSN if so. PATTERN and
TYPE describe 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. */
static bool
get_best_extraction_insn (extraction_insn *insn,
enum extraction_pattern pattern,
enum extraction_type type,
unsigned HOST_WIDE_INT struct_bits,
enum machine_mode field_mode)
{
enum machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
while (mode != VOIDmode)
{
if (get_extraction_insn (insn, pattern, type, mode))
{
while (mode != VOIDmode
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode)
&& !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
field_mode))
{
get_extraction_insn (insn, pattern, type, mode);
mode = GET_MODE_WIDER_MODE (mode);
}
return true;
}
mode = GET_MODE_WIDER_MODE (mode);
}
return false;
}
/* 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. */
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 get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
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_mem_extraction_insn (extraction_insn *insn,
enum extraction_pattern pattern,
HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
enum machine_mode field_mode)
{
unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
+ bitsize
+ BITS_PER_UNIT - 1);
struct_bits -= struct_bits % BITS_PER_UNIT;
return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
struct_bits, field_mode);
}
#include "gt-optabs.h"
......@@ -323,6 +323,38 @@ extern rtx optab_libfunc (optab optab, enum machine_mode mode);
extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
enum machine_mode mode2);
/* 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. */
enum 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. */
enum machine_mode field_mode;
/* The mode of the field's bit position. This is only important
when the position is variable rather than constant. */
enum machine_mode pos_mode;
};
/* Enumerates the possible extraction_insn operations. */
enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
extern bool get_best_reg_extraction_insn (extraction_insn *,
enum extraction_pattern,
unsigned HOST_WIDE_INT,
enum machine_mode);
extern bool get_best_mem_extraction_insn (extraction_insn *,
enum extraction_pattern,
HOST_WIDE_INT, HOST_WIDE_INT,
enum machine_mode);
extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
rtx operand);
......
......@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "tree-pass.h"
#include "df.h"
#include "insn-codes.h"
#ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD
......@@ -542,6 +543,16 @@ cancel_changes (int num)
num_changes = num;
}
/* Reduce conditional compilation elsewhere. */
#ifndef HAVE_extv
#define HAVE_extv 0
#define CODE_FOR_extv CODE_FOR_nothing
#endif
#ifndef HAVE_extzv
#define HAVE_extzv 0
#define CODE_FOR_extzv CODE_FOR_nothing
#endif
/* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
rtx. */
......@@ -628,19 +639,17 @@ simplify_while_replacing (rtx *loc, rtx to, rtx object,
enum machine_mode is_mode = GET_MODE (XEXP (x, 0));
int pos = INTVAL (XEXP (x, 2));
if (GET_CODE (x) == ZERO_EXTRACT)
if (GET_CODE (x) == ZERO_EXTRACT && HAVE_extzv)
{
enum machine_mode new_mode
= mode_for_extraction (EP_extzv, 1);
if (new_mode != MAX_MACHINE_MODE)
wanted_mode = new_mode;
wanted_mode = insn_data[CODE_FOR_extzv].operand[1].mode;
if (wanted_mode == VOIDmode)
wanted_mode = word_mode;
}
else if (GET_CODE (x) == SIGN_EXTRACT)
else if (GET_CODE (x) == SIGN_EXTRACT && HAVE_extv)
{
enum machine_mode new_mode
= mode_for_extraction (EP_extv, 1);
if (new_mode != MAX_MACHINE_MODE)
wanted_mode = new_mode;
wanted_mode = insn_data[CODE_FOR_extv].operand[1].mode;
if (wanted_mode == VOIDmode)
wanted_mode = word_mode;
}
/* If we have a narrower mode, we can do something. */
......
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