diff mbox series

[committed] Fix minor bug in recently added sanity test in tree-ssa-dse.c

Message ID 7331c16f-3725-c528-8cd6-7f38bc19f0c2@redhat.com
State New
Headers show
Series [committed] Fix minor bug in recently added sanity test in tree-ssa-dse.c | expand

Commit Message

Jeff Law Aug. 27, 2018, 8:30 p.m. UTC
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

Comments

Richard Biener Aug. 28, 2018, 9:37 a.m. UTC | #1
On Mon, Aug 27, 2018 at 10:31 PM Jeff Law <law@redhat.com> wrote:
>
>
> 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.

Hmm, you seem to get ref->base from an address but you know types
on addresses do not have any meaning, so ...  how does

      /* But don't trim away out of bounds accesses, as this defeats
         proper warnings.

         We could have a type with no TYPE_SIZE_UNIT or we could have a VLA
         where TYPE_SIZE_UNIT is not a constant.  */
      if (*trim_tail
          && TYPE_SIZE_UNIT (TREE_TYPE (ref->base))
          && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (ref->base))) == INTEGER_CST
          && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
                               last_orig) <= 0)
        *trim_tail = 0;

make any sense in the above case where ref->base is even based on a
pointer?  I'd say the
above should be at least

    if (*trim_tail
        && DECL_P (ref->base)
        && ....

?  Not sure if we ever have decls with incomplete types so eventually
the new check
isn't needed.

Richard.

> jeff
Jeff Law Sept. 14, 2018, 9:46 p.m. UTC | #2
On 8/28/18 3:37 AM, Richard Biener wrote:
> On Mon, Aug 27, 2018 at 10:31 PM Jeff Law <law@redhat.com> wrote:
>>
>>
>> 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.
> 
> Hmm, you seem to get ref->base from an address but you know types
> on addresses do not have any meaning, so ...  how does
It doesn't affect correctness.  Essentially when we have information
which indicates there might be an out of bounds write, we leave the
statement as-is.

So if the type specified a smaller size than reality, then we
potentially might suppress an optimization.

If the type specified a large size than reality, then nothing changes.



> 
>       /* But don't trim away out of bounds accesses, as this defeats
>          proper warnings.
> 
>          We could have a type with no TYPE_SIZE_UNIT or we could have a VLA
>          where TYPE_SIZE_UNIT is not a constant.  */
>       if (*trim_tail
>           && TYPE_SIZE_UNIT (TREE_TYPE (ref->base))
>           && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (ref->base))) == INTEGER_CST
>           && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
>                                last_orig) <= 0)
>         *trim_tail = 0;
> 
> make any sense in the above case where ref->base is even based on a
> pointer?  I'd say the
> above should be at least
> 
>     if (*trim_tail
>         && DECL_P (ref->base)
>         && ....
> 
> ?  Not sure if we ever have decls with incomplete types so eventually
> the new check
> isn't needed.
We could have something casted to a void type.  Can't remember where it
happened, but it certainly came up.

jeff
diff mbox series

Patch

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  <law@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  <sellcey@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  <law@redhat.com>
+
+	* gcc.c-torture/compile/dse.c: New test.
+
 2018-08-27  Jakub Jelinek  <jakub@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;