From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22673 invoked by alias); 9 Mar 2011 06:07:31 -0000 Received: (qmail 22664 invoked by uid 22791); 9 Mar 2011 06:07:29 -0000 X-SWARE-Spam-Status: No, hits=-0.9 required=5.0 tests=AWL,BAYES_05,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,KAM_STOCKGEN,RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-iy0-f175.google.com (HELO mail-iy0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Mar 2011 06:07:23 +0000 Received: by iyb26 with SMTP id 26so294257iyb.20 for ; Tue, 08 Mar 2011 22:07:21 -0800 (PST) Received: by 10.42.72.138 with SMTP id o10mr7820832icj.51.1299650841569; Tue, 08 Mar 2011 22:07:21 -0800 (PST) Received: from bubble.grove.modra.org ([115.187.252.19]) by mx.google.com with ESMTPS id xa8sm1099021icb.22.2011.03.08.22.07.18 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 08 Mar 2011 22:07:20 -0800 (PST) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id F2E2B170C1FA; Wed, 9 Mar 2011 16:37:13 +1030 (CST) Date: Wed, 09 Mar 2011 06:07:00 -0000 From: Alan Modra To: David Edelsohn Cc: gcc-patches@gcc.gnu.org Subject: Fix pr48032, powerpc64 -mcmodel=medium invalid ld offset Message-ID: <20110309060713.GQ6275@bubble.grove.modra.org> Mail-Followup-To: David Edelsohn , gcc-patches@gcc.gnu.org References: <20110302073455.GF13094@bubble.grove.modra.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-03/txt/msg00448.txt.bz2 This patch a) Moves the offsettable_ok_by_alignment call from rs6000_emit_move to legitimate_constant_pool_address_p, and b) teaches offsettable_ok_by_alignment how to handle -fsection-anchors addresses, and c) teaches offsettable_ok_by_alignment about other SYMBOL_REF_DECL trees I see there, various constant trees and CONSTRUCTOR. About (a), well, that's just the way I should have written the cmodel=medium optimization in the first place. There is no alignment reason to not create a cmodel=medium address (ie. addis,addi relative to toc pointer), it's just that they do need to be sufficiently aligned to use in a MEM. We want reg=cmodel_medium_losum; mem[reg] whenever we can do so, rather than creating a toc entry, but must not allow the sequence to be combined into mem[cmodel_medium_losum] if cmodel_medium_losum is not offsettable to access all the bytes of mem. Perhaps legitimate_constant_pool_address_p should be renamed. I didn't do that because it already allows the non-constant-pool cmodel=medium addresses, and the name is long enough now. I commented the function instead. (b) is necessary because -fsection-anchors unfortunately loses the real SYMBOL_REF_DECL when substituting anchor+offset into MEMs. The way I imlemented this is why legitimate_constant_pool_address_p needs the MEM mode. I suppose it would be possible to keep the original SYMBOL_REF_DECL around in the rtl by some means or find the decl in the struct object_block info, but both of these options seem like overkill to me. Note that I pass QImode to l_c_p_a_p from rs6000_mode_dependent_address, print_operand_address, and the 'R' constraint to indicate that any cmodel=medium address is permissable. (c) was developed specifically to fix problems found on ibm/gcc-4_5-branch. I'd still like to commit this on mainline even though it seems that mainline creates VAR_DECLs for constants. Bootstrapped and regression tested powerpc64-linux. OK to apply? PR target/48032 * config/rs6000/rs6000.c (offsettable_ok_by_alignment): Do not presume symbol_refs without a symbol_ref_decl are suitably aligned, nor other trees we may see here. Handle anchor symbols. (legitimate_constant_pool_address_p): Comment. Add mode param. Check cmodel=medium addresses. Adjust all calls. (rs6000_emit_move): Don't call offsettable_ok_by_alignment on creating cmodel=medium optimized access to locals. * config/rs6000/constraints.md (R): Pass QImode to legitimate_constant_pool_address_p. * config/rs6000/predicates.md (input_operand): Pass mode to legitimate_constant_pool_address_p. * config/rs6000/rs6000-protos.h (legitimate_constant_pool_address_p): Update prototype. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 170807) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -5768,6 +5768,91 @@ virtual_stack_registers_memory_p (rtx op && regnum <= LAST_VIRTUAL_POINTER_REGISTER); } +/* Return true if memory accesses to OP are known to never straddle + a 32k boundary. */ + +static bool +offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT offset, + enum machine_mode mode) +{ + tree decl, type; + unsigned HOST_WIDE_INT dsize, dalign; + + if (GET_CODE (op) != SYMBOL_REF) + return false; + + decl = SYMBOL_REF_DECL (op); + if (!decl) + { + /* -fsection-anchors loses the original SYMBOL_REF_DECL when + replacing memory addresses with an anchor plus offset. We + could find the decl by rummaging around in the block->objects + VEC for the given offset but that seems like too much work. */ + dalign = 1; + if (SYMBOL_REF_HAS_BLOCK_INFO_P (op) + && SYMBOL_REF_ANCHOR_P (op) + && SYMBOL_REF_BLOCK (op) != NULL) + { + struct object_block *block = SYMBOL_REF_BLOCK (op); + HOST_WIDE_INT lsb, mask; + + /* Given the alignment of the block.. */ + dalign = block->alignment; + mask = dalign / BITS_PER_UNIT - 1; + + /* ..and the combined offset of the anchor and any offset + to this block object.. */ + offset += SYMBOL_REF_BLOCK_OFFSET (op); + lsb = offset & -offset; + + /* ..find how many bits of the alignment we know for the + object. */ + mask &= lsb - 1; + dalign = mask + 1; + } + return dalign >= GET_MODE_SIZE (mode); + } + + if (DECL_P (decl)) + { + if (TREE_CODE (decl) == FUNCTION_DECL) + return true; + + if (!DECL_SIZE_UNIT (decl)) + return false; + + if (!host_integerp (DECL_SIZE_UNIT (decl), 1)) + return false; + + dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1); + if (dsize > 32768) + return false; + + dalign = DECL_ALIGN_UNIT (decl); + return dalign >= dsize; + } + + type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == STRING_CST) + dsize = TREE_STRING_LENGTH (decl); + else if (TYPE_SIZE_UNIT (type) + && host_integerp (TYPE_SIZE_UNIT (type), 1)) + dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1); + else + return false; + if (dsize > 32768) + return false; + + dalign = TYPE_ALIGN (type); + if (CONSTANT_CLASS_P (decl)) + dalign = CONSTANT_ALIGNMENT (decl, dalign); + else + dalign = DATA_ALIGNMENT (decl, dalign); + dalign /= BITS_PER_UNIT; + return dalign >= dsize; +} + static bool constant_pool_expr_p (rtx op) { @@ -5792,8 +5877,12 @@ toc_relative_expr_p (rtx op) && XINT (tocrel_base, 1) == UNSPEC_TOCREL); } +/* Return true if X is a constant pool address, and also for cmodel=medium + if X is a toc-relative address known to be offsettable within MODE. */ + bool -legitimate_constant_pool_address_p (const_rtx x, bool strict) +legitimate_constant_pool_address_p (const_rtx x, enum machine_mode mode, + bool strict) { return (TARGET_TOC && (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM) @@ -5802,7 +5891,12 @@ legitimate_constant_pool_address_p (cons || ((TARGET_MINIMAL_TOC || TARGET_CMODEL != CMODEL_SMALL) && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))) - && toc_relative_expr_p (XEXP (x, 1))); + && toc_relative_expr_p (XEXP (x, 1)) + && (TARGET_CMODEL != CMODEL_MEDIUM + || constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0)) + || mode == QImode + || offsettable_ok_by_alignment (XVECEXP (tocrel_base, 0, 0), + INTVAL (tocrel_offset), mode))); } static bool @@ -5830,7 +5924,7 @@ rs6000_legitimate_offset_address_p (enum return false; if (!reg_offset_addressing_ok_p (mode)) return virtual_stack_registers_memory_p (x); - if (legitimate_constant_pool_address_p (x, strict)) + if (legitimate_constant_pool_address_p (x, mode, strict)) return true; if (GET_CODE (XEXP (x, 1)) != CONST_INT) return false; @@ -6830,7 +6924,8 @@ rs6000_legitimate_address_p (enum machin return 1; if (reg_offset_p && legitimate_small_data_p (mode, x)) return 1; - if (reg_offset_p && legitimate_constant_pool_address_p (x, reg_ok_strict)) + if (reg_offset_p + && legitimate_constant_pool_address_p (x, mode, reg_ok_strict)) return 1; /* If not REG_OK_STRICT (before reload) let pass any stack offset. */ if (! reg_ok_strict @@ -6940,7 +7035,7 @@ rs6000_mode_dependent_address (const_rtx case LO_SUM: /* Anything in the constant pool is sufficiently aligned that all bytes have the same high part address. */ - return !legitimate_constant_pool_address_p (addr, false); + return !legitimate_constant_pool_address_p (addr, QImode, false); /* Auto-increment cases are now treated generically in recog.c. */ case PRE_MODIFY: @@ -7304,53 +7399,21 @@ rs6000_eliminate_indexed_memrefs (rtx op if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) != REG - && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0), false)) + && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0), + GET_MODE (operands[0]), false)) operands[0] = replace_equiv_address (operands[0], copy_addr_to_reg (XEXP (operands[0], 0))); if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) != REG - && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0), false)) + && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0), + GET_MODE (operands[1]), false)) operands[1] = replace_equiv_address (operands[1], copy_addr_to_reg (XEXP (operands[1], 0))); } -/* Return true if memory accesses to DECL are known to never straddle - a 32k boundary. */ - -static bool -offsettable_ok_by_alignment (tree decl) -{ - unsigned HOST_WIDE_INT dsize, dalign; - - /* Presume any compiler generated symbol_ref is suitably aligned. */ - if (!decl) - return true; - - if (TREE_CODE (decl) != VAR_DECL - && TREE_CODE (decl) != PARM_DECL - && TREE_CODE (decl) != RESULT_DECL - && TREE_CODE (decl) != FIELD_DECL) - return true; - - if (!DECL_SIZE_UNIT (decl)) - return false; - - if (!host_integerp (DECL_SIZE_UNIT (decl), 1)) - return false; - - dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1); - if (dsize <= 1) - return true; - if (dsize > 32768) - return false; - - dalign = DECL_ALIGN_UNIT (decl); - return dalign >= dsize; -} - /* Emit a move from SOURCE to DEST in mode MODE. */ void rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) @@ -7672,8 +7735,7 @@ rs6000_emit_move (rtx dest, rtx source, || (TARGET_CMODEL == CMODEL_MEDIUM && GET_CODE (operands[1]) == SYMBOL_REF && !CONSTANT_POOL_ADDRESS_P (operands[1]) - && SYMBOL_REF_LOCAL_P (operands[1]) - && offsettable_ok_by_alignment (SYMBOL_REF_DECL (operands[1])))) + && SYMBOL_REF_LOCAL_P (operands[1]))) { rtx reg = NULL_RTX; if (TARGET_CMODEL != CMODEL_SMALL) @@ -7695,7 +7757,8 @@ rs6000_emit_move (rtx dest, rtx source, || (GET_CODE (operands[0]) == REG && FP_REGNO_P (REGNO (operands[0])))) && GET_CODE (operands[1]) != HIGH - && ! legitimate_constant_pool_address_p (operands[1], false) + && ! legitimate_constant_pool_address_p (operands[1], mode, + false) && ! toc_relative_expr_p (operands[1]) && (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p () @@ -16421,7 +16484,7 @@ print_operand_address (FILE *file, rtx x fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); } #endif - else if (legitimate_constant_pool_address_p (x, true)) + else if (legitimate_constant_pool_address_p (x, QImode, true)) { /* This hack along with a corresponding hack in rs6000_output_addr_const_extra arranges to output addends Index: gcc/config/rs6000/constraints.md =================================================================== --- gcc/config/rs6000/constraints.md (revision 170807) +++ gcc/config/rs6000/constraints.md (working copy) @@ -166,7 +166,7 @@ (define_address_constraint "a" (define_constraint "R" "AIX TOC entry" - (match_test "legitimate_constant_pool_address_p (op, false)")) + (match_test "legitimate_constant_pool_address_p (op, QImode, false)")) ;; General constraints Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 170807) +++ gcc/config/rs6000/predicates.md (working copy) @@ -848,7 +848,7 @@ (define_predicate "input_operand" return 1; /* A SYMBOL_REF referring to the TOC is valid. */ - if (legitimate_constant_pool_address_p (op, false)) + if (legitimate_constant_pool_address_p (op, mode, false)) return 1; /* A constant pool expression (relative to the TOC) is valid */ Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 170807) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -41,7 +41,8 @@ extern int small_data_operand (rtx, enum extern bool toc_relative_expr_p (rtx); extern bool invalid_e500_subreg (rtx, enum machine_mode); extern void validate_condition_mode (enum rtx_code, enum machine_mode); -extern bool legitimate_constant_pool_address_p (const_rtx, bool); +extern bool legitimate_constant_pool_address_p (const_rtx, enum machine_mode, + bool); extern bool legitimate_indirect_address_p (rtx, int); extern bool legitimate_indexed_address_p (rtx, int); extern bool avoiding_indexed_address_p (enum machine_mode); -- Alan Modra Australia Development Lab, IBM