On Tue, Jul 19, 2011 at 03:13:59PM +0200, Jakub Jelinek wrote: > 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.
And here are the 4.4 backports, again bootstrapped/regtested on x86_64-linux and i686-linux, committed to 4.4 branch. Jakub
2011-07-19 Jakub Jelinek <ja...@redhat.com> Backport from mainline 2011-05-18 Jakub Jelinek <ja...@redhat.com> 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 <a, c>, MIN_EXPR <b, d>]. * gcc.c-torture/execute/pr49039.c: New test. * gcc.dg/tree-ssa/pr49039.c: New test. * g++.dg/torture/pr49039.C: New test. --- gcc/tree-vrp.c (revision 173875) +++ gcc/tree-vrp.c (revision 173876) @@ -2259,17 +2259,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); } else if (code == MULT_EXPR || code == TRUNC_DIV_EXPR --- 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 <class T1, class T2> +struct pair +{ + T1 first; + T2 second; + pair (const T1 & a, const T2 & b):first (a), second (b) {} +}; + +template <class T1, class T2> +inline pair <T1, T2> +make_pair (T1 x, T2 y) +{ + return pair <T1, T2> (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 <S, S> 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 <S, S> 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; +}
2011-07-19 Jakub Jelinek <ja...@redhat.com> Backport from mainline 2011-05-23 Jakub Jelinek <ja...@redhat.com> PR middle-end/48973 * expr.c (expand_expr_real_1) <case LT_EXPR>: 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 TREE_TYPE (exp) is single bit signed type, disable single bit test optimization, pass -1 instead of 1 as last parameter to emit_store_flag and use constm1_rtx instead of const1_rtx as true value. * 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) @@ -9113,10 +9113,12 @@ expand_expr_real_1 (tree exp, rtx target /* If temp is constant, we can just compute the result. */ if (GET_CODE (temp) == CONST_INT) { - if (INTVAL (temp) != 0) - emit_move_insn (target, const1_rtx); - else + if (INTVAL (temp) == 0) emit_move_insn (target, const0_rtx); + else if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) + emit_move_insn (target, constm1_rtx); + else + emit_move_insn (target, const1_rtx); return target; } @@ -9133,7 +9135,9 @@ expand_expr_real_1 (tree exp, rtx target op1 = gen_label_rtx (); emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX, GET_MODE (temp), unsignedp, op1); - emit_move_insn (temp, const1_rtx); + emit_move_insn (temp, + TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type) + ? constm1_rtx : const1_rtx); emit_label (op1); return temp; } @@ -9757,7 +9761,7 @@ do_store_flag (tree exp, rtx target, enu rtx op0, op1; enum insn_code icode; rtx subtarget = target; - rtx result, label; + rtx result, label, trueval = const1_rtx; /* If this is a TRUTH_NOT_EXPR, set a flag indicating we must invert the result at the end. We can't simply invert the test since it would @@ -9887,7 +9891,9 @@ do_store_flag (tree exp, rtx target, enu 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 (TREE_TYPE (exp)) != 1 + || TYPE_UNSIGNED (TREE_TYPE (exp)))) { tree type = lang_hooks.types.type_for_mode (mode, unsignedp); return expand_expr (fold_single_bit_test (code == NE ? NE_EXPR : EQ_EXPR, @@ -9939,13 +9945,18 @@ do_store_flag (tree exp, rtx target, enu if (target == 0) target = gen_reg_rtx (mode); + if (TYPE_PRECISION (TREE_TYPE (exp)) == 1 + && !TYPE_UNSIGNED (TREE_TYPE (exp))) + trueval = constm1_rtx; + result = emit_store_flag (target, code, op0, op1, - operand_mode, unsignedp, 1); + operand_mode, unsignedp, + trueval == const1_rtx ? 1 : -1); if (result) { if (invert) - result = expand_binop (mode, xor_optab, result, const1_rtx, + result = expand_binop (mode, xor_optab, result, trueval, result, 0, OPTAB_LIB_WIDEN); return result; } @@ -9955,12 +9966,12 @@ do_store_flag (tree exp, rtx target, enu || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1)) target = gen_reg_rtx (GET_MODE (target)); - emit_move_insn (target, invert ? const0_rtx : const1_rtx); + emit_move_insn (target, invert ? const0_rtx : trueval); label = gen_label_rtx (); do_compare_rtx_and_jump (op0, op1, code, unsignedp, operand_mode, NULL_RTX, NULL_RTX, label, -1); - emit_move_insn (target, invert ? const1_rtx : const0_rtx); + emit_move_insn (target, invert ? trueval : const0_rtx); emit_label (label); return target; --- 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 <ja...@redhat.com> Backport from mainline 2011-05-26 Jakub Jelinek <ja...@redhat.com> 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) @@ -2570,13 +2570,18 @@ shortcut_cond_r (tree pred, tree *true_l false_label_p); 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)))) { /* As long as we're messing with gotos, turn if (a ? b : c) into 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. */ expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0), shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p), --- 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 <ja...@redhat.com> Backport from mainline 2011-05-27 Jakub Jelinek <ja...@redhat.com> PR c++/49165 * c-common.c (c_common_truthvalue_conversion) <case COND_EXPR>: 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) @@ -3430,13 +3430,18 @@ c_common_truthvalue_conversion (location TREE_OPERAND (expr, 0)); case COND_EXPR: - /* Distribute the conversion into the arms of a COND_EXPR. */ - return fold_build3 (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 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); + /* Distribute the conversion into the arms of a COND_EXPR. */ + return fold_build3 (COND_EXPR, truthvalue_type_node, + TREE_OPERAND (expr, 0), op1, op2); + } CASE_CONVERT: /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, --- 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 <ja...@redhat.com> Backport from mainline 2011-07-04 Jakub Jelinek <ja...@redhat.com> 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 <ja...@redhat.com> Backport from mainline 2011-07-07 Jakub Jelinek <ja...@redhat.com> 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; +}