Hi! Apparently one of the testcases in my recent 6.x backports ICEs on powerpc64le-linux and doesn't on the trunk/7.x.
The following backports fix that, bootstrapped/regtested on x86_64-linux and i686-linux and additionally tested with a cross-compiler on the constexpr-77* and pr71310.c testcases, committed to 6.x branch. 2017-05-09 Jakub Jelinek <ja...@redhat.com> PR testsuite/80678 2016-06-14 Richard Biener <rguent...@suse.de> PR middle-end/71310 PR bootstrap/71510 * expr.h (get_bit_range): Declare. * expr.c (get_bit_range): Export. * fold-const.c (optimize_bit_field_compare): Use get_bit_range and word_mode again to constrain the bitfield access. 2016-06-11 Segher Boessenkool <seg...@kernel.crashing.org> 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.target/powerpc/pr71310.c: New testcase. --- gcc/fold-const.c (revision 237318) +++ gcc/fold-const.c (revision 237426) @@ -3902,9 +3902,19 @@ return 0; } + /* Honor the C++ memory model and mimic what RTL expansion does. */ + unsigned HOST_WIDE_INT bitstart = 0; + unsigned HOST_WIDE_INT bitend = 0; + if (TREE_CODE (lhs) == COMPONENT_REF) + { + get_bit_range (&bitstart, &bitend, lhs, &lbitpos, &offset); + if (offset != NULL_TREE) + return 0; + } + /* 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, + nmode = get_best_mode (lbitsize, lbitpos, bitstart, bitend, const_p ? TYPE_ALIGN (TREE_TYPE (linner)) : MIN (TYPE_ALIGN (TREE_TYPE (linner)), TYPE_ALIGN (TREE_TYPE (rinner))), --- gcc/expr.c (revision 237425) +++ gcc/expr.c (revision 237426) @@ -4795,7 +4795,7 @@ optimize_bitfield_assignment_op (unsigne If the access does not need to be restricted, 0 is returned in both *BITSTART and *BITEND. */ -static void +void get_bit_range (unsigned HOST_WIDE_INT *bitstart, unsigned HOST_WIDE_INT *bitend, tree exp, --- gcc/expr.h (revision 237425) +++ gcc/expr.h (revision 237426) @@ -242,6 +242,10 @@ extern rtx push_block (rtx, int, int); extern bool emit_push_insn (rtx, machine_mode, tree, rtx, unsigned int, int, rtx, int, rtx, rtx, int, rtx, bool); +/* Extract the accessible bit-range from a COMPONENT_REF. */ +extern void get_bit_range (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, + tree, HOST_WIDE_INT *, tree *); + /* Expand an assignment that stores the value of FROM into TO. */ extern void expand_assignment (tree, tree, bool); --- gcc/testsuite/gcc.target/powerpc/pr71310.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/pr71310.c (revision 237319) @@ -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); +} Jakub