Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-ssa-address.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/tree-ssa-address.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/tree-ssa-address.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Memory address lowering and addressing mode selection. - Copyright (C) 2004-2018 Free Software Foundation, Inc. + Copyright (C) 2004-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -259,6 +259,20 @@ ? expand_expr (addr->index, NULL_RTX, pointer_mode, EXPAND_NORMAL) : NULL_RTX); + /* addr->base could be an SSA_NAME that was set to a constant value. The + call to expand_expr may expose that constant. If so, fold the value + into OFF and clear BSE. Otherwise we may later try to pull a mode from + BSE to generate a REG, which won't work with constants because they + are modeless. */ + if (bse && GET_CODE (bse) == CONST_INT) + { + if (off) + off = simplify_gen_binary (PLUS, pointer_mode, bse, off); + else + off = bse; + gcc_assert (GET_CODE (off) == CONST_INT); + bse = NULL_RTX; + } gen_addr_rtx (pointer_mode, sym, bse, idx, st, off, &address, NULL, NULL); if (pointer_mode != address_mode) address = convert_memory_address (address_mode, address); @@ -1127,6 +1141,39 @@ return new_ref; } +/* Return the preferred index scale factor for accessing memory of mode + MEM_MODE in the address space of pointer BASE. Assume that we're + optimizing for speed if SPEED is true and for size otherwise. */ +unsigned int +preferred_mem_scale_factor (tree base, machine_mode mem_mode, + bool speed) +{ + /* For BLKmode, we can't do anything so return 1. */ + if (mem_mode == BLKmode) + return 1; + + struct mem_address parts = {}; + addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base)); + unsigned int fact = GET_MODE_UNIT_SIZE (mem_mode); + + /* Addressing mode "base + index". */ + parts.index = integer_one_node; + parts.base = integer_one_node; + rtx addr = addr_for_mem_ref (&parts, as, false); + unsigned cost = address_cost (addr, mem_mode, as, speed); + + /* Addressing mode "base + index << scale". */ + parts.step = wide_int_to_tree (sizetype, fact); + addr = addr_for_mem_ref (&parts, as, false); + unsigned new_cost = address_cost (addr, mem_mode, as, speed); + + /* Compare the cost of an address with an unscaled index with + a scaled index and return factor if useful. */ + if (new_cost < cost) + return GET_MODE_UNIT_SIZE (mem_mode); + return 1; +} + /* Dump PARTS to FILE. */ extern void dump_mem_address (FILE *, struct mem_address *);