We recently changes tree-ssa-dse.c to not trim stores outside the bounds
of the referenced object.  This is generally a good thing.

However, there are cases where the object doesn't have a usable size.
We see this during kernel builds, at least on the microblaze target.

We've got...

_1 = p_47(D)->stack;
childregs_48 = &MEM[(void *)_1 + 8040B];
[ ... ]
memset (childregs_48, 0, 152);
[ ... ]
MEM[(struct pt_regs *)_1 + 8040B].pt_mode = 1;


We want to trim the memset call as the assignment to pt_mode is the last
word written by the memset call, thus making the store of that word via
memset dead.

Our ref->base is:

(gdb) p debug_tree ($66)
 <mem_ref 0x7fffe8b946e0
    type <void_type 0x7fffe9e210a8 void VOID
        align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7fffe9e210a8
        pointer_to_this <pointer_type 0x7fffe9e21150>>

    arg:0 <ssa_name 0x7fffe8f8a2d0
        type <pointer_type 0x7fffe9e21150 type <void_type 0x7fffe9e210a8
void>
            public unsigned SI
            size <integer_cst 0x7fffe9e0d678 constant 32>
            unit-size <integer_cst 0x7fffe9e0d690 constant 4>
            align:32 warn_if_not_align:0 symtab:0 alias-set 8
canonical-type 0x7fffe9e21150 context <translation_unit_decl
0x7fffe8f72438 /tmp/process.i>
            pointer_to_this <pointer_type 0x7fffe9e28bd0>
reference_to_this <reference_type 0x7fffe9e282a0>>
        visited
        def_stmt _1 = p_47(D)->stack;
        version:1
        ptr-info 0x7fffe8f65fa8>
    arg:1 <integer_cst 0x7fffe8f65f60 type <pointer_type 0x7fffe9e21150>
constant 8040>>


Note the void type.  Those do not have a suitable TYPE_SIZE_UNIT, thus
causing an ICE when we try to reference it within compute_trims:
    /* But don't trim away out of bounds accesses, as this defeats
         proper warnings.  */
      if (*trim_tail
          && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
                               last_orig) <= 0)


The fix is obvious enough.  Don't do the check when the underlying type
has no usable TYPE_SIZE_UNIT.

I pondered moving the tests into the code that determines whether or not
we do byte tracking DSE, but decided the current location was fine.

Bootstrapped and regression tested on x86.  Also verified the original
testfile will build with a microblaze cross compiler.

Installing on the trunk momentarily.

jeff
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac46b7422bc..a8ab83580b5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2018-08-27  Jeff Law  <l...@redhat.com>
+
+       * tree-ssa-dse.c (compute_trims): Handle case where the reference's
+       type does not have a TYPE_SIZE_UNIT.
+
 2018-08-27  Steve Ellcey  <sell...@cavium.com>
 
        * config/aarch64/aarch64-speculation.cc: Replace include of cfg.h
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 824372c346a..6410f4638cc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2018-08-27  Jeff Law  <l...@redhat.com>
+
+       * gcc.c-torture/compile/dse.c: New test.
+
 2018-08-27  Jakub Jelinek  <ja...@redhat.com>
 
        PR c++/86993
diff --git a/gcc/testsuite/gcc.c-torture/compile/dse.c 
b/gcc/testsuite/gcc.c-torture/compile/dse.c
new file mode 100644
index 00000000000..908e6503eb4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/dse.c
@@ -0,0 +1,19 @@
+typedef unsigned long microblaze_reg_t;
+struct pt_regs
+{
+  microblaze_reg_t msr;
+  int pt_mode;
+};
+struct task_struct
+{
+  void *stack;
+};
+int
+copy_thread (struct task_struct *p)
+{
+  struct pt_regs *childregs =
+    (((struct pt_regs *) ((1 << 13) + ((void *) (p)->stack))) - 1);
+  memset (childregs, 0, sizeof (struct pt_regs));
+  childregs->pt_mode = 1;
+}
+
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 016aa6cc97c..bddbbe8377a 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -252,6 +252,7 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, 
int *trim_tail,
       /* But don't trim away out of bounds accesses, as this defeats
         proper warnings.  */
       if (*trim_tail
+         && TYPE_SIZE_UNIT (TREE_TYPE (ref->base))
          && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
                               last_orig) <= 0)
        *trim_tail = 0;

Reply via email to