/* Memory address lowering and addressing mode selection.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions
that directly map to addressing modes of the target. */
if (base)
{
if (*addr)
- *addr = gen_rtx_PLUS (Pmode, *addr, base);
+ *addr = simplify_gen_binary (PLUS, Pmode, base, *addr);
else
*addr = base;
}
act_elem = symbol;
if (offset)
{
- act_elem = gen_rtx_CONST (Pmode,
- gen_rtx_PLUS (Pmode, act_elem, offset));
+ act_elem = gen_rtx_PLUS (Pmode, act_elem, offset);
+
if (offset_p)
- *offset_p = &XEXP (XEXP (act_elem, 0), 1);
+ *offset_p = &XEXP (act_elem, 1);
+
+ if (GET_CODE (symbol) == SYMBOL_REF
+ || GET_CODE (symbol) == LABEL_REF
+ || GET_CODE (symbol) == CONST)
+ act_elem = gen_rtx_CONST (Pmode, act_elem);
}
if (*addr)
if (addr_off)
{
- addr = fold_convert (type, addr_off);
if (addr_base)
- addr = fold_build2 (PLUS_EXPR, type, addr_base, addr);
+ addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off);
+ else
+ addr = fold_convert (type, addr_off);
}
else if (addr_base)
addr = addr_base;
if (!parts->index)
{
- parts->index = elt;
+ parts->index = fold_convert (sizetype, elt);
return;
}
/* Add ELT to base. */
type = TREE_TYPE (parts->base);
- parts->base = fold_build2 (PLUS_EXPR, type,
+ parts->base = fold_build2 (POINTER_PLUS_EXPR, type,
parts->base,
- fold_convert (type, elt));
+ fold_convert (sizetype, elt));
}
/* Finds the most expensive multiplication in ADDR that can be
j++;
continue;
}
-
+
elt = fold_convert (sizetype, addr->elts[i].val);
if (mult_elt)
mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
{
if (parts->base)
parts->base = force_gimple_operand_bsi (bsi, parts->base,
- true, NULL_TREE);
+ true, NULL_TREE,
+ true, BSI_SAME_STMT);
if (parts->index)
parts->index = force_gimple_operand_bsi (bsi, parts->index,
- true, NULL_TREE);
+ true, NULL_TREE,
+ true, BSI_SAME_STMT);
}
/* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
create_mem_ref (block_stmt_iterator *bsi, tree type, aff_tree *addr)
{
tree mem_ref, tmp;
- tree addr_type = build_pointer_type (type), atype;
+ tree atype;
struct mem_address parts;
addr_to_parts (addr, &parts);
parts.index = force_gimple_operand_bsi (bsi,
fold_build2 (MULT_EXPR, sizetype,
parts.index, parts.step),
- true, NULL_TREE);
+ true, NULL_TREE, true, BSI_SAME_STMT);
parts.step = NULL_TREE;
mem_ref = create_mem_ref_raw (type, &parts);
if (parts.symbol)
{
- tmp = fold_convert (addr_type,
- build_addr (parts.symbol, current_function_decl));
+ tmp = build_addr (parts.symbol, current_function_decl);
+ gcc_assert (is_gimple_val (tmp));
/* Add the symbol to base, eventually forcing it to register. */
if (parts.base)
{
+ gcc_assert (useless_type_conversion_p
+ (sizetype, TREE_TYPE (parts.base)));
+
if (parts.index)
- parts.base = force_gimple_operand_bsi (bsi,
- fold_build2 (PLUS_EXPR, addr_type,
- fold_convert (addr_type, parts.base),
+ {
+ atype = TREE_TYPE (tmp);
+ parts.base = force_gimple_operand_bsi (bsi,
+ fold_build2 (PLUS_EXPR, atype,
+ fold_convert (atype, parts.base),
tmp),
- true, NULL_TREE);
+ true, NULL_TREE, true, BSI_SAME_STMT);
+ }
else
{
parts.index = parts.base;
fold_build2 (PLUS_EXPR, atype,
parts.base,
fold_convert (atype, parts.index)),
- true, NULL_TREE);
+ true, NULL_TREE, true, BSI_SAME_STMT);
}
else
parts.base = parts.index;
{
atype = TREE_TYPE (parts.base);
parts.base = force_gimple_operand_bsi (bsi,
- fold_build2 (PLUS_EXPR, atype,
+ fold_build2 (POINTER_PLUS_EXPR, atype,
parts.base,
- fold_convert (atype, parts.offset)),
- true, NULL_TREE);
+ fold_convert (sizetype, parts.offset)),
+ true, NULL_TREE, true, BSI_SAME_STMT);
}
else
parts.base = parts.offset;