From 95c18dd0464e8937a7caab76db490597b760c0d4 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sat, 11 Jun 2016 01:58:09 +0200 Subject: [PATCH] fold-const: Don't access bit fields with too big mode (PR71310) Currently, optimize_bit_field_compare reads the bitfield in word_mode if it can. If the bit field is normally accessed in a smaller mode, this might be a violation of the memory model, although the "extra" part of the read is not used. But also, previous stores to the bit field will have been done in the smaller mode, and then bigger loads from it cause a LHS problem. PR middle-end/71310 * fold-const.c (optimize_bit_field_compare): Don't try to use word_mode unconditionally for reading the bit field, look at DECL_BIT_FIELD_REPRESENTATIVE instead. gcc/testsuite/ PR middle-end/71310 * gcc.target/powerpc/pr71310.c: New testcase. From-SVN: r237319 --- gcc/ChangeLog | 7 +++++++ gcc/fold-const.c | 13 +++++++++++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/powerpc/pr71310.c | 23 ++++++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr71310.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 508ff0eb0bc..e463219cdf0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-06-11 Segher Boessenkool + + PR middle-end/71310 + * fold-const.c (optimize_bit_field_compare): Don't try to use + word_mode unconditionally for reading the bit field, look at + DECL_BIT_FIELD_REPRESENTATIVE instead. + 2016-06-11 Kugan Vivekanandarajah PR middle-end/71478 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0b7ea82c034..7f8803ca57d 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3904,13 +3904,24 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, return 0; } + /* Don't use a larger mode for reading the bit field than we will + use in other places accessing the bit field. */ + machine_mode largest_mode = word_mode; + if (TREE_CODE (lhs) == COMPONENT_REF) + { + tree field = TREE_OPERAND (lhs, 1); + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field); + if (repr) + largest_mode = DECL_MODE (repr); + } + /* See if we can find a mode to refer to this field. We should be able to, but fail if we can't. */ nmode = get_best_mode (lbitsize, lbitpos, 0, 0, const_p ? TYPE_ALIGN (TREE_TYPE (linner)) : MIN (TYPE_ALIGN (TREE_TYPE (linner)), TYPE_ALIGN (TREE_TYPE (rinner))), - word_mode, false); + largest_mode, false); if (nmode == VOIDmode) return 0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index deeeff54bb8..2b31ceb5191 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-06-11 Segher Boessenkool + + PR middle-end/71310 + * gcc.target/powerpc/pr71310.c: New testcase. + 2016-06-11 Kugan Vivekanandarajah PR middle-end/71478 diff --git a/gcc/testsuite/gcc.target/powerpc/pr71310.c b/gcc/testsuite/gcc.target/powerpc/pr71310.c new file mode 100644 index 00000000000..6869a500943 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr71310.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-options "-O2" } */ + +/* { dg-final { scan-assembler-not {\mld} } } */ +/* { dg-final { scan-assembler-not {\mlwz} } } */ +/* { dg-final { scan-assembler-times {\mlbz} 2 } } */ + +struct mmu_gather { + long end; + int fullmm : 1; +}; + +void __tlb_reset_range(struct mmu_gather *p1) +{ + if (p1->fullmm) + p1->end = 0; +} + +void tlb_gather_mmu(struct mmu_gather *p1) +{ + p1->fullmm = 1; + __tlb_reset_range(p1); +} -- 2.30.2