Hi! compute_access_stride does: tree ref = DR_REF (dr); tree scev_base = build_fold_addr_expr (ref); but that really isn't valid for bitfield drs, where we can't take addresses of the bitfield. As I understood this function only wants to compute strides, so constant bit offsets shouldn't make a difference, therefore this patch attempts to deal with those the cheapest way by just using the struct address it is component of instead for the purposes of stride computation. If the bitfield is in a VLA structure, we can use the DECL_BIT_FIELD_REPRESENTATIVE, otherwise punt.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-12-09 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/83337 * gimple-loop-interchange.cc (compute_access_stride): Handle bitfield DRs properly. * gcc.dg/tree-ssa/loop-interchange-14.c: New test. * gcc.dg/tree-ssa/loop-interchange-15.c: New test. --- gcc/gimple-loop-interchange.cc.jj 2017-12-08 12:27:11.000000000 +0100 +++ gcc/gimple-loop-interchange.cc 2017-12-09 14:11:17.271026901 +0100 @@ -1291,6 +1291,30 @@ compute_access_stride (struct loop *loop gcc_assert (loop == bb->loop_father); tree ref = DR_REF (dr); + if (TREE_CODE (ref) == COMPONENT_REF + && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))) + { + /* We can't take address of bitfields. If the bitfield is at constant + offset from the start of the struct, just use address of the + struct, for analysis of the strides that shouldn't matter. */ + if (!TREE_OPERAND (ref, 2) + || TREE_CODE (TREE_OPERAND (ref, 2)) == INTEGER_CST) + ref = TREE_OPERAND (ref, 0); + /* Otherwise, if we have a bit field representative, use that. */ + else if (DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (ref, 1)) + != NULL_TREE) + { + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (ref, 1)); + ref = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (ref, 0), + repr, TREE_OPERAND (ref, 2)); + } + /* Otherwise punt. */ + else + { + dr->aux = strides; + return; + } + } tree scev_base = build_fold_addr_expr (ref); tree scev = analyze_scalar_evolution (loop, scev_base); scev = instantiate_scev (loop_preheader_edge (loop_nest), loop, scev); --- gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-14.c.jj 2017-12-09 14:03:38.567556128 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-14.c 2017-12-09 14:10:07.089889192 +0100 @@ -0,0 +1,60 @@ +/* PR tree-optimization/83337 */ +/* { dg-do run { target int32plus } } */ +/* { dg-options "-O2 -floop-interchange -fdump-tree-linterchange-details" } */ + +/* Copied from graphite/interchange-5.c */ + +#define DEBUG 0 +#if DEBUG +#include <stdio.h> +#endif + +#define N 100 +#define M 1111 +struct S { int a : 3; int b : 17; int c : 12; }; +struct S A[N][M]; + +static int __attribute__((noinline)) +foo (void) +{ + int i, j; + + for( i = 0; i < M; i++) + for( j = 0; j < N; j++) + A[j][i].b = 5 * A[j][i].b; + + return A[0][0].b + A[N-1][M-1].b; +} + +extern void abort (); + +static void __attribute__((noinline)) +init (int i) +{ + int j; + + for (j = 0; j < M; j++) + A[i][j].b = 2; +} + +int +main (void) +{ + int i, j, res; + + for (i = 0; i < N; i++) + init (i); + + res = foo (); + +#if DEBUG + fprintf (stderr, "res = %d \n", res); +#endif + + if (res != 20) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "Loop_pair<outer:., inner:.> is interchanged" 1 "linterchange"} } */ --- gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-15.c.jj 2017-12-09 16:43:44.469944977 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/loop-interchange-15.c 2017-12-09 20:14:20.469419342 +0100 @@ -0,0 +1,53 @@ +/* PR tree-optimization/83337 */ +/* { dg-do run { target int32plus } } */ +/* { dg-options "-O2 -floop-interchange" } */ + +/* Copied from graphite/interchange-5.c */ + +#define DEBUG 0 +#if DEBUG +#include <stdio.h> +#endif + +#define N 100 +#define M 1111 + +extern void abort (); + +static void __attribute__((noipa)) +foo (int n) +{ + int i, j; + struct S { char d[n]; int a : 3; int b : 17; int c : 12; }; + struct S A[N][M]; + + for (i = 0; i < N; i++) + { + asm volatile ("" : : "g" (&A[0][0]) : "memory"); + for (j = 0; j < M; j++) + A[i][j].b = 2; + } + asm volatile ("" : : "g" (&A[0][0]) : "memory"); + + for (i = 0; i < M; i++) + for (j = 0; j < N; j++) + A[j][i].b = 5 * A[j][i].b; + + asm volatile ("" : : "g" (&A[0][0]) : "memory"); + int res = A[0][0].b + A[N-1][M-1].b; + +#if DEBUG + fprintf (stderr, "res = %d \n", res); +#endif + + if (res != 20) + abort (); +} + +int +main (void) +{ + foo (1); + foo (8); + return 0; +} Jakub