x32 uses a mixture of MEM address modes for the same address space. Some MEMs have SImode addresses, some have DImode. This means that the currently common idiom:
targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)) isn't trustworthy. We have to use the mode of the address if it has one, and only fall back on the above for VOIDmode (CONST_INT) addresses. We actually already have two (identical) functions to calculate such a mode. The patch below puts the function in a more general place and uses it instead of the above for rtl-level stuff. I'm not sure whether what x32 is doing is a good thing, but I like the patch anyway because (a) it removes a duplicated function and (b) it at least abstracts the concept away. Bootstrapped & regression-tested on x86_64-linux-gnu. Also tested to make sure that there were no differences for cc1 .ii files for MIPS n32, o32 and n64. (I used MIPS to get LO_SUM coverage.) OK to install? Richard gcc/ PR middle-end/53249 * dwarf2out.h (get_address_mode): Move declaration to... * rtl.h: ...here. * dwarf2out.c (get_address_mode): Move definition to... * rtlanal.c: ...here. * var-tracking.c (get_address_mode): Delete. * combine.c (find_split_point): Use get_address_mode instead of targetm.addr_space.address_mode. * cselib.c (cselib_record_sets): Likewise. * dse.c (canon_address, record_store): Likewise. * emit-rtl.c (adjust_address_1, offset_address): Likewise. * expr.c (move_by_pieces, emit_block_move_via_loop, store_by_pieces) (store_by_pieces_1, expand_assignment, store_expr, store_constructor) (expand_expr_real_1): Likewise. * ifcvt.c (noce_try_cmove_arith): Likewise. * optabs.c (maybe_legitimize_operand_same_code): Likewise. * reload.c (find_reloads): Likewise. * sched-deps.c (sched_analyze_1, sched_analyze_2): Likewise. * sel-sched-dump.c (debug_mem_addr_value): Likewise. Index: gcc/dwarf2out.h =================================================================== --- gcc/dwarf2out.h 2012-05-06 16:17:20.000000000 +0100 +++ gcc/dwarf2out.h 2012-05-06 16:17:20.316206160 +0100 @@ -228,7 +228,6 @@ typedef struct GTY(()) dw_loc_descr_stru (rtx, enum machine_mode mode, enum machine_mode mem_mode, enum var_init_status); extern bool loc_descr_equal_p (dw_loc_descr_ref, dw_loc_descr_ref); -extern enum machine_mode get_address_mode (rtx mem); extern dw_fde_ref dwarf2out_alloc_current_fde (void); extern unsigned long size_of_locs (dw_loc_descr_ref); Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2012-05-06 16:17:20.000000000 +0100 +++ gcc/rtl.h 2012-05-06 16:17:20.294206160 +0100 @@ -1899,6 +1899,7 @@ typedef struct replace_label_data bool update_label_nuses; } replace_label_data; +extern enum machine_mode get_address_mode (rtx mem); extern int rtx_addr_can_trap_p (const_rtx); extern bool nonzero_address_p (const_rtx); extern int rtx_unstable_p (const_rtx); Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/dwarf2out.c 2012-05-06 16:17:20.315206160 +0100 @@ -10971,17 +10971,6 @@ parameter_ref_descriptor (rtx rtl) return ret; } -/* Helper function to get mode of MEM's address. */ - -enum machine_mode -get_address_mode (rtx mem) -{ - enum machine_mode mode = GET_MODE (XEXP (mem, 0)); - if (mode != VOIDmode) - return mode; - return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); -} - /* The following routine converts the RTL for a variable or parameter (resident in memory) into an equivalent Dwarf representation of a mechanism for getting the address of that same variable onto the top of a Index: gcc/rtlanal.c =================================================================== --- gcc/rtlanal.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/rtlanal.c 2012-05-06 16:17:20.298206160 +0100 @@ -5279,3 +5279,17 @@ low_bitmask_len (enum machine_mode mode, return exact_log2 (m + 1); } + +/* Return the mode of MEM's address. */ + +enum machine_mode +get_address_mode (rtx mem) +{ + enum machine_mode mode; + + gcc_assert (MEM_P (mem)); + mode = GET_MODE (XEXP (mem, 0)); + if (mode != VOIDmode) + return mode; + return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); +} Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/var-tracking.c 2012-05-06 16:17:20.306206160 +0100 @@ -4909,17 +4909,6 @@ find_use_val (rtx x, enum machine_mode m return NULL; } -/* Helper function to get mode of MEM's address. */ - -static inline enum machine_mode -get_address_mode (rtx mem) -{ - enum machine_mode mode = GET_MODE (XEXP (mem, 0)); - if (mode != VOIDmode) - return mode; - return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); -} - /* Replace all registers and addresses in an expression with VALUE expressions that map back to them, unless the expression is a register. If no mapping is or can be performed, returns NULL. */ Index: gcc/combine.c =================================================================== --- gcc/combine.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/combine.c 2012-05-06 16:17:20.322206160 +0100 @@ -4611,8 +4611,7 @@ find_split_point (rtx *loc, rtx insn, bo if (GET_CODE (XEXP (x, 0)) == CONST || GET_CODE (XEXP (x, 0)) == SYMBOL_REF) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x)); + enum machine_mode address_mode = get_address_mode (x); SUBST (XEXP (x, 0), gen_rtx_LO_SUM (address_mode, Index: gcc/cselib.c =================================================================== --- gcc/cselib.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/cselib.c 2012-05-06 16:17:20.300206160 +0100 @@ -2524,8 +2524,7 @@ cselib_record_sets (rtx insn) sets[i].src_elt = cselib_lookup (src, GET_MODE (dest), 1, VOIDmode); if (MEM_P (dest)) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest)); + enum machine_mode address_mode = get_address_mode (dest); sets[i].dest_addr_elt = cselib_lookup (XEXP (dest, 0), address_mode, 1, Index: gcc/dse.c =================================================================== --- gcc/dse.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/dse.c 2012-05-06 16:17:20.303206160 +0100 @@ -1146,8 +1146,7 @@ canon_address (rtx mem, HOST_WIDE_INT *offset, cselib_val **base) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); + enum machine_mode address_mode = get_address_mode (mem); rtx mem_address = XEXP (mem, 0); rtx expanded_address, address; int expanded; @@ -1392,7 +1391,6 @@ record_store (rtx body, bb_info_t bb_inf cselib_val *base = NULL; insn_info_t ptr, last, redundant_reason; bool store_is_unused; - enum machine_mode address_mode; if (GET_CODE (body) != SET && GET_CODE (body) != CLOBBER) return 0; @@ -1455,8 +1453,6 @@ record_store (rtx body, bb_info_t bb_inf return 0; } - address_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); - if (GET_MODE (mem) == BLKmode) width = MEM_SIZE (mem); else @@ -1564,7 +1560,7 @@ record_store (rtx body, bb_info_t bb_inf mem_addr = group->canon_base_addr; } if (offset) - mem_addr = plus_constant (address_mode, mem_addr, offset); + mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } while (ptr) @@ -2181,11 +2177,7 @@ check_mem_read_rtx (rtx *loc, void *data mem_addr = group->canon_base_addr; } if (offset) - { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); - mem_addr = plus_constant (address_mode, mem_addr, offset); - } + mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } /* We ignore the clobbers in store_info. The is mildly aggressive, Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/emit-rtl.c 2012-05-06 16:17:20.326206159 +0100 @@ -2092,7 +2092,7 @@ adjust_address_1 (rtx memref, enum machi /* Convert a possibly large offset to a signed value within the range of the target address space. */ - address_mode = targetm.addr_space.address_mode (attrs.addrspace); + address_mode = get_address_mode (memref); pbits = GET_MODE_BITSIZE (address_mode); if (HOST_BITS_PER_WIDE_INT > pbits) { @@ -2179,7 +2179,7 @@ offset_address (rtx memref, rtx offset, struct mem_attrs attrs, *defattrs; attrs = *get_mem_attrs (memref); - address_mode = targetm.addr_space.address_mode (attrs.addrspace); + address_mode = get_address_mode (memref); new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset); /* At this point we don't know _why_ the address is invalid. It Index: gcc/expr.c =================================================================== --- gcc/expr.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/expr.c 2012-05-06 16:17:20.329206159 +0100 @@ -867,8 +867,8 @@ move_by_pieces (rtx to, rtx from, unsign unsigned int align, int endp) { struct move_by_pieces_d data; - enum machine_mode to_addr_mode, from_addr_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (from)); + enum machine_mode to_addr_mode; + enum machine_mode from_addr_mode = get_address_mode (from); rtx to_addr, from_addr = XEXP (from, 0); unsigned int max_size = MOVE_MAX_PIECES + 1; enum insn_code icode; @@ -879,7 +879,7 @@ move_by_pieces (rtx to, rtx from, unsign data.from_addr = from_addr; if (to) { - to_addr_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to)); + to_addr_mode = get_address_mode (to); to_addr = XEXP (to, 0); data.to = to; data.autinc_to @@ -1434,10 +1434,8 @@ emit_block_move_via_loop (rtx x, rtx y, unsigned int align ATTRIBUTE_UNUSED) { rtx cmp_label, top_label, iter, x_addr, y_addr, tmp; - enum machine_mode x_addr_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x)); - enum machine_mode y_addr_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (y)); + enum machine_mode x_addr_mode = get_address_mode (x); + enum machine_mode y_addr_mode = get_address_mode (y); enum machine_mode iter_mode; iter_mode = GET_MODE (size); @@ -2464,8 +2462,7 @@ store_by_pieces (rtx to, unsigned HOST_W rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode), void *constfundata, unsigned int align, bool memsetp, int endp) { - enum machine_mode to_addr_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to)); + enum machine_mode to_addr_mode = get_address_mode (to); struct store_by_pieces_d data; if (len == 0) @@ -2551,8 +2548,7 @@ clear_by_pieces_1 (void *data ATTRIBUTE_ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED, unsigned int align ATTRIBUTE_UNUSED) { - enum machine_mode to_addr_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (data->to)); + enum machine_mode to_addr_mode = get_address_mode (data->to); rtx to_addr = XEXP (data->to, 0); unsigned int max_size = STORE_MAX_PIECES + 1; enum insn_code icode; @@ -4707,8 +4703,7 @@ expand_assignment (tree to, tree from, b } offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM); - address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to_rtx)); + address_mode = get_address_mode (to_rtx); if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); @@ -5247,8 +5242,7 @@ store_expr (tree exp, rtx target, int ca { enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (MEM_ADDR_SPACE (target)); - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (target)); + enum machine_mode address_mode = get_address_mode (target); /* Compute the size of the data to copy from the string. */ tree copy_size @@ -5816,8 +5810,7 @@ store_constructor (tree exp, rtx target, offset_rtx = expand_normal (offset); gcc_assert (MEM_P (to_rtx)); - address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to_rtx)); + address_mode = get_address_mode (to_rtx); if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); @@ -9937,8 +9930,7 @@ expand_expr_real_1 (tree exp, rtx target gcc_assert (MEM_P (op0)); - address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (op0)); + address_mode = get_address_mode (op0); if (GET_MODE (offset_rtx) != address_mode) offset_rtx = convert_to_mode (address_mode, offset_rtx, 0); Index: gcc/ifcvt.c =================================================================== --- gcc/ifcvt.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/ifcvt.c 2012-05-06 16:17:20.295206160 +0100 @@ -1520,8 +1520,7 @@ noce_try_cmove_arith (struct noce_if_inf && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b) && if_info->branch_cost >= 5) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (a)); + enum machine_mode address_mode = get_address_mode (a); a = XEXP (a, 0); b = XEXP (b, 0); Index: gcc/optabs.c =================================================================== --- gcc/optabs.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/optabs.c 2012-05-06 16:17:20.332206159 +0100 @@ -8253,7 +8253,7 @@ maybe_legitimize_operand_same_code (enum enum machine_mode mode; last = get_last_insn (); - mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); + mode = get_address_mode (mem); mem = replace_equiv_address (mem, copy_to_mode_reg (mode, addr)); if (insn_operand_matches (icode, opno, mem)) { Index: gcc/reload.c =================================================================== --- gcc/reload.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/reload.c 2012-05-06 16:17:20.334206159 +0100 @@ -3993,10 +3993,8 @@ find_reloads (rtx insn, int replace, int as would have been done by find_reloads_address. */ addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]); enum machine_mode address_mode; - address_mode = GET_MODE (XEXP (recog_data.operand[i], 0)); - if (address_mode == VOIDmode) - address_mode = targetm.addr_space.address_mode (as); + address_mode = get_address_mode (recog_data.operand[i]); operand_reloadnum[i] = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX, &XEXP (recog_data.operand[i], 0), (rtx*) 0, Index: gcc/sched-deps.c =================================================================== --- gcc/sched-deps.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/sched-deps.c 2012-05-06 16:17:20.299206160 +0100 @@ -2445,8 +2445,7 @@ sched_analyze_1 (struct deps_desc *deps, if (sched_deps_info->use_cselib) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest)); + enum machine_mode address_mode = get_address_mode (dest); t = shallow_copy_rtx (dest); cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1, @@ -2607,8 +2606,7 @@ sched_analyze_2 (struct deps_desc *deps, if (sched_deps_info->use_cselib) { - enum machine_mode address_mode - = targetm.addr_space.address_mode (MEM_ADDR_SPACE (t)); + enum machine_mode address_mode = get_address_mode (t); t = shallow_copy_rtx (t); cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1, Index: gcc/sel-sched-dump.c =================================================================== --- gcc/sel-sched-dump.c 2012-05-06 16:17:20.000000000 +0100 +++ gcc/sel-sched-dump.c 2012-05-06 16:17:20.316206160 +0100 @@ -957,7 +957,7 @@ debug_mem_addr_value (rtx x) enum machine_mode address_mode; gcc_assert (MEM_P (x)); - address_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x)); + address_mode = get_address_mode (x); t = shallow_copy_rtx (x); if (cselib_lookup (XEXP (t, 0), address_mode, 0, GET_MODE (t)))