From patchwork Tue Jul 19 13:13:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 105474 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 A5653B6F7E for ; Tue, 19 Jul 2011 23:14:46 +1000 (EST) Received: (qmail 24016 invoked by alias); 19 Jul 2011 13:14:44 -0000 Received: (qmail 24002 invoked by uid 22791); 19 Jul 2011 13:14:41 -0000 X-SWARE-Spam-Status: No, hits=-7.0 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CB, TW_TM X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 19 Jul 2011 13:14:02 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p6JDE1qr021115 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 19 Jul 2011 09:14:01 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p6JDE1wm030888 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 19 Jul 2011 09:14:01 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p6JDE0IV013008 for ; Tue, 19 Jul 2011 15:14:00 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p6JDE08c013007 for gcc-patches@gcc.gnu.org; Tue, 19 Jul 2011 15:14:00 +0200 Date: Tue, 19 Jul 2011 15:13:59 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: 11 backports from the trunk to 4.5 branch Message-ID: <20110719131359.GC2687@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) 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! I've bootstrapped/regtested on 4.5 branch on x86_64-linux and i686-linux following patches and committed to the branch. Will backport those that are needed for 4.4 also soon. Jakub 2011-07-19 Jakub Jelinek Backport from mainline 2011-05-18 Jakub Jelinek PR tree-optimization/49039 * tree-vrp.c (extract_range_from_binary_expr): For MIN_EXPR <~[a, b], ~[c, d]> and MAX_EXPR <~[a, b], ~[c, d]> return ~[MAX_EXPR , MIN_EXPR ]. * gcc.c-torture/execute/pr49039.c: New test. * gcc.dg/tree-ssa/pr49039.c: New test. * g++.dg/torture/pr49039.C: New test. 2011-07-19 Jakub Jelinek Backport from mainline 2011-05-23 Jakub Jelinek PR middle-end/48973 * expr.c (expand_expr_real_2) : If do_store_flag failed and the comparison has a single bit signed type, use constm1_rtx instead of const1_rtx for true value. (do_store_flag): If ops->type is single bit signed type, disable signel bit test optimization and pass -1 instead of 1 as last parameter to emit_store_flag_force. * gcc.c-torture/execute/pr48973-1.c: New test. * gcc.c-torture/execute/pr48973-2.c: New test. --- gcc/expr.c (revision 174059) +++ gcc/expr.c (revision 174060) @@ -8105,7 +8105,10 @@ expand_expr_real_2 (sepops ops, rtx targ op1 = gen_label_rtx (); jumpifnot_1 (code, treeop0, treeop1, op1, -1); - emit_move_insn (target, const1_rtx); + if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) + emit_move_insn (target, constm1_rtx); + else + emit_move_insn (target, const1_rtx); emit_label (op1); return target; @@ -10050,7 +10053,8 @@ do_store_flag (sepops ops, rtx target, e if ((code == NE || code == EQ) && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1) - && integer_pow2p (TREE_OPERAND (arg0, 1))) + && integer_pow2p (TREE_OPERAND (arg0, 1)) + && (TYPE_PRECISION (ops->type) != 1 || TYPE_UNSIGNED (ops->type))) { tree type = lang_hooks.types.type_for_mode (mode, unsignedp); return expand_expr (fold_single_bit_test (loc, @@ -10070,7 +10074,9 @@ do_store_flag (sepops ops, rtx target, e /* Try a cstore if possible. */ return emit_store_flag_force (target, code, op0, op1, - operand_mode, unsignedp, 1); + operand_mode, unsignedp, + (TYPE_PRECISION (ops->type) == 1 + && !TYPE_UNSIGNED (ops->type)) ? -1 : 1); } --- gcc/testsuite/gcc.c-torture/execute/pr48973-1.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr48973-1.c (revision 174060) @@ -0,0 +1,20 @@ +/* PR middle-end/48973 */ + +extern void abort (void); +struct S { int f : 1; } s; +int v = -1; + +void +foo (unsigned int x) +{ + if (x != -1U) + abort (); +} + +int +main () +{ + s.f = (v & 1) > 0; + foo (s.f); + return 0; +} --- gcc/testsuite/gcc.c-torture/execute/pr48973-2.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr48973-2.c (revision 174060) @@ -0,0 +1,14 @@ +/* PR middle-end/48973 */ + +extern void abort (void); +struct S { int f : 1; } s; +int v = -1; + +int +main () +{ + s.f = v < 0; + if ((unsigned int) s.f != -1U) + abort (); + return 0; +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-05-23 Jakub Jelinek PR c/49120 * c-decl.c (start_decl): Convert expr to void_type_node. * gcc.dg/pr49120.c: New test. --- gcc/c-decl.c (revision 174080) +++ gcc/c-decl.c (revision 174081) @@ -3942,7 +3942,7 @@ start_decl (struct c_declarator *declara return 0; if (expr) - add_stmt (expr); + add_stmt (fold_convert (void_type_node, expr)); if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))) warning (OPT_Wmain, "%q+D is usually a function", decl); --- gcc/testsuite/gcc.dg/pr49120.c (revision 0) +++ gcc/testsuite/gcc.dg/pr49120.c (revision 174081) @@ -0,0 +1,11 @@ +/* PR c/49120 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +int +main () +{ + int a = 1; + int c = ({ char b[a + 1]; b[0] = 0; b[0]; }); + return c; +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-05-26 Jakub Jelinek PR tree-optimization/49161 * tree-vrp.c (struct case_info): New type. (compare_case_labels): Sort case_info structs instead of trees, and not primarily by CASE_LABEL uids but by label_for_block indexes. (find_switch_asserts): Put case labels into struct case_info array instead of TREE_VEC, adjust sorting, compare label_for_block values instead of CASE_LABELs. * gcc.c-torture/execute/pr49161.c: New test. --- gcc/tree-vrp.c (revision 174269) +++ gcc/tree-vrp.c (revision 174270) @@ -4673,28 +4673,35 @@ find_conditional_asserts (basic_block bb return need_assert; } -/* Compare two case labels sorting first by the destination label uid +struct case_info +{ + tree expr; + basic_block bb; +}; + +/* Compare two case labels sorting first by the destination bb index and then by the case value. */ static int compare_case_labels (const void *p1, const void *p2) { - const_tree const case1 = *(const_tree const*)p1; - const_tree const case2 = *(const_tree const*)p2; - unsigned int uid1 = DECL_UID (CASE_LABEL (case1)); - unsigned int uid2 = DECL_UID (CASE_LABEL (case2)); + const struct case_info *ci1 = (const struct case_info *) p1; + const struct case_info *ci2 = (const struct case_info *) p2; + int idx1 = ci1->bb->index; + int idx2 = ci2->bb->index; - if (uid1 < uid2) + if (idx1 < idx2) return -1; - else if (uid1 == uid2) + else if (idx1 == idx2) { /* Make sure the default label is first in a group. */ - if (!CASE_LOW (case1)) + if (!CASE_LOW (ci1->expr)) return -1; - else if (!CASE_LOW (case2)) + else if (!CASE_LOW (ci2->expr)) return 1; else - return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2)); + return tree_int_cst_compare (CASE_LOW (ci1->expr), + CASE_LOW (ci2->expr)); } else return 1; @@ -4715,8 +4722,8 @@ find_switch_asserts (basic_block bb, gim gimple_stmt_iterator bsi; tree op; edge e; - tree vec2; - size_t n = gimple_switch_num_labels(last); + struct case_info *ci; + size_t n = gimple_switch_num_labels (last); #if GCC_VERSION >= 4000 unsigned int idx; #else @@ -4731,36 +4738,38 @@ find_switch_asserts (basic_block bb, gim return false; /* Build a vector of case labels sorted by destination label. */ - vec2 = make_tree_vec (n); + ci = XNEWVEC (struct case_info, n); for (idx = 0; idx < n; ++idx) - TREE_VEC_ELT (vec2, idx) = gimple_switch_label (last, idx); - qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels); + { + ci[idx].expr = gimple_switch_label (last, idx); + ci[idx].bb = label_to_block (CASE_LABEL (ci[idx].expr)); + } + qsort (ci, n, sizeof (struct case_info), compare_case_labels); for (idx = 0; idx < n; ++idx) { tree min, max; - tree cl = TREE_VEC_ELT (vec2, idx); + tree cl = ci[idx].expr; + basic_block cbb = ci[idx].bb; min = CASE_LOW (cl); max = CASE_HIGH (cl); /* If there are multiple case labels with the same destination we need to combine them to a single value range for the edge. */ - if (idx + 1 < n - && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx + 1))) + if (idx + 1 < n && cbb == ci[idx + 1].bb) { /* Skip labels until the last of the group. */ do { ++idx; - } while (idx < n - && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx))); + } while (idx < n && cbb == ci[idx].bb); --idx; /* Pick up the maximum of the case label range. */ - if (CASE_HIGH (TREE_VEC_ELT (vec2, idx))) - max = CASE_HIGH (TREE_VEC_ELT (vec2, idx)); + if (CASE_HIGH (ci[idx].expr)) + max = CASE_HIGH (ci[idx].expr); else - max = CASE_LOW (TREE_VEC_ELT (vec2, idx)); + max = CASE_LOW (ci[idx].expr); } /* Nothing to do if the range includes the default label until we @@ -4769,7 +4778,7 @@ find_switch_asserts (basic_block bb, gim continue; /* Find the edge to register the assert expr on. */ - e = find_edge (bb, label_to_block (CASE_LABEL (cl))); + e = find_edge (bb, cbb); /* Register the necessary assertions for the operand in the SWITCH_EXPR. */ @@ -4787,6 +4796,7 @@ find_switch_asserts (basic_block bb, gim } } + XDELETEVEC (ci); return need_assert; } --- gcc/testsuite/gcc.c-torture/execute/pr49161.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr49161.c (revision 174270) @@ -0,0 +1,46 @@ +/* PR tree-optimization/49161 */ + +extern void abort (void); + +int c; + +__attribute__((noinline, noclone)) void +bar (int x) +{ + if (x != c++) + abort (); +} + +__attribute__((noinline, noclone)) void +foo (int x) +{ + switch (x) + { + case 3: goto l1; + case 4: goto l2; + case 6: goto l3; + default: return; + } +l1: + goto l4; +l2: + goto l4; +l3: + bar (-1); +l4: + bar (0); + if (x != 4) + bar (1); + if (x != 3) + bar (-1); + bar (2); +} + +int +main () +{ + foo (3); + if (c != 3) + abort (); + return 0; +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-05-26 Jakub Jelinek PR c++/49165 * gimplify.c (shortcut_cond_r): Don't special case COND_EXPRs if they have void type on one of their arms. * g++.dg/eh/cond5.C: New test. --- gcc/gimplify.c (revision 174272) +++ gcc/gimplify.c (revision 174273) @@ -2573,7 +2573,9 @@ shortcut_cond_r (tree pred, tree *true_l new_locus); append_to_statement_list (t, &expr); } - else if (TREE_CODE (pred) == COND_EXPR) + else if (TREE_CODE (pred) == COND_EXPR + && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1))) + && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2)))) { location_t new_locus; @@ -2581,7 +2583,10 @@ shortcut_cond_r (tree pred, tree *true_l if (a) if (b) goto yes; else goto no; else - if (c) goto yes; else goto no; */ + if (c) goto yes; else goto no; + + Don't do this if one of the arms has void type, which can happen + in C++ when the arm is throw. */ /* Keep the original source location on the first 'if'. Set the source location of the ? on the second 'if'. */ --- gcc/testsuite/g++.dg/eh/cond5.C (revision 0) +++ gcc/testsuite/g++.dg/eh/cond5.C (revision 174273) @@ -0,0 +1,43 @@ +// PR c++/49165 +// { dg-do run } + +extern "C" void abort (); + +int +foo (bool x, int y) +{ + if (y < 10 && (x ? true : throw 1)) + y++; + if (y > 20 || (x ? true : throw 2)) + y++; + return y; +} + +int +main () +{ + if (foo (true, 0) != 2 + || foo (true, 10) != 11 + || foo (false, 30) != 31) + abort (); + try + { + foo (false, 0); + abort (); + } + catch (int i) + { + if (i != 1) + abort (); + } + try + { + foo (false, 10); + abort (); + } + catch (int i) + { + if (i != 2) + abort (); + } +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-05-27 Jakub Jelinek PR c++/49165 * c-common.c (c_common_truthvalue_conversion) : For C++ don't call c_common_truthvalue_conversion on void type arms. * g++.dg/eh/cond6.C: New test. --- gcc/c-common.c (revision 174349) +++ gcc/c-common.c (revision 174350) @@ -3945,14 +3945,15 @@ c_common_truthvalue_conversion (location /* Distribute the conversion into the arms of a COND_EXPR. */ if (c_dialect_cxx ()) { + tree op1 = TREE_OPERAND (expr, 1); + tree op2 = TREE_OPERAND (expr, 2); + /* In C++ one of the arms might have void type if it is throw. */ + if (!VOID_TYPE_P (TREE_TYPE (op1))) + op1 = c_common_truthvalue_conversion (location, op1); + if (!VOID_TYPE_P (TREE_TYPE (op2))) + op2 = c_common_truthvalue_conversion (location, op2); expr = fold_build3_loc (location, COND_EXPR, truthvalue_type_node, - TREE_OPERAND (expr, 0), - c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, - 1)), - c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, - 2))); + TREE_OPERAND (expr, 0), op1, op2); goto ret; } else --- gcc/testsuite/g++.dg/eh/cond6.C (revision 0) +++ gcc/testsuite/g++.dg/eh/cond6.C (revision 174350) @@ -0,0 +1,43 @@ +// PR c++/49165 +// { dg-do run } + +extern "C" void abort (); + +int +foo (bool x, int y) +{ + if (y < 10 && (x ? 1 : throw 1)) + y++; + if (y > 20 || (x ? 1 : throw 2)) + y++; + return y; +} + +int +main () +{ + if (foo (true, 0) != 2 + || foo (true, 10) != 11 + || foo (false, 30) != 31) + abort (); + try + { + foo (false, 0); + abort (); + } + catch (int i) + { + if (i != 1) + abort (); + } + try + { + foo (false, 10); + abort (); + } + catch (int i) + { + if (i != 2) + abort (); + } +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-07-04 Jakub Jelinek PR rtl-optimization/49619 * combine.c (combine_simplify_rtx): In PLUS -> IOR simplification pass VOIDmode as op0_mode to recursive call. * gcc.dg/pr49619.c: New test. --- gcc/combine.c (revision 175824) +++ gcc/combine.c (revision 175825) @@ -5298,7 +5298,7 @@ combine_simplify_rtx (rtx x, enum machin { /* Try to simplify the expression further. */ rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); - temp = combine_simplify_rtx (tor, mode, in_dest); + temp = combine_simplify_rtx (tor, VOIDmode, in_dest); /* If we could, great. If not, do not go ahead with the IOR replacement, since PLUS appears in many special purpose --- gcc/testsuite/gcc.dg/pr49619.c (revision 0) +++ gcc/testsuite/gcc.dg/pr49619.c (revision 175825) @@ -0,0 +1,13 @@ +/* PR rtl-optimization/49619 */ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-fre" } */ + +extern int a, b; + +void +foo (int x) +{ + a = 2; + b = 0; + b = (a && ((a = 1, 0 >= b) || (short) (x + (b & x)))); +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-07-07 Jakub Jelinek PR middle-end/49640 * gimplify.c (gimplify_compound_lval): For last 2 ARRAY_*REF operands and last COMPONENT_REF operand call gimplify_expr on it if non-NULL. * gcc.dg/gomp/pr49640.c: New test. --- gcc/gimplify.c (revision 175966) +++ gcc/gimplify.c (revision 175967) @@ -2010,8 +2010,14 @@ gimplify_compound_lval (tree *expr_p, gi ret = MIN (ret, tret); } } + else + { + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_reg, fb_rvalue); + ret = MIN (ret, tret); + } - if (!TREE_OPERAND (t, 3)) + if (TREE_OPERAND (t, 3) == NULL_TREE) { tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))); tree elmt_size = unshare_expr (array_ref_element_size (t)); @@ -2031,11 +2037,17 @@ gimplify_compound_lval (tree *expr_p, gi ret = MIN (ret, tret); } } + else + { + tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p, + is_gimple_reg, fb_rvalue); + ret = MIN (ret, tret); + } } else if (TREE_CODE (t) == COMPONENT_REF) { /* Set the field offset into T and gimplify it. */ - if (!TREE_OPERAND (t, 2)) + if (TREE_OPERAND (t, 2) == NULL_TREE) { tree offset = unshare_expr (component_ref_field_offset (t)); tree field = TREE_OPERAND (t, 1); @@ -2054,6 +2066,12 @@ gimplify_compound_lval (tree *expr_p, gi ret = MIN (ret, tret); } } + else + { + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_reg, fb_rvalue); + ret = MIN (ret, tret); + } } } --- gcc/testsuite/gcc.dg/gomp/pr49640.c (revision 0) +++ gcc/testsuite/gcc.dg/gomp/pr49640.c (revision 175967) @@ -0,0 +1,29 @@ +/* PR middle-end/49640 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -std=gnu99 -fopenmp" } */ + +void +foo (int N, int M, int K, int P, int Q, int R, int i, int j, int k, + unsigned char x[P][Q][R], int y[N][M][K]) +{ + int ii, jj, kk; + +#pragma omp parallel for private(ii,jj,kk) + for (ii = 0; ii < P; ++ii) + for (jj = 0; jj < Q; ++jj) + for (kk = 0; kk < R; ++kk) + y[i + ii][j + jj][k + kk] = x[ii][jj][kk]; +} + +void +bar (int N, int M, int K, int P, int Q, int R, int i, int j, int k, + unsigned char x[P][Q][R], float y[N][M][K], float factor, float zero) +{ + int ii, jj, kk; + +#pragma omp parallel for private(ii,jj,kk) + for (ii = 0; ii < P; ++ii) + for (jj = 0; jj < Q; ++jj) + for (kk = 0; kk < R; ++kk) + y[i + ii][j + jj][k + kk] = factor * x[ii][jj][kk] + zero; +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-07-07 Jakub Jelinek PR c/49644 * c-typeck.c (build_binary_op): For MULT_EXPR and TRUNC_DIV_EXPR with one non-complex and one complex argument, call c_save_expr on both operands. * gcc.c-torture/execute/pr49644.c: New test. --- gcc/c-typeck.c (revision 176003) +++ gcc/c-typeck.c (revision 176004) @@ -10040,6 +10040,7 @@ build_binary_op (location_t location, en { case MULT_EXPR: case TRUNC_DIV_EXPR: + op1 = c_save_expr (op1); imag = build2 (resultcode, real_type, imag, op1); /* Fall through. */ case PLUS_EXPR: @@ -10060,6 +10061,7 @@ build_binary_op (location_t location, en switch (code) { case MULT_EXPR: + op0 = c_save_expr (op0); imag = build2 (resultcode, real_type, op0, imag); /* Fall through. */ case PLUS_EXPR: --- gcc/testsuite/gcc.c-torture/execute/pr49644.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr49644.c (revision 176004) @@ -0,0 +1,16 @@ +/* PR c/49644 */ + +extern void abort (void); + +int +main () +{ + _Complex double a[12], *c = a, s = 3.0 + 1.0i; + double b[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, *d = b; + int i; + for (i = 0; i < 6; i++) + *c++ = *d++ * s; + if (c != a + 6 || d != b + 6) + abort (); + return 0; +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-07-07 Jakub Jelinek PR c/49644 * typeck.c (cp_build_binary_op): For MULT_EXPR and TRUNC_DIV_EXPR with one non-complex and one complex argument, call save_expr on both operands. * g++.dg/torture/pr49644.C: New test. --- gcc/cp/typeck.c (revision 176005) +++ gcc/cp/typeck.c (revision 176006) @@ -4338,6 +4338,7 @@ cp_build_binary_op (location_t location, { case MULT_EXPR: case TRUNC_DIV_EXPR: + op1 = save_expr (op1); imag = build2 (resultcode, real_type, imag, op1); /* Fall through. */ case PLUS_EXPR: @@ -4356,6 +4357,7 @@ cp_build_binary_op (location_t location, switch (code) { case MULT_EXPR: + op0 = save_expr (op0); imag = build2 (resultcode, real_type, op0, imag); /* Fall through. */ case PLUS_EXPR: --- gcc/testsuite/g++.dg/torture/pr49644.C (revision 0) +++ gcc/testsuite/g++.dg/torture/pr49644.C (revision 176006) @@ -0,0 +1,17 @@ +// PR c/49644 +// { dg-do run } + +extern "C" void abort (); + +int +main () +{ + _Complex double a[12], *c = a, s = 3.0 + 1.0i; + double b[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, *d = b; + int i; + for (i = 0; i < 6; i++) + *c++ = *d++ * s; + if (c != a + 6 || d != b + 6) + abort (); + return 0; +} 2011-07-19 Jakub Jelinek Backport from mainline 2011-07-08 Jakub Jelinek PR target/49621 * config/rs6000/rs6000.c (rs6000_emit_vector_cond_expr): Use CONST0_RTX (dest_mode) instead of const0_rtx as second operand of NE. * config/rs6000/vector.md (vector_select_, vector_select__uns): Change second operand of NE to CONST0_RTX (mode) instead of const0_rtx. * config/rs6000/altivec.md (*altivec_vsel, *altivec_vsel_uns): Expect second operand of NE to be zero_constant of the corresponding vector mode. * config/rs6000/vsx.md (*vsx_xxsel, *vsx_xxsel_uns): Likewise. * gcc.target/powerpc/altivec-34.c: New test. --- gcc/config/rs6000/vector.md (revision 176062) +++ gcc/config/rs6000/vector.md (revision 176063) @@ -465,21 +465,21 @@ (define_expand "vector_select_" [(set (match_operand:VEC_L 0 "vlogical_operand" "") (if_then_else:VEC_L (ne:CC (match_operand:VEC_L 3 "vlogical_operand" "") - (const_int 0)) + (match_dup 4)) (match_operand:VEC_L 2 "vlogical_operand" "") (match_operand:VEC_L 1 "vlogical_operand" "")))] "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" - "") + "operands[4] = CONST0_RTX (mode);") (define_expand "vector_select__uns" [(set (match_operand:VEC_L 0 "vlogical_operand" "") (if_then_else:VEC_L (ne:CCUNS (match_operand:VEC_L 3 "vlogical_operand" "") - (const_int 0)) + (match_dup 4)) (match_operand:VEC_L 2 "vlogical_operand" "") (match_operand:VEC_L 1 "vlogical_operand" "")))] "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" - "") + "operands[4] = CONST0_RTX (mode);") ;; Expansions that compare vectors producing a vector result and a predicate, ;; setting CR6 to indicate a combined status --- gcc/config/rs6000/rs6000.c (revision 176062) +++ gcc/config/rs6000/rs6000.c (revision 176063) @@ -16888,7 +16888,7 @@ rs6000_emit_vector_cond_expr (rtx dest, op_false = tmp; } - cond2 = gen_rtx_fmt_ee (NE, cc_mode, mask, const0_rtx); + cond2 = gen_rtx_fmt_ee (NE, cc_mode, mask, CONST0_RTX (dest_mode)); emit_insn (gen_rtx_SET (VOIDmode, dest, gen_rtx_IF_THEN_ELSE (dest_mode, --- gcc/config/rs6000/vsx.md (revision 176062) +++ gcc/config/rs6000/vsx.md (revision 176063) @@ -674,7 +674,7 @@ (define_insn "*vsx_xxsel" [(set (match_operand:VSX_L 0 "vsx_register_operand" "=,?wa") (if_then_else:VSX_L (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" ",wa") - (const_int 0)) + (match_operand:VSX_L 4 "zero_constant" "")) (match_operand:VSX_L 2 "vsx_register_operand" ",wa") (match_operand:VSX_L 3 "vsx_register_operand" ",wa")))] "VECTOR_MEM_VSX_P (mode)" @@ -685,7 +685,7 @@ (define_insn "*vsx_xxsel_uns" [(set (match_operand:VSX_L 0 "vsx_register_operand" "=,?wa") (if_then_else:VSX_L (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" ",wa") - (const_int 0)) + (match_operand:VSX_L 4 "zero_constant" "")) (match_operand:VSX_L 2 "vsx_register_operand" ",wa") (match_operand:VSX_L 3 "vsx_register_operand" ",wa")))] "VECTOR_MEM_VSX_P (mode)" --- gcc/config/rs6000/altivec.md (revision 176062) +++ gcc/config/rs6000/altivec.md (revision 176063) @@ -487,7 +487,7 @@ (define_insn "*altivec_vsel" [(set (match_operand:VM 0 "altivec_register_operand" "=v") (if_then_else:VM (ne:CC (match_operand:VM 1 "altivec_register_operand" "v") - (const_int 0)) + (match_operand:VM 4 "zero_constant" "")) (match_operand:VM 2 "altivec_register_operand" "v") (match_operand:VM 3 "altivec_register_operand" "v")))] "VECTOR_MEM_ALTIVEC_P (mode)" @@ -498,7 +498,7 @@ (define_insn "*altivec_vsel_uns" [(set (match_operand:VM 0 "altivec_register_operand" "=v") (if_then_else:VM (ne:CCUNS (match_operand:VM 1 "altivec_register_operand" "v") - (const_int 0)) + (match_operand:VM 4 "zero_constant" "")) (match_operand:VM 2 "altivec_register_operand" "v") (match_operand:VM 3 "altivec_register_operand" "v")))] "VECTOR_MEM_ALTIVEC_P (mode)" --- gcc/testsuite/gcc.target/powerpc/altivec-34.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/altivec-34.c (revision 176063) @@ -0,0 +1,24 @@ +/* PR target/49621 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -maltivec" } */ + +#include + +int +foo (void) +{ + vector unsigned a, b, c; + unsigned k = 1; + + a = (vector unsigned) { 0, 0, 0, 1 }; + b = c = (vector unsigned) { 0, 0, 0, 0 }; + + a = vec_add (a, vec_splats (k)); + b = vec_add (b, a); + c = vec_sel (c, a, b); + + if (vec_any_eq (b, c)) + return 1; + + return 0; +} --- gcc/tree-vrp.c (revision 173875) +++ gcc/tree-vrp.c (revision 173876) @@ -1,5 +1,5 @@ /* Support routines for Value Range Propagation (VRP). - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Diego Novillo . @@ -2358,17 +2358,27 @@ extract_range_from_binary_expr (value_ra op0 + op1 == 0, so we cannot claim that the sum is in ~[0,0]. Note that we are guaranteed to have vr0.type == vr1.type at this point. */ - if (code == PLUS_EXPR && vr0.type == VR_ANTI_RANGE) + if (vr0.type == VR_ANTI_RANGE) { - set_value_range_to_varying (vr); - return; + if (code == PLUS_EXPR) + { + set_value_range_to_varying (vr); + return; + } + /* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs, + the resulting VR_ANTI_RANGE is the same - intersection + of the two ranges. */ + min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min); + max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max); + } + else + { + /* For operations that make the resulting range directly + proportional to the original ranges, apply the operation to + the same end of each range. */ + min = vrp_int_const_binop (code, vr0.min, vr1.min); + max = vrp_int_const_binop (code, vr0.max, vr1.max); } - - /* For operations that make the resulting range directly - proportional to the original ranges, apply the operation to - the same end of each range. */ - min = vrp_int_const_binop (code, vr0.min, vr1.min); - max = vrp_int_const_binop (code, vr0.max, vr1.max); /* If both additions overflowed the range kind is still correct. This happens regularly with subtracting something in unsigned --- gcc/testsuite/gcc.c-torture/execute/pr49039.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr49039.c (revision 173876) @@ -0,0 +1,26 @@ +/* PR tree-optimization/49039 */ +extern void abort (void); +int cnt; + +__attribute__((noinline, noclone)) void +foo (unsigned int x, unsigned int y) +{ + unsigned int minv, maxv; + if (x == 1 || y == -2U) + return; + minv = x < y ? x : y; + maxv = x > y ? x : y; + if (minv == 1) + ++cnt; + if (maxv == -2U) + ++cnt; +} + +int +main () +{ + foo (-2U, 1); + if (cnt != 2) + abort (); + return 0; +} --- gcc/testsuite/gcc.dg/tree-ssa/pr49039.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/pr49039.c (revision 173876) @@ -0,0 +1,31 @@ +/* PR tree-optimization/49039 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void bar (void); + +void +foo (unsigned int x, unsigned int y) +{ + unsigned int minv, maxv; + if (x >= 3 && x <= 6) + return; + if (y >= 5 && y <= 8) + return; + minv = x < y ? x : y; + maxv = x > y ? x : y; + if (minv == 5) + bar (); + if (minv == 6) + bar (); + if (maxv == 5) + bar (); + if (maxv == 6) + bar (); +} + +/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 5 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 6 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 5 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 6 to 0" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ --- gcc/testsuite/g++.dg/torture/pr49039.C (revision 0) +++ gcc/testsuite/g++.dg/torture/pr49039.C (revision 173876) @@ -0,0 +1,76 @@ +// PR tree-optimization/49039 +// { dg-do run } + +template +struct pair +{ + T1 first; + T2 second; + pair (const T1 & a, const T2 & b):first (a), second (b) {} +}; + +template +inline pair +make_pair (T1 x, T2 y) +{ + return pair (x, y); +} + +typedef __SIZE_TYPE__ size_t; +struct S +{ + const char *Data; + size_t Length; + static size_t min (size_t a, size_t b) { return a < b ? a : b; } + static size_t max (size_t a, size_t b) { return a > b ? a : b; } + S () :Data (0), Length (0) { } + S (const char *Str) : Data (Str), Length (__builtin_strlen (Str)) {} + S (const char *data, size_t length) : Data (data), Length (length) {} + bool empty () const { return Length == 0; } + size_t size () const { return Length; } + S slice (size_t Start, size_t End) const + { + Start = min (Start, Length); + End = min (max (Start, End), Length); + return S (Data + Start, End - Start); + } + pair split (char Separator) const + { + size_t Idx = find (Separator); + if (Idx == ~size_t (0)) + return make_pair (*this, S ()); + return make_pair (slice (0, Idx), slice (Idx + 1, ~size_t (0))); + } + size_t find (char C, size_t From = 0) const + { + for (size_t i = min (From, Length), e = Length; i != e; ++i) + if (Data[i] == C) + return i; + return ~size_t (0); + } +}; + +void +Test (const char *arg) +{ + S Desc (arg); + while (!Desc.empty ()) + { + pair Split = Desc.split ('-'); + S Token = Split.first; + Desc = Split.second; + if (Token.empty ()) + continue; + Split = Token.split (':'); + S Specifier = Split.first; + if (Specifier.empty ()) + __builtin_abort (); + } +} + +int +main () +{ + Test ("-"); + return 0; +}