From: Richard Biener Date: Mon, 18 Sep 2017 13:14:45 +0000 (+0000) Subject: Backport PRs 64516, 68528, 80171, 80362 X-Git-Tag: releases/gcc-5.5.0~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38f38646d3c0b82ab77f61ae72826fd607fff1a5;p=thirdparty%2Fgcc.git Backport PRs 64516, 68528, 80171, 80362 2017-09-18 Richard Biener Backport from mainline 2017-04-10 Richard Biener PR middle-end/80362 * fold-const.c (fold_binary_loc): Look at unstripped ops when looking for NEGATE_EXPR in -A / -B to A / B folding. * gcc.dg/torture/pr80362.c: New testcase. 2015-11-25 Richard Biener PR middle-end/68528 * fold-const.c (fold_binary_loc): Do not call negate_expr_p on stripped operands. * gcc.dg/torture/pr68528.c: New testcase. 2017-03-27 Richard Biener PR middle-end/80171 * gimple-fold.c (fold_ctor_reference): Properly guard against NULL return value from canonicalize_constructor_val. * g++.dg/torture/pr80171.C: New testcase. 2016-06-13 Richard Biener PR middle-end/64516 * fold-const.c (fold_unary_loc): Preserve alignment when folding a VIEW_CONVERT_EXPR into a MEM_REF. * gcc.dg/align-3.c: New testcase. From-SVN: r252926 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 60a389b781a6..4a8c62ef50e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2017-09-18 Richard Biener + + Backport from mainline + 2017-04-10 Richard Biener + + PR middle-end/80362 + * fold-const.c (fold_binary_loc): Look at unstripped ops when + looking for NEGATE_EXPR in -A / -B to A / B folding. + + 2015-11-25 Richard Biener + + PR middle-end/68528 + * fold-const.c (fold_binary_loc): Do not call negate_expr_p + on stripped operands. + + 2017-03-27 Richard Biener + + PR middle-end/80171 + * gimple-fold.c (fold_ctor_reference): Properly guard against + NULL return value from canonicalize_constructor_val. + + 2016-06-13 Richard Biener + + PR middle-end/64516 + * fold-const.c (fold_unary_loc): Preserve alignment when + folding a VIEW_CONVERT_EXPR into a MEM_REF. + 2017-09-16 Jakub Jelinek Backported from mainline diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 7adefba83cbc..8fa6e489f525 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8152,8 +8152,13 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) case VIEW_CONVERT_EXPR: if (TREE_CODE (op0) == MEM_REF) - return fold_build2_loc (loc, MEM_REF, type, - TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); + { + if (TYPE_ALIGN (TREE_TYPE (op0)) != TYPE_ALIGN (type)) + type = build_aligned_type (type, TYPE_ALIGN (TREE_TYPE (op0))); + tem = fold_build2_loc (loc, MEM_REF, type, + TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); + return tem; + } return NULL_TREE; @@ -10574,13 +10579,12 @@ fold_binary_loc (location_t loc, } /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */ if (TREE_CODE (arg0) == NEGATE_EXPR - && negate_expr_p (arg1) + && negate_expr_p (op1) && reorder_operands_p (arg0, arg1)) return fold_build2_loc (loc, MINUS_EXPR, type, - fold_convert_loc (loc, type, - negate_expr (arg1)), - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 0))); + negate_expr (op1), + fold_convert_loc (loc, type, + TREE_OPERAND (arg0, 0))); /* X - (X / Y) * Y is X % Y. */ if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) @@ -10679,17 +10683,16 @@ fold_binary_loc (location_t loc, } /* A - B -> A + (-B) if B is easily negatable. */ - if (negate_expr_p (arg1) - && !TYPE_OVERFLOW_SANITIZED (type) + if (negate_expr_p (op1) + && ! TYPE_OVERFLOW_SANITIZED (type) && ((FLOAT_TYPE_P (type) /* Avoid this transformation if B is a positive REAL_CST. */ - && (TREE_CODE (arg1) != REAL_CST - || REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))) + && (TREE_CODE (op1) != REAL_CST + || REAL_VALUE_NEGATIVE (TREE_REAL_CST (op1)))) || INTEGRAL_TYPE_P (type))) return fold_build2_loc (loc, PLUS_EXPR, type, - fold_convert_loc (loc, type, arg0), - fold_convert_loc (loc, type, - negate_expr (arg1))); + fold_convert_loc (loc, type, arg0), + negate_expr (op1)); /* Try folding difference of addresses. */ { @@ -10757,15 +10760,14 @@ fold_binary_loc (location_t loc, if (! FLOAT_TYPE_P (type)) { /* Transform x * -C into -x * C if x is easily negatable. */ - if (TREE_CODE (arg1) == INTEGER_CST - && tree_int_cst_sgn (arg1) == -1 - && negate_expr_p (arg0) - && (tem = negate_expr (arg1)) != arg1 - && !TREE_OVERFLOW (tem)) + if (TREE_CODE (op1) == INTEGER_CST + && tree_int_cst_sgn (op1) == -1 + && negate_expr_p (op0) + && (tem = negate_expr (op1)) != op1 + && ! TREE_OVERFLOW (tem)) return fold_build2_loc (loc, MULT_EXPR, type, - fold_convert_loc (loc, type, - negate_expr (arg0)), - tem); + fold_convert_loc (loc, type, + negate_expr (op0)), tem); /* (a * (1 << b)) is (a << b) */ if (TREE_CODE (arg1) == LSHIFT_EXPR @@ -11940,8 +11942,8 @@ fold_binary_loc (location_t loc, /* Convert -A / -B to A / B when the type is signed and overflow is undefined. */ if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type)) - && TREE_CODE (arg0) == NEGATE_EXPR - && negate_expr_p (arg1)) + && TREE_CODE (op0) == NEGATE_EXPR + && negate_expr_p (op1)) { if (INTEGRAL_TYPE_P (type)) fold_overflow_warning (("assuming signed overflow does not occur " @@ -11949,14 +11951,13 @@ fold_binary_loc (location_t loc, "division"), WARN_STRICT_OVERFLOW_MISC); return fold_build2_loc (loc, code, type, - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 0)), - fold_convert_loc (loc, type, - negate_expr (arg1))); + fold_convert_loc (loc, type, + TREE_OPERAND (arg0, 0)), + negate_expr (op1)); } if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type)) - && TREE_CODE (arg1) == NEGATE_EXPR - && negate_expr_p (arg0)) + && TREE_CODE (op1) == NEGATE_EXPR + && negate_expr_p (op0)) { if (INTEGRAL_TYPE_P (type)) fold_overflow_warning (("assuming signed overflow does not occur " @@ -11964,10 +11965,9 @@ fold_binary_loc (location_t loc, "division"), WARN_STRICT_OVERFLOW_MISC); return fold_build2_loc (loc, code, type, - fold_convert_loc (loc, type, - negate_expr (arg0)), - fold_convert_loc (loc, type, - TREE_OPERAND (arg1, 0))); + negate_expr (op0), + fold_convert_loc (loc, type, + TREE_OPERAND (arg1, 0))); } /* If arg0 is a multiple of arg1, then rewrite to the fastest div diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 7950cb627fd0..dd56cfdeff9d 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5483,9 +5483,12 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset, && !compare_tree_int (TYPE_SIZE (TREE_TYPE (ctor)), size)) { ret = canonicalize_constructor_val (unshare_expr (ctor), from_decl); - ret = fold_unary (VIEW_CONVERT_EXPR, type, ret); if (ret) - STRIP_USELESS_TYPE_CONVERSION (ret); + { + ret = fold_unary (VIEW_CONVERT_EXPR, type, ret); + if (ret) + STRIP_USELESS_TYPE_CONVERSION (ret); + } return ret; } /* For constants and byte-aligned/sized reads try to go through diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc749c6c647e..2bab3a2489de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,26 @@ +2017-09-18 Richard Biener + + Backport from mainline + 2017-04-10 Richard Biener + + PR middle-end/80362 + * gcc.dg/torture/pr80362.c: New testcase. + + 2015-11-25 Richard Biener + + PR middle-end/68528 + * gcc.dg/torture/pr68528.c: New testcase. + + 2017-03-27 Richard Biener + + PR middle-end/80171 + * g++.dg/torture/pr80171.C: New testcase. + + 2016-06-13 Richard Biener + + PR middle-end/64516 + * gcc.dg/align-3.c: New testcase. + 2017-09-18 Martin Liska * gcc.dg/asan/pr81224.c: Remove. diff --git a/gcc/testsuite/g++.dg/torture/pr80171.C b/gcc/testsuite/g++.dg/torture/pr80171.C new file mode 100644 index 000000000000..91cfb3bd8f61 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr80171.C @@ -0,0 +1,184 @@ +// { dg-do compile } +// { dg-additional-options "-std=c++11" } + +template struct remove_reference; +template struct remove_reference<_Tp &> { typedef _Tp type; }; +template typename remove_reference<_Tp>::type move(_Tp &&p1) { + return static_cast::type &&>(p1); +} +void *operator new(__SIZE_TYPE__, void *p2) { return p2; } +struct Trans_NS__v1_GenericTlv { + virtual int getMinimumValueLength(); + virtual unsigned long getValueLength() const; +}; +struct IPv4NeighborAddressSubTlv; +struct Trans_NS__v1_GenericTlvBase : Trans_NS__v1_GenericTlv { + virtual bool operator==(const IPv4NeighborAddressSubTlv &) const; +}; +struct Trans_NS__v1_GenericUnsupportedTlv; +template struct backup_holder { + Trans_NS__v1_GenericUnsupportedTlv *backup_; + Trans_NS__v1_GenericUnsupportedTlv &get() { return *backup_; } +}; +template struct make_reference_content { + typedef IPv4NeighborAddressSubTlv type; +}; +template struct unwrap_recursive { + typedef IPv4NeighborAddressSubTlv type; +}; +template struct begin_impl; +template struct begin { + typedef typename Sequence::tag tag_; + typedef typename begin_impl::template apply::type type; +}; +struct long_ { + static const int value = 0; +}; +template struct O1_size_impl; +template +struct O1_size + : O1_size_impl::template apply {}; +template +struct apply_wrap2 : F::template apply {}; +template struct iter_fold_impl; +template +struct iter_fold_impl<0, First, ForwardOp> { + typedef typename apply_wrap2::type state; +}; +template struct iter_fold { + typedef + typename iter_fold_impl::value, + typename begin::type, ForwardOp>::state + type; +}; +template struct deref; +template struct pair { typedef T1 first; }; +struct make_initializer_node { + template struct apply { + struct initializer_node { + typedef typename deref::type recursive_enabled_T; + static int + initialize(void *p1, + typename unwrap_recursive::type) { + new (p1) typename make_reference_content::type; + } + }; + typedef pair type; + }; +}; +struct l_item { + typedef int tag; + typedef l_item type; + typedef long_ size; + typedef int item; +}; +template <> struct O1_size_impl { + template struct apply : List::size {}; +}; +template struct l_iter; +template struct deref> { + typedef typename Node::item type; +}; +template <> struct begin_impl { + template struct apply { + typedef l_iter type; + }; +}; +template +struct list : l_item {}; +template struct make_variant_list { typedef list type; }; +template T cast_storage(void *p1) { return *static_cast(p1); } +struct visitation_impl_step { + typedef Trans_NS__v1_GenericUnsupportedTlv type; +}; +template +void visitation_impl_invoke_impl(Visitor p1, VoidPtrCV p2, T *) { + backup_holder __trans_tmp_8 = + cast_storage>(p2); + p1.internal_visit(__trans_tmp_8, 0); +} +template +void visitation_impl_invoke(Visitor p1, VoidPtrCV p2, T p3, NoBackupFlag) { + visitation_impl_invoke_impl(p1, p2, p3); +} +template +void visitation_impl(Visitor p1, VoidPtrCV p2, NoBackupFlag, Which, step0 *) { + visitation_impl_invoke(p1, p2, static_cast(0), 0); +} +struct move_into { + move_into(void *); + template void internal_visit(backup_holder p1, int) { + T __trans_tmp_2 = p1.get(); + new (0) T(__trans_tmp_2); + } +}; +template struct variant { + struct initializer : iter_fold::type, + make_initializer_node>::type::first {}; + template void convert_construct(T p1, int) { + void *__trans_tmp_9 = this; + initializer::initialize(__trans_tmp_9, p1); + } + template variant(T p1) { convert_construct(p1, 0); } + variant(variant &&p1) { + move_into visitor(0); + p1.internal_apply_visitor(visitor); + } + template void internal_apply_visitor(Visitor p1) { + void *__trans_tmp_10 = this; + visitation_impl(p1, __trans_tmp_10, 0, 0, + static_cast(0)); + } +}; +template struct generic_element_tlvs; +template +struct generic_element_tlvs { + typedef variant variant_type; +}; +template struct Trans_NS__v1_GenericTlvContainer { + template void addTlv(const TlvClass &); +}; +template +template +void Trans_NS__v1_GenericTlvContainer::addTlv( + const TlvClass &p1) { + typename ElementTlvs::variant_type wrap(p1); + move(wrap); +} +template +struct Trans_NS__v1_GenericContainerEntryBase + : Trans_NS__v1_GenericTlvContainer {}; +template +struct Trans_NS__v1_GenericFixedLengthTlvBase : Trans_NS__v1_GenericTlvBase { + unsigned long getValueLength() const; +}; +struct Trans_NS__v1_GenericUnsupportedTlv : Trans_NS__v1_GenericTlv { + long getHeaderLengthconst; +}; +using isis_tlv_config = int; +template +using isis_element_tlvs = + generic_element_tlvs; +template +using ContainerEntryBase = Trans_NS__v1_GenericContainerEntryBase; +template +using FixedLengthTlvBase = Trans_NS__v1_GenericFixedLengthTlvBase; +struct IPv4NeighborAddressSubTlv + : FixedLengthTlvBase<0, IPv4NeighborAddressSubTlv, 0> { + bool operator==(const IPv4NeighborAddressSubTlv &) const; +}; +void test() { + ContainerEntryBase< + 0, int, + isis_element_tlvs< + FixedLengthTlvBase<0, int, 0>, FixedLengthTlvBase<0, int, 0>, + IPv4NeighborAddressSubTlv, FixedLengthTlvBase<0, int, 0>, + FixedLengthTlvBase<0, int, 0>, FixedLengthTlvBase<0, int, 0>>> + isEntry; + IPv4NeighborAddressSubTlv nbAddressSubTlv; + isEntry.addTlv(nbAddressSubTlv); +} diff --git a/gcc/testsuite/gcc.dg/align-3.c b/gcc/testsuite/gcc.dg/align-3.c new file mode 100644 index 000000000000..5c97d5ac3cc3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/align-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand" } */ + +typedef struct { char a[2]; } __attribute__((__packed__)) TU2; +unsigned short get16_unaligned(const void *p) { + unsigned short v; + *(TU2 *)(void *)(&v) = *(const TU2 *)p; + return v; +} + +/* { dg-final { scan-rtl-dump "MEM\[^\n\r\]*A8\\\]" "expand" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr68528.c b/gcc/testsuite/gcc.dg/torture/pr68528.c new file mode 100644 index 000000000000..d69d600f43bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr68528.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ + +#define INT_MIN ( -__INT_MAX__ - 1 ) + +extern void abort (void); + +int main (void) +{ + int x0 = INT_MIN; + long x1 = 0L; + int x2 = 0; + int t = ( 0 || ( INT_MIN - (int) ( x0 - x1 ) ) ); + + if ( t != 0 ) { x2 = t; abort(); } + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr80362.c b/gcc/testsuite/gcc.dg/torture/pr80362.c new file mode 100644 index 000000000000..6d22eb040ad3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr80362.c @@ -0,0 +1,10 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fstrict-overflow" } */ + +int main() +{ + signed char var_0, var_1 = -128; + var_0 = (signed char)(-var_1) / 3; + if (var_0 > 0) + __builtin_abort(); +}