* integrate.c (copy_rtx_and_substitute): Use simplify_gen_subreg.
(simplify_subreg): Handle complex types represented as CONCAT.
* recog.c (validate_replace_rtx_1): Properly canonicalize expression
* rtl.h (swap_commutative_operands_p): Declare.
* rtlanal.c (swap_commutative_operands_p): New.
(operand_preference): New static function.
* combine.c (combine_simplify_rtx): Use swap_commutative_operands_p.
(gen_binary): Likewise.
* optabs.c (emit_cmp_and_jump_insns, emit_conditional_move): Likewise.
* simplify-rtx.c (simplify_gen_binary,
simplify_gen_relational): Likewise.
From-SVN: r42224
+Thu May 17 23:19:46 CEST 2001 Jan Hubicka <jh@suse.cz>
+
+ * integrate.c (copy_rtx_and_substitute): Use simplify_gen_subreg.
+ (simplify_subreg): Handle complex types represented as CONCAT.
+
+ * recog.c (validate_replace_rtx_1): Properly canonicalize expression
+ * rtl.h (swap_commutative_operands_p): Declare.
+ * rtlanal.c (swap_commutative_operands_p): New.
+ (operand_preference): New static function.
+
+ * combine.c (combine_simplify_rtx): Use swap_commutative_operands_p.
+ (gen_binary): Likewise.
+ * optabs.c (emit_cmp_and_jump_insns, emit_conditional_move): Likewise.
+ * simplify-rtx.c (simplify_gen_binary,
+ simplify_gen_relational): Likewise.
+
Thu May 17 20:43:36 CEST 2001 Jan Hubicka <jh@suse.cz>
* cse.c (fold_rtx): Use simplify_subreg.
/* If this is a commutative operation, put a constant last and a complex
expression first. We don't need to do this for comparisons here. */
if (GET_RTX_CLASS (code) == 'c'
- && ((CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
- || (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == 'o'
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) != 'o')
- || (GET_CODE (XEXP (x, 0)) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0)))) == 'o'
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) != 'o')))
+ && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
{
temp = XEXP (x, 0);
SUBST (XEXP (x, 0), XEXP (x, 1));
/* Put complex operands first and constants second. */
if (GET_RTX_CLASS (code) == 'c'
- && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
- || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
- || (GET_CODE (op0) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
+ && swap_commutative_operands_p (op0, op1))
return gen_rtx_fmt_ee (code, mode, op1, op0);
/* If we are turning off bits already known off in OP0, we need not do
subreg_lowpart_p (x)
rtx x;
{
- unsigned int offset = 0;
- int difference = (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- - GET_MODE_SIZE (GET_MODE (x)));
-
if (GET_CODE (x) != SUBREG)
return 1;
else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
case SUBREG:
copy = copy_rtx_and_substitute (SUBREG_REG (orig), map, for_lhs);
- /* SUBREG is ordinary, but don't make nested SUBREGs. */
- if (GET_CODE (copy) == SUBREG)
- {
- int final_offset = SUBREG_BYTE (orig) + SUBREG_BYTE (copy);
-
- /* When working with SUBREGs the rule is that the byte
- offset must be a multiple of the SUBREG's mode. */
- final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (orig)));
- final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (orig)));
- return gen_rtx_SUBREG (GET_MODE (orig), SUBREG_REG (copy),
- final_offset);
- }
- else if (GET_CODE (copy) == CONCAT)
- {
- rtx retval = subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1);
- int final_offset;
-
- if (GET_MODE (retval) == GET_MODE (orig))
- return retval;
-
- final_offset = SUBREG_BYTE (orig) %
- GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (orig)));
- final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (orig)));
- final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (orig)));
- return gen_rtx_SUBREG (GET_MODE (orig), retval, final_offset);
- }
- else
- return gen_rtx_SUBREG (GET_MODE (orig), copy,
- SUBREG_BYTE (orig));
+ return simplify_gen_subreg (GET_MODE (orig), copy,
+ GET_MODE (SUBREG_REG (orig)),
+ SUBREG_BYTE (orig));
case ADDRESSOF:
copy = gen_rtx_ADDRESSOF (mode,
rtx op0;
rtx op1;
- if ((CONSTANT_P (x) && ! CONSTANT_P (y))
- || (GET_CODE (x) == CONST_INT && GET_CODE (y) != CONST_INT))
+ if (swap_commutative_operands_p (x, y))
{
/* Swap operands and condition to ensure canonical RTL. */
op0 = y;
{
rtx tem, subtarget, comparison, insn;
enum insn_code icode;
+ enum rtx_code reversed;
/* If one operand is constant, make it the second one. Only do this
if the other operand is not constant as well. */
- if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
- || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+ if (swap_commutative_operands_p (op0, op1))
{
tem = op0;
op0 = op1;
if (cmode == VOIDmode)
cmode = GET_MODE (op0);
- if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
- || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
- && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
- || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_unsafe_math_optimizations))
+ if (swap_commutative_operands_p (op2, op3)
+ && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
+ != UNKNOWN))
{
tem = op2;
op2 = op3;
op3 = tem;
- code = reverse_condition (code);
+ code = reversed;
}
if (mode == VOIDmode)
extern int reg_referenced_between_p PARAMS ((rtx, rtx, rtx));
extern int reg_set_between_p PARAMS ((rtx, rtx, rtx));
extern int regs_set_between_p PARAMS ((rtx, rtx, rtx));
+extern int swap_commutative_operands_p PARAMS ((rtx, rtx));
extern int modified_between_p PARAMS ((rtx, rtx, rtx));
extern int no_labels_between_p PARAMS ((rtx, rtx));
extern int no_jumps_between_p PARAMS ((rtx, rtx));
static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
static int computed_jump_p_1 PARAMS ((rtx));
+static int operand_preference PARAMS ((rtx));
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
return NULL_RTX;
}
+/* Return a value indicating whether OP, an operand of a commutative
+ operation, is preferred as the first or second operand. The higher
+ the value, the stronger the preference for being the first operand.
+ We use negative values to indicate a preference for the first operand
+ and positive values for the second operand. */
+
+static int
+operand_preference (op)
+ rtx op;
+{
+ /* Constants always come the second operand. Prefer "nice" constants. */
+ if (GET_CODE (op) == CONST_INT)
+ return -4;
+ if (GET_CODE (op) == CONST_DOUBLE)
+ return -3;
+ if (CONSTANT_P (op))
+ return -2;
+
+ /* SUBREGs of objects should come second. */
+ if (GET_CODE (op) == SUBREG
+ && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op))) == 'o')
+ return -1;
+
+ /* If only one operand is a `neg', `not',
+ `mult', `plus', or `minus' expression, it will be the first
+ operand. */
+ if (GET_CODE (op) == NEG || GET_CODE (op) == NOT
+ || GET_CODE (op) == MULT || GET_CODE (op) == PLUS
+ || GET_CODE (op) == MINUS)
+ return 2;
+
+ /* Complex expressions should be the first. */
+ if (GET_RTX_CLASS (GET_CODE (op)) == 'o')
+ return 1;
+ return 0;
+}
+
+/* Return 1 iff it is neccesary to swap operands of commutative operation
+ in order to canonicalize expression. */
+
+int
+swap_commutative_operands_p (x, y)
+ rtx x, y;
+{
+ return operand_preference (x) < operand_preference (y);
+}
/* Return 1 if X is an autoincrement side effect and the register is
not the stack pointer. */
/* Put complex operands first and constants second if commutative. */
if (GET_RTX_CLASS (code) == 'c'
- && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
- || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
- || (GET_CODE (op0) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
+ && swap_commutative_operands_p (op0, op1))
tem = op0, op0 = op1, op1 = tem;
/* If this simplifies, do it. */
return tem;
/* Put complex operands first and constants second. */
- if ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
- || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
- || (GET_CODE (op0) == SUBREG
- && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
- && GET_RTX_CLASS (GET_CODE (op1)) != 'o'))
+ if (swap_commutative_operands_p (op0, op1))
tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
return gen_rtx_fmt_ee (code, mode, op0, op1);
|| byte >= GET_MODE_SIZE (innermode))
abort ();
+ if (outermode == innermode && !byte)
+ return op;
+
/* Attempt to simplify constant to non-SUBREG expression. */
if (CONSTANT_P (op))
{
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
+
+ /* Handle complex values represented as CONCAT
+ of real and imaginary part. */
+ if (GET_CODE (op) == CONCAT)
+ {
+ int is_realpart = byte < GET_MODE_UNIT_SIZE (innermode) / 2;
+ rtx part = is_realpart ? XEXP (op, 0) : XEXP (op, 1);
+ unsigned int final_offset;
+
+ final_offset = SUBREG_BYTE (op) % (GET_MODE_UNIT_SIZE (innermode) / 2);
+ return simplify_subreg (outermode, part, GET_MODE (part), final_offset);
+ }
+
return NULL_RTX;
}
/* Make a SUBREG operation or equivalent if it folds. */