Hi!
I've backported a couple of patches to 8.x, after bootstrapping/regtesting
them there:
Jakub
2018-05-30 Jakub Jelinek <[email protected]>
Backported from mainline
2018-05-08 Jakub Jelinek <[email protected]>
PR target/85683
* config/i386/i386.md: Add peepholes for mem {+,-,&,|,^}= x; mem != 0
after cmpelim optimization.
* gcc.target/i386/pr49095.c: Add -masm=att to dg-options. Add
scan-assembler-times checking that except for [fh]*xor other functions
don't use any load instructions.
--- gcc/config/i386/i386.md (revision 260044)
+++ gcc/config/i386/i386.md (revision 260045)
@@ -19286,6 +19286,37 @@ (define_peephole2
const0_rtx);
})
+;; Likewise for cmpelim optimized pattern.
+(define_peephole2
+ [(set (match_operand:SWI 0 "register_operand")
+ (match_operand:SWI 1 "memory_operand"))
+ (parallel [(set (reg FLAGS_REG)
+ (compare (match_operator:SWI 3 "plusminuslogic_operator"
+ [(match_dup 0)
+ (match_operand:SWI 2 "<nonmemory_operand>")])
+ (const_int 0)))
+ (set (match_dup 0) (match_dup 3))])
+ (set (match_dup 1) (match_dup 0))]
+ "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (3, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
+ && ix86_match_ccmode (peep2_next_insn (1),
+ (GET_CODE (operands[3]) == PLUS
+ || GET_CODE (operands[3]) == MINUS)
+ ? CCGOCmode : CCNOmode)"
+ [(parallel [(set (match_dup 4) (match_dup 6))
+ (set (match_dup 1) (match_dup 5))])]
+{
+ operands[4] = SET_DEST (XVECEXP (PATTERN (peep2_next_insn (1)), 0, 0));
+ operands[5]
+ = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
+ copy_rtx (operands[1]), operands[2]);
+ operands[6]
+ = gen_rtx_COMPARE (GET_MODE (operands[4]), copy_rtx (operands[5]),
+ const0_rtx);
+})
+
;; Likewise for instances where we have a lea pattern.
(define_peephole2
[(set (match_operand:SWI 0 "register_operand")
@@ -19349,6 +19380,34 @@ (define_peephole2
const0_rtx);
})
+;; Likewise for cmpelim optimized pattern.
+(define_peephole2
+ [(parallel [(set (reg FLAGS_REG)
+ (compare (match_operator:SWI 2 "plusminuslogic_operator"
+ [(match_operand:SWI 0 "register_operand")
+ (match_operand:SWI 1 "memory_operand")])
+ (const_int 0)))
+ (set (match_dup 0) (match_dup 2))])
+ (set (match_dup 1) (match_dup 0))]
+ "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (2, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && ix86_match_ccmode (peep2_next_insn (0),
+ (GET_CODE (operands[2]) == PLUS
+ || GET_CODE (operands[2]) == MINUS)
+ ? CCGOCmode : CCNOmode)"
+ [(parallel [(set (match_dup 3) (match_dup 5))
+ (set (match_dup 1) (match_dup 4))])]
+{
+ operands[3] = SET_DEST (XVECEXP (PATTERN (peep2_next_insn (0)), 0, 0));
+ operands[4]
+ = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+ copy_rtx (operands[1]), operands[0]);
+ operands[5]
+ = gen_rtx_COMPARE (GET_MODE (operands[3]), copy_rtx (operands[4]),
+ const0_rtx);
+})
+
(define_peephole2
[(set (match_operand:SWI12 0 "register_operand")
(match_operand:SWI12 1 "memory_operand"))
--- gcc/testsuite/gcc.target/i386/pr49095.c (revision 260044)
+++ gcc/testsuite/gcc.target/i386/pr49095.c (revision 260045)
@@ -1,6 +1,6 @@
/* PR rtl-optimization/49095 */
/* { dg-do compile } */
-/* { dg-options "-Os -fno-shrink-wrap" } */
+/* { dg-options "-Os -fno-shrink-wrap -masm=att" } */
/* { dg-additional-options "-mregparm=2" { target ia32 } } */
void foo (void *);
@@ -71,3 +71,6 @@ G (int)
G (long)
/* { dg-final { scan-assembler-not "test\[lq\]" } } */
+/* The {f,h}{char,short,int,long}xor functions aren't optimized into
+ a RMW instruction, so need load, modify and store. FIXME eventually. */
+/* { dg-final { scan-assembler-times "\\), %" 8 } } */
2018-05-30 Jakub Jelinek <[email protected]>
Backported from mainline
2018-05-10 Jakub Jelinek <[email protected]>
PR c++/85662
* c-common.h (fold_offsetof_1): Removed.
(fold_offsetof): Add TYPE argument defaulted to size_type_node and
CTX argument defaulted to ERROR_MARK.
* c-common.c (fold_offsetof_1): Renamed to ...
(fold_offsetof): ... this. Remove wrapper function. Add TYPE
argument, convert the pointer constant to TYPE and use size_binop
with PLUS_EXPR instead of fold_build_pointer_plus if type is not
a pointer type. Adjust recursive calls.
* c-fold.c (c_fully_fold_internal): Use fold_offsetof rather than
fold_offsetof_1, pass TREE_TYPE (expr) as TYPE to it and drop the
fold_convert_loc.
* c-typeck.c (build_unary_op): Use fold_offsetof rather than
fold_offsetof_1, pass argtype as TYPE to it and drop the
fold_convert_loc.
* cp-gimplify.c (cp_fold): Use fold_offsetof rather than
fold_offsetof_1, pass TREE_TYPE (x) as TYPE to it and drop the
fold_convert.
* g++.dg/ext/offsetof2.C: New test.
--- gcc/c-family/c-common.c (revision 260118)
+++ gcc/c-family/c-common.c (revision 260119)
@@ -6168,10 +6168,11 @@ c_common_to_target_charset (HOST_WIDE_IN
/* Fold an offsetof-like expression. EXPR is a nested sequence of component
references with an INDIRECT_REF of a constant at the bottom; much like the
- traditional rendering of offsetof as a macro. Return the folded result. */
+ traditional rendering of offsetof as a macro. TYPE is the desired type of
+ the whole expression. Return the folded result. */
tree
-fold_offsetof_1 (tree expr, enum tree_code ctx)
+fold_offsetof (tree expr, tree type, enum tree_code ctx)
{
tree base, off, t;
tree_code code = TREE_CODE (expr);
@@ -6196,10 +6197,10 @@ fold_offsetof_1 (tree expr, enum tree_co
error ("cannot apply %<offsetof%> to a non constant address");
return error_mark_node;
}
- return TREE_OPERAND (expr, 0);
+ return convert (type, TREE_OPERAND (expr, 0));
case COMPONENT_REF:
- base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code);
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
if (base == error_mark_node)
return base;
@@ -6216,7 +6217,7 @@ fold_offsetof_1 (tree expr, enum tree_co
break;
case ARRAY_REF:
- base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code);
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
if (base == error_mark_node)
return base;
@@ -6273,23 +6274,16 @@ fold_offsetof_1 (tree expr, enum tree_co
/* Handle static members of volatile structs. */
t = TREE_OPERAND (expr, 1);
gcc_checking_assert (VAR_P (get_base_address (t)));
- return fold_offsetof_1 (t);
+ return fold_offsetof (t, type);
default:
gcc_unreachable ();
}
+ if (!POINTER_TYPE_P (type))
+ return size_binop (PLUS_EXPR, base, convert (type, off));
return fold_build_pointer_plus (base, off);
}
-
-/* Likewise, but convert it to the return type of offsetof. */
-
-tree
-fold_offsetof (tree expr)
-{
- return convert (size_type_node, fold_offsetof_1 (expr));
-}
-
/* *PTYPE is an incomplete array. Complete it with a domain based on
INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
--- gcc/c-family/c-common.h (revision 260118)
+++ gcc/c-family/c-common.h (revision 260119)
@@ -1033,8 +1033,8 @@ extern bool c_dump_tree (void *, tree);
extern void verify_sequence_points (tree);
-extern tree fold_offsetof_1 (tree, tree_code ctx = ERROR_MARK);
-extern tree fold_offsetof (tree);
+extern tree fold_offsetof (tree, tree = size_type_node,
+ tree_code ctx = ERROR_MARK);
extern int complete_array_type (tree *, tree, bool);
--- gcc/c/c-fold.c (revision 260118)
+++ gcc/c/c-fold.c (revision 260119)
@@ -473,7 +473,7 @@ c_fully_fold_internal (tree expr, bool i
&& (op1 = get_base_address (op0)) != NULL_TREE
&& INDIRECT_REF_P (op1)
&& TREE_CONSTANT (TREE_OPERAND (op1, 0)))
- ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0));
+ ret = fold_offsetof (op0, TREE_TYPE (expr));
else if (op0 != orig_op0 || in_init)
ret = in_init
? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
--- gcc/c/c-typeck.c (revision 260118)
+++ gcc/c/c-typeck.c (revision 260119)
@@ -4676,7 +4676,7 @@ build_unary_op (location_t location, enu
if (val && INDIRECT_REF_P (val)
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
{
- ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
+ ret = fold_offsetof (arg, argtype);
goto return_build_unary_op;
}
--- gcc/cp/cp-gimplify.c (revision 260118)
+++ gcc/cp/cp-gimplify.c (revision 260119)
@@ -2232,7 +2232,7 @@ cp_fold (tree x)
val = TREE_OPERAND (val, 0);
STRIP_NOPS (val);
if (TREE_CODE (val) == INTEGER_CST)
- return fold_convert (TREE_TYPE (x), fold_offsetof_1 (op0));
+ return fold_offsetof (op0, TREE_TYPE (x));
}
}
goto finish_unary;
--- gcc/testsuite/g++.dg/ext/offsetof2.C (nonexistent)
+++ gcc/testsuite/g++.dg/ext/offsetof2.C (revision 260119)
@@ -0,0 +1,6 @@
+// PR c++/85662
+// { dg-do compile { target c++11 } }
+
+struct S { unsigned long x[31]; };
+struct T { bool b; S f; };
+static_assert (__builtin_offsetof (T, f.x[31 - 1]) == __builtin_offsetof (T,
f.x[30]), "");
2018-05-30 Jakub Jelinek <[email protected]>
Backported from mainline
2018-05-11 Jakub Jelinek <[email protected]>
PR c/85696
* c-omp.c (c_omp_predetermined_sharing): Return
OMP_CLAUSE_DEFAULT_SHARED for artificial vars with integral type.
* cp-tree.h (cxx_omp_predetermined_sharing_1): New prototype.
* cp-gimplify.c (cxx_omp_predetermined_sharing): New wrapper around
cxx_omp_predetermined_sharing_1. Rename old function to ...
(cxx_omp_predetermined_sharing_1): ... this.
* semantics.c (finish_omp_clauses): Use cxx_omp_predetermined_sharing_1
instead of cxx_omp_predetermined_sharing.
* c-c++-common/gomp/pr85696.c: New test.
--- gcc/c-family/c-omp.c (revision 260155)
+++ gcc/c-family/c-omp.c (revision 260156)
@@ -1611,5 +1611,13 @@ c_omp_predetermined_sharing (tree decl)
if (TREE_READONLY (decl))
return OMP_CLAUSE_DEFAULT_SHARED;
+ /* Predetermine artificial variables holding integral values, those
+ are usually result of gimplify_one_sizepos or SAVE_EXPR
+ gimplification. */
+ if (VAR_P (decl)
+ && DECL_ARTIFICIAL (decl)
+ && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+ return OMP_CLAUSE_DEFAULT_SHARED;
+
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
--- gcc/cp/cp-gimplify.c (revision 260155)
+++ gcc/cp/cp-gimplify.c (revision 260156)
@@ -1957,7 +1957,7 @@ cxx_omp_const_qual_no_mutable (tree decl
/* True if OpenMP sharing attribute of DECL is predetermined. */
enum omp_clause_default_kind
-cxx_omp_predetermined_sharing (tree decl)
+cxx_omp_predetermined_sharing_1 (tree decl)
{
/* Static data members are predetermined shared. */
if (TREE_STATIC (decl))
@@ -1973,6 +1973,32 @@ cxx_omp_predetermined_sharing (tree decl
return OMP_CLAUSE_DEFAULT_SHARED;
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+}
+
+/* Likewise, but also include the artificial vars. We don't want to
+ disallow the artificial vars being mentioned in explicit clauses,
+ as we use artificial vars e.g. for loop constructs with random
+ access iterators other than pointers, but during gimplification
+ we want to treat them as predetermined. */
+
+enum omp_clause_default_kind
+cxx_omp_predetermined_sharing (tree decl)
+{
+ enum omp_clause_default_kind ret = cxx_omp_predetermined_sharing_1 (decl);
+ if (ret != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+ return ret;
+
+ /* Predetermine artificial variables holding integral values, those
+ are usually result of gimplify_one_sizepos or SAVE_EXPR
+ gimplification. */
+ if (VAR_P (decl)
+ && DECL_ARTIFICIAL (decl)
+ && INTEGRAL_TYPE_P (TREE_TYPE (decl))
+ && !(DECL_LANG_SPECIFIC (decl)
+ && DECL_OMP_PRIVATIZED_MEMBER (decl)))
+ return OMP_CLAUSE_DEFAULT_SHARED;
+
+ return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
/* Finalize an implicitly determined clause. */
--- gcc/cp/semantics.c (revision 260155)
+++ gcc/cp/semantics.c (revision 260156)
@@ -7297,7 +7297,7 @@ finish_omp_clauses (tree clauses, enum c
if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
share_name = "threadprivate";
- else switch (cxx_omp_predetermined_sharing (t))
+ else switch (cxx_omp_predetermined_sharing_1 (t))
{
case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
break;
--- gcc/cp/cp-tree.h (revision 260155)
+++ gcc/cp/cp-tree.h (revision 260156)
@@ -7383,6 +7383,7 @@ extern int cp_gimplify_expr (tree
*, g
gimple_seq *);
extern void cp_genericize (tree);
extern bool cxx_omp_const_qual_no_mutable (tree);
+extern enum omp_clause_default_kind cxx_omp_predetermined_sharing_1 (tree);
extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
extern tree cxx_omp_clause_default_ctor (tree, tree, tree);
extern tree cxx_omp_clause_copy_ctor (tree, tree, tree);
--- gcc/testsuite/c-c++-common/gomp/pr85696.c (nonexistent)
+++ gcc/testsuite/c-c++-common/gomp/pr85696.c (revision 260156)
@@ -0,0 +1,20 @@
+/* PR c/85696 */
+
+#ifndef __cplusplus
+void
+foo (int n, int a[][n])
+{
+ #pragma omp parallel shared(a) default(none)
+ #pragma omp master
+ a[23][0] = 42;
+}
+#endif
+
+void
+bar (int n, void *p)
+{
+ int (*a)[n] = (int (*)[n]) p;
+ #pragma omp parallel shared(a) default(none)
+ #pragma omp master
+ a[23][0] = 42;
+}
2018-05-30 Jakub Jelinek <[email protected]>
Backported from mainline
2018-05-14 Jakub Jelinek <[email protected]>
PR target/85756
* config/i386/i386.md: Disallow non-commutative arithmetics in
last twpeephole for mem {+,-,&,|,^}= x; mem != 0 after cmpelim
optimization. Use COMMUTATIVE_ARITH_P test rather than != MINUS
in the peephole2 before it.
* gcc.c-torture/execute/pr85756.c: New test.
--- gcc/config/i386/i386.md (revision 260230)
+++ gcc/config/i386/i386.md (revision 260231)
@@ -19370,7 +19370,7 @@ (define_peephole2
(set (match_dup 1) (match_dup 0))
(set (reg FLAGS_REG) (compare (match_dup 0) (const_int 0)))]
"(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
- && GET_CODE (operands[2]) != MINUS
+ && COMMUTATIVE_ARITH_P (operands[2])
&& peep2_reg_dead_p (3, operands[0])
&& !reg_overlap_mentioned_p (operands[0], operands[1])
&& ix86_match_ccmode (peep2_next_insn (2),
@@ -19400,11 +19400,11 @@ (define_peephole2
(set (match_dup 0) (match_dup 2))])
(set (match_dup 1) (match_dup 0))]
"(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && COMMUTATIVE_ARITH_P (operands[2])
&& peep2_reg_dead_p (2, operands[0])
&& !reg_overlap_mentioned_p (operands[0], operands[1])
&& ix86_match_ccmode (peep2_next_insn (0),
- (GET_CODE (operands[2]) == PLUS
- || GET_CODE (operands[2]) == MINUS)
+ GET_CODE (operands[2]) == PLUS
? CCGOCmode : CCNOmode)"
[(parallel [(set (match_dup 3) (match_dup 5))
(set (match_dup 1) (match_dup 4))])]
--- gcc/testsuite/gcc.c-torture/execute/pr85756.c (nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr85756.c (revision 260231)
@@ -0,0 +1,50 @@
+/* PR target/85756 */
+
+#if __CHAR_BIT__ == 8 && __SIZEOF_SHORT__ == 2 && __SIZEOF_INT__ == 4
+int a, c, *e, f, h = 10;
+short b;
+unsigned int p;
+
+__attribute__((noipa)) void
+bar (int a)
+{
+ asm volatile ("" : : "r" (a) : "memory");
+}
+
+void
+foo ()
+{
+ unsigned j = 1, m = 430523;
+ int k, n = 1, *l = &h;
+lab:
+ p = m;
+ m = -((~65535U | j) - n);
+ f = b << ~(n - 8);
+ n = (m || b) ^ f;
+ j = p;
+ if (p < m)
+ *l = k < 3;
+ if (!n)
+ l = &k;
+ if (c)
+ {
+ bar (a);
+ goto lab;
+ }
+ if (!*l)
+ *e = 1;
+}
+
+int
+main ()
+{
+ foo ();
+ return 0;
+}
+#else
+int
+main ()
+{
+ return 0;
+}
+#endif
2018-05-30 Jakub Jelinek <[email protected]>
Backported from mainline
2018-05-29 Jakub Jelinek <[email protected]>
PR c++/85952
* init.c (build_aggr_init): For structured binding initialized from
array call mark_rvalue_use on the initializer.
* g++.dg/warn/Wunused-var-33.C: New test.
--- gcc/cp/init.c (revision 260898)
+++ gcc/cp/init.c (revision 260899)
@@ -1678,6 +1678,7 @@ build_aggr_init (tree exp, tree init, in
if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp))
{
from_array = 1;
+ init = mark_rvalue_use (init);
if (init && DECL_P (init)
&& !(flags & LOOKUP_ONLYCONVERTING))
{
--- gcc/testsuite/g++.dg/warn/Wunused-var-33.C (nonexistent)
+++ gcc/testsuite/g++.dg/warn/Wunused-var-33.C (revision 260899)
@@ -0,0 +1,37 @@
+// PR c++/85952
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wunused-but-set-variable" }
+
+int
+foo ()
+{
+ int a[2] = {1, 2}; // { dg-bogus "set but not used" } */
+ auto [x, y] = a; // { dg-warning "structured bindings only available
with" "" { target c++14_down } }
+ return x + y;
+}
+
+struct S { int d, e; };
+
+int
+bar ()
+{
+ S a = {1, 2};
+ auto [x, y] = a; // { dg-warning "structured bindings only available
with" "" { target c++14_down } }
+ return x + y;
+}
+
+int
+baz ()
+{
+ S a = {1, 2};
+ auto & [x, y] = a; // { dg-warning "structured bindings only available
with" "" { target c++14_down } }
+ return x + y;
+}
+
+int
+qux ()
+{
+ int a[2] = {1, 2};
+ auto & [x, y] = a; // { dg-warning "structured bindings only available
with" "" { target c++14_down } }
+ return x + y;
+}