From patchwork Wed Jul 13 17:48:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 104570 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B5B95B6F18 for ; Thu, 14 Jul 2011 03:49:02 +1000 (EST) Received: (qmail 13167 invoked by alias); 13 Jul 2011 17:48:59 -0000 Received: (qmail 13156 invoked by uid 22791); 13 Jul 2011 17:48:58 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-qy0-f175.google.com (HELO mail-qy0-f175.google.com) (209.85.216.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 13 Jul 2011 17:48:36 +0000 Received: by qyk30 with SMTP id 30so442460qyk.20 for ; Wed, 13 Jul 2011 10:48:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.61.94 with SMTP id s30mr1214081qch.86.1310579315760; Wed, 13 Jul 2011 10:48:35 -0700 (PDT) Received: by 10.229.71.157 with HTTP; Wed, 13 Jul 2011 10:48:35 -0700 (PDT) In-Reply-To: References: <4E18C5BE.6020809@gnu.org> <4E1AD86A.8000800@gnu.org> <4E1DC42D.1010307@gnu.org> Date: Wed, 13 Jul 2011 10:48:35 -0700 Message-ID: Subject: Re: PING: PATCH [4/n]: Prepare x32: Permute the conversion and addition if one operand is a constant From: "H.J. Lu" To: Paolo Bonzini Cc: GCC Patches X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On Wed, Jul 13, 2011 at 9:54 AM, Paolo Bonzini wrote: >>>> Why?  Certainly Y = 8 has 31-bit (or less) precision.  So it has the same >>>> representation in SImode and DImode, and the test above on XEXP (x, 1) >>>> succeeds. >>> >>> And then we permute conversion and addition, which leads to the issue you >>> raised above.  In another word, the current code permutes conversion >>> and addition. >> >> No, only if we have ptr_extend. > > Oops, hit send too early, I understand now what you mean.  But even > more so, let's make sure x32 is done right so that perhaps we can > remove the bogus test on XEXP (x, 1) for other Pmode != ptr_mode > targets, non-ptr_extend.  Then we can worry perhaps of > POINTERS_EXTEND_UNSIGNED < 0. > Here is the patch. OK for trunk? Thanks. diff --git a/gcc/explow.c b/gcc/explow.c index 3c692f4..8551fe8 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -320,8 +320,10 @@ break_out_memory_refs (rtx x) arithmetic insns can be used. */ rtx -convert_memory_address_addr_space (enum machine_mode to_mode ATTRIBUTE_UNUSED, - rtx x, addr_space_t as ATTRIBUTE_UNUSED) +convert_memory_address_addr_space_1 (enum machine_mode to_mode ATTRIBUTE_UNUSED, + rtx x, addr_space_t as ATTRIBUTE_UNUSED, + bool no_emit ATTRIBUTE_UNUSED, + bool ignore_address_wrap_around ATTRIBUTE_UNUSED) { #ifndef POINTERS_EXTEND_UNSIGNED gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode); @@ -377,28 +379,28 @@ convert_memory_address_addr_space (enum machine_mode to_mode ATTRIBUTE_UNUSED, break; case CONST: - return gen_rtx_CONST (to_mode, - convert_memory_address_addr_space - (to_mode, XEXP (x, 0), as)); + temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0), + as, no_emit, + ignore_address_wrap_around); + return temp ? gen_rtx_CONST (to_mode, temp) : temp; break; case PLUS: case MULT: - /* For addition we can safely permute the conversion and addition - operation if one operand is a constant and converting the constant - does not change it or if one operand is a constant and we are - using a ptr_extend instruction (POINTERS_EXTEND_UNSIGNED < 0). - We can always safely permute them if we are making the address - narrower. */ + /* For addition, we can safely permute the conversion and addition + operation if one operand is a constant and we are using a + ptr_extend instruction (POINTERS_EXTEND_UNSIGNED < 0) or address + wrap-around is ignored. We can always safely permute them if + we are making the address narrower. */ if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode) || (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)) - && (XEXP (x, 1) == convert_memory_address_addr_space - (to_mode, XEXP (x, 1), as) - || POINTERS_EXTEND_UNSIGNED < 0))) + && (POINTERS_EXTEND_UNSIGNED < 0 + || ignore_address_wrap_around))) return gen_rtx_fmt_ee (GET_CODE (x), to_mode, - convert_memory_address_addr_space - (to_mode, XEXP (x, 0), as), + convert_memory_address_addr_space_1 + (to_mode, XEXP (x, 0), as, no_emit, + ignore_address_wrap_around), XEXP (x, 1)); break; @@ -406,10 +408,17 @@ convert_memory_address_addr_space (enum machine_mode to_mode ATTRIBUTE_UNUSED, break; } - return convert_modes (to_mode, from_mode, - x, POINTERS_EXTEND_UNSIGNED); + return convert_modes_1 (to_mode, from_mode, x, + POINTERS_EXTEND_UNSIGNED, no_emit); #endif /* defined(POINTERS_EXTEND_UNSIGNED) */ } + +rtx +convert_memory_address_addr_space (enum machine_mode to_mode, + rtx x, addr_space_t as) +{ + return convert_memory_address_addr_space_1 (to_mode, x, as, false, true); +} /* Return something equivalent to X but valid as a memory address for something of mode MODE in the named address space AS. When X is not itself valid, diff --git a/gcc/expr.c b/gcc/expr.c index 77039e8..e42ab04 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -693,13 +693,16 @@ convert_to_mode (enum machine_mode mode, rtx x, int unsignedp) Both modes may be floating, or both integer. UNSIGNEDP is nonzero if X is an unsigned value. + If NO_EMIT is true, don't emit any instructions. + This can be done by referring to a part of X in place or by copying to a new temporary with conversion. You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode. */ rtx -convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int unsignedp) +convert_modes_1 (enum machine_mode mode, enum machine_mode oldmode, + rtx x, int unsignedp, bool no_emit) { rtx temp; @@ -709,7 +712,12 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x) && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode) && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp) - x = gen_lowpart (mode, x); + { + if (no_emit) + x = rtl_hooks.gen_lowpart_no_emit (mode, x); + else + x = gen_lowpart (mode, x); + } if (GET_MODE (x) != VOIDmode) oldmode = GET_MODE (x); @@ -773,7 +781,10 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns return gen_int_mode (val, mode); } - return gen_lowpart (mode, x); + if (no_emit) + return rtl_hooks.gen_lowpart_no_emit (mode, x); + else + return gen_lowpart (mode, x); } /* Converting from integer constant into mode is always equivalent to an @@ -784,10 +795,20 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns return simplify_gen_subreg (mode, x, oldmode, 0); } + if (no_emit) + return NULL_RTX; + temp = gen_reg_rtx (mode); convert_move (temp, x, unsignedp); return temp; } + +rtx +convert_modes (enum machine_mode mode, enum machine_mode oldmode, + rtx x, int unsignedp) +{ + return convert_modes_1 (mode, oldmode, x, unsignedp, false); +} /* Return the largest alignment we can use for doing a move (or store) of MAX_PIECES. ALIGN is the largest alignment we could use. */ diff --git a/gcc/expr.h b/gcc/expr.h index cb4050d..2ac9788 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -267,6 +267,8 @@ extern rtx convert_to_mode (enum machine_mode, rtx, int); /* Convert an rtx to MODE from OLDMODE and return the result. */ extern rtx convert_modes (enum machine_mode, enum machine_mode, rtx, int); +extern rtx convert_modes_1 (enum machine_mode, enum machine_mode, rtx, + int, bool); /* Emit code to move a block Y to a block X. */ diff --git a/gcc/rtl.h b/gcc/rtl.h index e3ceecd..1497d50 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1638,8 +1638,14 @@ extern int byte_lowpart_offset (enum machine_mode, enum machine_mode); extern rtx make_safe_from (rtx, rtx); extern rtx convert_memory_address_addr_space (enum machine_mode, rtx, addr_space_t); +extern rtx convert_memory_address_addr_space_1 (enum machine_mode, rtx, + addr_space_t, bool, bool); #define convert_memory_address(to_mode,x) \ convert_memory_address_addr_space ((to_mode), (x), ADDR_SPACE_GENERIC) +#define convert_memory_address_1(to_mode,x,no_emit,ignore_address_wrap_around) \ + convert_memory_address_addr_space_1 ((to_mode), (x), \ + ADDR_SPACE_GENERIC, (no_emit), \ + (ignore_address_wrap_around)) extern const char *get_insn_name (int); extern rtx get_last_insn_anywhere (void); extern rtx get_first_nonnote_insn (void); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 82b818b..c62aab1 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1150,7 +1150,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) && REG_P (SUBREG_REG (op)) && REG_POINTER (SUBREG_REG (op)) && GET_MODE (SUBREG_REG (op)) == Pmode))) - return convert_memory_address (Pmode, op); + return convert_memory_address_1 (Pmode, op, true, false); #endif break; @@ -1243,7 +1243,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) && REG_P (SUBREG_REG (op)) && REG_POINTER (SUBREG_REG (op)) && GET_MODE (SUBREG_REG (op)) == Pmode))) - return convert_memory_address (Pmode, op); + return convert_memory_address_1 (Pmode, op, true, false); #endif break;