/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
This should be 0 if you are generating rtl, such as if you are calling
the functions in optabs.c and expmed.c (most of the time).
This should be 1 if all valid insns need to be recognized,
- such as in regclass.c and final.c and reload.c.
+ such as in reginfo.c and final.c and reload.c.
init_recog and init_recog_no_volatile are responsible for setting this. */
const char *c = constraints[i];
if (c[0] == '%')
c++;
- if (ISDIGIT ((unsigned char) c[0]) && c[1] == '\0')
- c = constraints[c[0] - '0'];
-
- if (! asm_operand_ok (operands[i], c))
+ if (! asm_operand_ok (operands[i], c, constraints))
return 0;
}
if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
break;
}
+ else if (REG_P (changes[i].old)
+ && asm_noperands (PATTERN (object)) > 0
+ && REG_EXPR (changes[i].old) != NULL_TREE
+ && DECL_ASSEMBLER_NAME_SET_P (REG_EXPR (changes[i].old))
+ && DECL_REGISTER (REG_EXPR (changes[i].old)))
+ {
+ /* Don't allow changes of hard register operands to inline
+ assemblies if they have been defined as register asm ("x"). */
+ break;
+ }
else if (insn_invalid_p (object))
{
rtx pat = PATTERN (object);
simplify_gen_binary to try to simplify it.
??? We may want later to remove this, once simplification is
separated from this function. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
+ if (CONST_INT_P (XEXP (x, 1)) && XEXP (x, 1) == to)
validate_change (object, loc,
simplify_gen_binary
(PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
break;
case MINUS:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ if (CONST_INT_P (XEXP (x, 1))
|| GET_CODE (XEXP (x, 1)) == CONST_DOUBLE)
validate_change (object, loc,
simplify_gen_binary
happen, we might just fail in some cases). */
if (MEM_P (XEXP (x, 0))
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && GET_CODE (XEXP (x, 2)) == CONST_INT
+ && CONST_INT_P (XEXP (x, 1))
+ && CONST_INT_P (XEXP (x, 2))
&& !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
&& !MEM_VOLATILE_P (XEXP (x, 0)))
{
simplify_while_replacing (loc, to, object, op0_mode);
}
+/* Try replacing every occurrence of FROM in subexpression LOC of INSN
+ with TO. After all changes have been made, validate by seeing
+ if INSN is still valid. */
+
+int
+validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc)
+{
+ validate_replace_rtx_1 (loc, from, to, insn, true);
+ return apply_change_group ();
+}
+
/* Try replacing every occurrence of FROM in INSN with TO. After all
changes have been made, validate by seeing if INSN is still valid. */
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
return 0;
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
return 0;
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
int
const_int_operand (rtx op, enum machine_mode mode)
{
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
if (mode != VOIDmode
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
return 0;
- return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)
+ return ((GET_CODE (op) == CONST_DOUBLE || CONST_INT_P (op))
&& (mode == VOIDmode || GET_MODE (op) == mode
|| GET_MODE (op) == VOIDmode));
}
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
return 0;
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
if (GET_CODE (op) != PRE_MODIFY
|| GET_CODE (XEXP (op, 1)) != PLUS
|| XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
- || GET_CODE (XEXP (XEXP (op, 1), 1)) != CONST_INT
+ || !CONST_INT_P (XEXP (XEXP (op, 1), 1))
#ifdef STACK_GROWS_DOWNWARD
|| INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
#else
int
memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
win:
return 1;
+#else
+ return targetm.legitimate_address_p (mode, addr, 0);
+#endif
}
/* Return 1 if OP is a valid memory reference with mode MODE,
return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
|| (GET_CODE (XEXP (inner, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT
+ && CONST_INT_P (XEXP (XEXP (inner, 0), 1))
&& INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
&& general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
}
&& general_operand (XEXP (op, 0), Pmode));
}
+/* Return 1 if this is an ordered comparison operator (not including
+ ORDERED and UNORDERED). */
+
+int
+ordered_comparison_operator (rtx op, enum machine_mode mode)
+{
+ if (mode != VOIDmode && GET_MODE (op) != mode)
+ return false;
+ switch (GET_CODE (op))
+ {
+ case EQ:
+ case NE:
+ case LT:
+ case LTU:
+ case LE:
+ case LEU:
+ case GT:
+ case GTU:
+ case GE:
+ case GEU:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Return 1 if this is a comparison operator. This allows the use of
MATCH_OPERATOR to recognize all the branch insns. */
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int
-asm_operand_ok (rtx op, const char *constraint)
+asm_operand_ok (rtx op, const char *constraint, const char **constraints)
{
int result = 0;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- /* For best results, our caller should have given us the
- proper matching constraint, but we can't actually fail
- the check if they didn't. Indicate that results are
- inconclusive. */
- do
- constraint++;
- while (ISDIGIT (*constraint));
- if (! result)
- result = -1;
+ /* If caller provided constraints pointer, look up
+ the maching constraint. Otherwise, our caller should have
+ given us the proper matching constraint, but we can't
+ actually fail the check if they didn't. Indicate that
+ results are inconclusive. */
+ if (constraints)
+ {
+ char *end;
+ unsigned long match;
+
+ match = strtoul (constraint, &end, 10);
+ if (!result)
+ result = asm_operand_ok (op, constraints[match], NULL);
+ constraint = (const char *) end;
+ }
+ else
+ {
+ do
+ constraint++;
+ while (ISDIGIT (*constraint));
+ if (! result)
+ result = -1;
+ }
continue;
case 'p':
break;
case 's':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
break;
break;
case 'n':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
result = 1;
break;
case 'I':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
result = 1;
break;
case 'J':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
result = 1;
break;
case 'K':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
result = 1;
break;
case 'L':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
result = 1;
break;
case 'M':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
result = 1;
break;
case 'N':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
result = 1;
break;
case 'O':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
result = 1;
break;
case 'P':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
result = 1;
break;
break;
case 's':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
break;
break;
case 'n':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
win = 1;
case 'N':
case 'O':
case 'P':
- if (GET_CODE (op) == CONST_INT
+ if (CONST_INT_P (op)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
win = 1;
break;
return NULL_RTX;
}
+/* Forget all currently tracked instructions, only remember current
+ LIVE regset. */
+
+static void
+peep2_reinit_state (regset live)
+{
+ int i;
+
+ /* Indicate that all slots except the last holds invalid data. */
+ for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
+ peep2_insn_data[i].insn = NULL_RTX;
+ peep2_current_count = 0;
+
+ /* Indicate that the last slot contains live_after data. */
+ peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
+ peep2_current = MAX_INSNS_PER_PEEP2;
+
+ COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+}
+
/* Perform the peephole2 optimization pass. */
static void
FOR_EACH_BB_REVERSE (bb)
{
rtl_profile_for_bb (bb);
- /* Indicate that all slots except the last holds invalid data. */
- for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
- peep2_insn_data[i].insn = NULL_RTX;
- peep2_current_count = 0;
-
- /* Indicate that the last slot contains live_after data. */
- peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
- peep2_current = MAX_INSNS_PER_PEEP2;
/* Start up propagation. */
bitmap_copy (live, DF_LR_OUT (bb));
- df_simulate_artificial_refs_at_end (bb, live);
- bitmap_copy (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+ df_simulate_initialize_backwards (bb, live);
+ peep2_reinit_state (live);
for (insn = BB_END (bb); ; insn = prev)
{
&& peep2_insn_data[peep2_current].insn == NULL_RTX)
peep2_current_count++;
peep2_insn_data[peep2_current].insn = insn;
- df_simulate_one_insn (bb, insn, live);
+ df_simulate_one_insn_backwards (bb, insn, live);
COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
if (RTX_FRAME_RELATED_P (insn))
/* If an insn has RTX_FRAME_RELATED_P set, peephole
substitution would lose the
REG_FRAME_RELATED_EXPR that is attached. */
- peep2_current_count = 0;
+ peep2_reinit_state (live);
attempt = NULL;
}
else
peep2_current_count++;
peep2_insn_data[i].insn = x;
df_insn_rescan (x);
- df_simulate_one_insn (bb, x, live);
+ df_simulate_one_insn_backwards (bb, x, live);
bitmap_copy (peep2_insn_data[i].live_before, live);
}
x = PREV_INSN (x);
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
TODO_dump_func | TODO_verify_rtl_sharing /* todo_flags_finish */
}
};
-
-