aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-10-18 21:34:14 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2001-10-18 17:34:14 -0400
commit0d4903b81e2e5f9371c330a82ddad63af0bb272a (patch)
tree8efd4ef27021837ed8a888f7f93fac0cede0d926 /gcc/expr.c
parenteacecf96651d07155d20c784f4ab8862b57b3a50 (diff)
downloadgcc-0d4903b81e2e5f9371c330a82ddad63af0bb272a.zip
gcc-0d4903b81e2e5f9371c330a82ddad63af0bb272a.tar.gz
gcc-0d4903b81e2e5f9371c330a82ddad63af0bb272a.tar.bz2
emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array.
* emit-rtl.c (gen_reg_rtx): Also reallocate reg_decl array. (offset_address): New function. (free_emit_status): Free regno_decl. (init_emit): Pass proper number of elements to xcalloc. Allocate regno_decl. (mark_emit_status): Mark regno_decl values. * expr.c (highest_pow2_factor): New function. (expand_assigment): Use it and offset_address. Properly handle ptr_mode vs. Pmode in offset calculation. (store_constructor, expand_expr_unaligned): Likewise. (expand_expr, case COMPONENT_EXPR): Likewise. * expr.h (offset_address): New decl. * function.h (struct emit_status): Add regno_decl. (REGNO_DECL): New macro. * final.c (output_asm_name): Move in file and don't conditionalize on flag_print_asm_name. (output_asm_insn): Only call output_asm_name if flag_print_asm_name. Output names of operands, if known. * function.c (assign_parms): Set REGNO_DECL. * integrate.c (integrate_decl_tree): Likewise. * stmt.c (expand_decl): Likewise. * regclass.c (reg_scan_mark_refs): Propagate REGNO_DECL for copies. From-SVN: r46337
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c126
1 files changed, 85 insertions, 41 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index e06d4b1..f486b32 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -164,6 +164,7 @@ static rtx store_field PARAMS ((rtx, HOST_WIDE_INT,
static enum memory_use_mode
get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
static rtx var_rtx PARAMS ((tree));
+static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
static rtx expand_increment PARAMS ((tree, int, int));
static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
@@ -3760,10 +3761,8 @@ expand_assignment (to, from, want_value, suggest_reg)
bitpos = 0;
}
- to_rtx = change_address (to_rtx, VOIDmode,
- gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
- force_reg (ptr_mode,
- offset_rtx)));
+ to_rtx = offset_address (to_rtx, offset_rtx,
+ highest_pow2_factor (offset));
}
if (volatilep)
@@ -3900,8 +3899,8 @@ expand_assignment (to, from, want_value, suggest_reg)
else
{
#ifdef POINTERS_EXTEND_UNSIGNED
- if (TREE_CODE (TREE_TYPE (to)) == REFERENCE_TYPE
- || TREE_CODE (TREE_TYPE (to)) == POINTER_TYPE)
+ if (POINTER_TYPE_P (TREE_TYPE (to))
+ && GET_MODE (to_rtx) != GET_MODE (value))
value = convert_memory_address (GET_MODE (to_rtx), value);
#endif
emit_move_insn (to_rtx, value);
@@ -4648,19 +4647,15 @@ store_constructor (exp, target, align, cleared, size)
abort ();
if (GET_MODE (offset_rtx) != ptr_mode)
- {
+ offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+
#ifdef POINTERS_EXTEND_UNSIGNED
- offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
-#else
- offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+ offset_rtx = convert_memory_address (Pmode, offset_rtx);
#endif
- }
- to_rtx
- = change_address (to_rtx, VOIDmode,
- gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
- force_reg (ptr_mode,
- offset_rtx)));
+ to_rtx = offset_address (to_rtx, offset_rtx,
+ highest_pow2_factor (offset));
+
align = DECL_OFFSET_ALIGN (field);
}
@@ -4820,7 +4815,7 @@ store_constructor (exp, target, align, cleared, size)
{
tree lo_index = TREE_OPERAND (index, 0);
tree hi_index = TREE_OPERAND (index, 1);
- rtx index_r, pos_rtx, addr, hi_r, loop_top, loop_end;
+ rtx index_r, pos_rtx, hi_r, loop_top, loop_end;
struct nesting *loop;
HOST_WIDE_INT lo, hi, count;
tree position;
@@ -4884,8 +4879,9 @@ store_constructor (exp, target, align, cleared, size)
TYPE_SIZE_UNIT (elttype)));
pos_rtx = expand_expr (position, 0, VOIDmode, 0);
- addr = gen_rtx_PLUS (Pmode, XEXP (target, 0), pos_rtx);
- xtarget = change_address (target, mode, addr);
+ xtarget = offset_address (target, pos_rtx,
+ highest_pow2_factor (position));
+ xtarget = adjust_address (xtarget, mode, 0);
if (TREE_CODE (value) == CONSTRUCTOR)
store_constructor (value, xtarget, align, cleared,
bitsize / BITS_PER_UNIT);
@@ -4906,7 +4902,6 @@ store_constructor (exp, target, align, cleared, size)
else if ((index != 0 && ! host_integerp (index, 0))
|| ! host_integerp (TYPE_SIZE (elttype), 1))
{
- rtx pos_rtx, addr;
tree position;
if (index == 0)
@@ -4920,9 +4915,10 @@ store_constructor (exp, target, align, cleared, size)
position = size_binop (MULT_EXPR, index,
convert (ssizetype,
TYPE_SIZE_UNIT (elttype)));
- pos_rtx = expand_expr (position, 0, VOIDmode, 0);
- addr = gen_rtx_PLUS (Pmode, XEXP (target, 0), pos_rtx);
- xtarget = change_address (target, mode, addr);
+ xtarget = offset_address (target,
+ expand_expr (position, 0, VOIDmode, 0),
+ highest_pow2_factor (position));
+ xtarget = adjust_address (xtarget, mode, 0);
store_expr (value, xtarget, 0);
}
else
@@ -5965,6 +5961,62 @@ check_max_integer_computation_mode (exp)
}
#endif
+/* Return the highest power of two that EXP is known to be a multiple of.
+ This is used in updating alignment of MEMs in array references. */
+
+static HOST_WIDE_INT
+highest_pow2_factor (exp)
+ tree exp;
+{
+ HOST_WIDE_INT c0, c1;
+
+ switch (TREE_CODE (exp))
+ {
+ case INTEGER_CST:
+ /* If the integer is expressable in a HOST_WIDE_INT, we can find
+ the lowest bit that's a one. If the result is zero or negative,
+ pessimize by returning 1. This is overly-conservative, but such
+ things should not happen in the offset expressions that we are
+ called with. */
+ if (host_integerp (exp, 0))
+ {
+ c0 = tree_low_cst (exp, 0);
+ return c0 >= 0 ? c0 & -c0 : 1;
+ }
+ break;
+
+ case PLUS_EXPR: case MINUS_EXPR:
+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+ return MIN (c0, c1);
+
+ case MULT_EXPR:
+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+ return c0 * c1;
+
+ case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+ return c0 / c1;
+
+ case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR:
+ case COMPOUND_EXPR: case SAVE_EXPR:
+ return highest_pow2_factor (TREE_OPERAND (exp, 0));
+
+ case COND_EXPR:
+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
+ return MIN (c0, c1);
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
/* Return an object on the placeholder list that matches EXP, a
PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
PLACEHOLDER_EXPR or a pointer type to it. For further information, see
@@ -7018,13 +7070,11 @@ expand_expr (exp, target, tmode, modifier)
abort ();
if (GET_MODE (offset_rtx) != ptr_mode)
- {
+ offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+
#ifdef POINTERS_EXTEND_UNSIGNED
- offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
-#else
- offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+ offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
#endif
- }
/* A constant address in OP0 can have VOIDmode, we must not try
to call force_reg for that case. Avoid that case. */
@@ -7048,10 +7098,8 @@ expand_expr (exp, target, tmode, modifier)
bitpos = 0;
}
- op0 = change_address (op0, VOIDmode,
- gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
- force_reg (ptr_mode,
- offset_rtx)));
+ op0 = offset_address (op0, offset_rtx,
+ highest_pow2_factor (offset));
}
/* Don't forget about volatility even if this is a bitfield. */
@@ -9036,18 +9084,14 @@ expand_expr_unaligned (exp, palign)
abort ();
if (GET_MODE (offset_rtx) != ptr_mode)
- {
+ offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+
#ifdef POINTERS_EXTEND_UNSIGNED
- offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
-#else
- offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+ offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
#endif
- }
- op0 = change_address (op0, VOIDmode,
- gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
- force_reg (ptr_mode,
- offset_rtx)));
+ op0 = offset_address (op0, offset_rtx,
+ highest_pow2_factor (offset));
}
/* Don't forget about volatility even if this is a bitfield. */