aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2002-09-26 18:23:55 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2002-09-26 18:23:55 +0000
commit1717e19e2fd482bd93a2b3d55afb8b55f351815b (patch)
tree152241aa7a37823990ff2b3d085dc1525ca33140 /gcc/expr.c
parent6cabe79eabc995c20a16ce121cb42d3409b7364c (diff)
downloadgcc-1717e19e2fd482bd93a2b3d55afb8b55f351815b.zip
gcc-1717e19e2fd482bd93a2b3d55afb8b55f351815b.tar.gz
gcc-1717e19e2fd482bd93a2b3d55afb8b55f351815b.tar.bz2
expr.c (expand_expr): Convert A - const to A + (-const) on RTX level, even for unsigned types.
* expr.c (expand_expr) [MINUS_EXPR]: Convert A - const to A + (-const) on RTX level, even for unsigned types. From-SVN: r57543
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 6190866..01c3603 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7804,9 +7804,6 @@ expand_expr (exp, target, tmode, modifier)
return op0;
case PLUS_EXPR:
- /* We come here from MINUS_EXPR when the second operand is a
- constant. */
- plus_expr:
this_optab = ! unsignedp && flag_trapv
&& (GET_MODE_CLASS (mode) == MODE_INT)
? addv_optab : add_optab;
@@ -7916,6 +7913,8 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
+ /* We come here from MINUS_EXPR when the second operand is a
+ constant. */
both_summands:
/* Make sure any term that's a sum with a constant comes last. */
if (GET_CODE (op0) == PLUS
@@ -7985,27 +7984,33 @@ expand_expr (exp, target, tmode, modifier)
else
return gen_rtx_MINUS (mode, op0, op1);
}
- /* Convert A - const to A + (-const). */
- if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
- {
- tree negated = fold (build1 (NEGATE_EXPR, type,
- TREE_OPERAND (exp, 1)));
- if (TREE_UNSIGNED (type) || TREE_OVERFLOW (negated))
- /* If we can't negate the constant in TYPE, leave it alone and
- expand_binop will negate it for us. We used to try to do it
- here in the signed version of TYPE, but that doesn't work
- on POINTER_TYPEs. */;
- else
- {
- exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), negated);
- goto plus_expr;
- }
- }
this_optab = ! unsignedp && flag_trapv
&& (GET_MODE_CLASS(mode) == MODE_INT)
? subv_optab : sub_optab;
- goto binop;
+
+ /* No sense saving up arithmetic to be done
+ if it's all in the wrong mode to form part of an address.
+ And force_operand won't know whether to sign-extend or
+ zero-extend. */
+ if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
+ || mode != ptr_mode)
+ goto binop;
+
+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
+ subtarget = 0;
+
+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
+
+ /* Convert A - const to A + (-const). */
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ op1 = negate_rtx (mode, op1);
+ goto both_summands;
+ }
+
+ goto binop2;
case MULT_EXPR:
/* If first operand is constant, swap them.