From patchwork Mon Aug 2 20:20:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60598 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 26B35B6EFE for ; Tue, 3 Aug 2010 06:20:50 +1000 (EST) Received: (qmail 20679 invoked by alias); 2 Aug 2010 20:20:47 -0000 Received: (qmail 20662 invoked by uid 22791); 2 Aug 2010 20:20:44 -0000 X-SWARE-Spam-Status: No, hits=-3.8 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 02 Aug 2010 20:20:39 +0000 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 128EA8726A for ; Mon, 2 Aug 2010 22:20:37 +0200 (CEST) Date: Mon, 2 Aug 2010 22:20:36 +0200 From: Martin Jambor To: GCC Patches Subject: [RFC PATCH] Remove call to build_ref_for_offset in IPA-SRA Message-ID: <20100802202036.GC18246@virgil.arch.suse.de> Mail-Followup-To: GCC Patches MIME-Version: 1.0 Content-Disposition: inline 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-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, the following is another patch in the series that eventually should re-implement build_ref_for_offset. It basically re-implements it in the IPA-SRA user of the function, I might eventually decide to use the new implementation of the function instead but I fairly like it separate because this (current) user of the function 1) always gets offsets aligned to bytes and 2) it can be fed pointers, unlike all others. Anyway, the problem with this patch is of course the hunk in expr.c. However, without it I get ICEs when compiling testcase g++.dg/torture/pr36445.C on x86_64-linux even though I believe I produce correct gimple. As far as I understand the code, if the V_C_E path is not taken and we try to build and expand a BIT_FIELD_REF, I get something that is not BLKmode because its argument is not and this is not expected by emit_block_move which attempts to use it. I am not sure what exactly and exactly under what circumstances needs to behave differently. I intend to go back to this problem but I am new to the code, and thus I would appreciate any help with that. Otherwise the patch bootstraps and tests fine. Thanks, Martin 2010-07-28 Martin Jambor * ipa-prop.c (ipa_modify_call_arguments): Build MEM_REF instead of calling build_ref_for_offset. * expr.c (expand_expr_real_1): When expanding MEM_REF, use V_C_E also when sizes don't match but expected mode is BLKmode. * testsuite/g++.dg/torture/pr34850.C: Remove expected warning. Index: mine/gcc/ipa-prop.c =================================================================== --- mine.orig/gcc/ipa-prop.c +++ mine/gcc/ipa-prop.c @@ -2149,40 +2149,63 @@ ipa_modify_call_arguments (struct cgraph } else if (!adj->remove_param) { - tree expr, orig_expr; - bool allow_ptr, repl_found; + tree expr, base, off; + location_t loc; - orig_expr = expr = gimple_call_arg (stmt, adj->base_index); - if (TREE_CODE (expr) == ADDR_EXPR) - { - allow_ptr = false; - expr = TREE_OPERAND (expr, 0); - } - else - allow_ptr = true; + gcc_checking_assert (adj->offset % BITS_PER_UNIT == 0); + base = gimple_call_arg (stmt, adj->base_index); + loc = EXPR_LOCATION (base); - repl_found = build_ref_for_offset (&expr, TREE_TYPE (expr), - adj->offset, adj->type, - allow_ptr); - if (repl_found) + if ((TREE_CODE (base) == ADDR_EXPR + && DECL_P (TREE_OPERAND (base, 0))) + || (TREE_CODE (base) != ADDR_EXPR + && POINTER_TYPE_P (TREE_TYPE (base)))) + off = build_int_cst (TREE_TYPE (base), adj->offset / BITS_PER_UNIT); + else { - if (adj->by_ref) - expr = build_fold_addr_expr (expr); + HOST_WIDE_INT base_offset; + tree prev_base; + + if (TREE_CODE (base) == ADDR_EXPR) + base = TREE_OPERAND (base, 0); + prev_base = base; + base = get_addr_base_and_unit_offset (base, &base_offset); + if (!base) + { + base = build_fold_addr_expr (prev_base); + off = build_int_cst (TREE_TYPE (base), + adj->offset / BITS_PER_UNIT); + } + else if (TREE_CODE (base) == MEM_REF) + { + off = build_int_cst (TREE_TYPE (TREE_OPERAND (base,1)), + base_offset + + adj->offset / BITS_PER_UNIT); + off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), + off, 0); + base = TREE_OPERAND (base, 0); + } + else + { + off = build_int_cst (build_pointer_type (TREE_TYPE (base)), + base_offset + + adj->offset / BITS_PER_UNIT); + base = build_fold_addr_expr (base); + } } - else + + expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off); + if (adj->by_ref) + expr = build_fold_addr_expr (expr); + + /* !!! Remove after testing */ + if (dump_file) { - tree ptrtype = build_pointer_type (adj->type); - expr = orig_expr; - if (!POINTER_TYPE_P (TREE_TYPE (expr))) - expr = build_fold_addr_expr (expr); - if (!useless_type_conversion_p (ptrtype, TREE_TYPE (expr))) - expr = fold_convert (ptrtype, expr); - expr = fold_build2 (POINTER_PLUS_EXPR, ptrtype, expr, - build_int_cst (sizetype, - adj->offset / BITS_PER_UNIT)); - if (!adj->by_ref) - expr = fold_build1 (INDIRECT_REF, adj->type, expr); + fprintf (dump_file, "Built MEM_REF: "); + print_generic_expr (dump_file, expr, 0); + fprintf (dump_file, "\n"); } + expr = force_gimple_operand_gsi (&gsi, expr, adj->by_ref || is_gimple_reg_type (adj->type), Index: mine/gcc/expr.c =================================================================== --- mine.orig/gcc/expr.c +++ mine/gcc/expr.c @@ -8709,8 +8709,11 @@ expand_expr_real_1 (tree exp, rtx target tree bftype; if (offset == 0 && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) - && (GET_MODE_BITSIZE (DECL_MODE (base)) - == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))) + && ((GET_MODE_BITSIZE (DECL_MODE (base)) + == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))) + || (TYPE_MODE (TREE_TYPE (exp)) == BLKmode + && (GET_MODE_BITSIZE (DECL_MODE (base)) + >= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))) return expand_expr (build1 (VIEW_CONVERT_EXPR, TREE_TYPE (exp), base), target, tmode, modifier); Index: mine/gcc/testsuite/g++.dg/torture/pr34850.C =================================================================== --- mine.orig/gcc/testsuite/g++.dg/torture/pr34850.C +++ mine/gcc/testsuite/g++.dg/torture/pr34850.C @@ -11,7 +11,7 @@ extern "C" { extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__, __artificial__)) void * memset (void *__dest, int __ch, size_t __len) throw () { if (__builtin_constant_p (__len) && __len == 0) - __warn_memset_zero_len (); /* { dg-warning "" } */ + __warn_memset_zero_len (); } } inline void clear_mem(void* ptr, u32bit n) {