https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108385

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |12.3
             Blocks|                            |85316
                 CC|                            |aldyh at gcc dot gnu.org,
                   |                            |amacleod at redhat dot com
           Keywords|                            |missed-optimization

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
<bb 2> [local count: 118111600]:
_1 = params_3(D)->ptrType1;
err = anotherMethod (_1); [return slot optimization]
_31 = err._size;
_32 = (sizetype) _31;
iftmp.0_33 = _32 * 8;
_34 = operator new [] (iftmp.0_33);

<bb 3> [local count: 118111600]:
aItr_35 = err._data;
if (iftmp.0_33 != 0)
  goto <bb 4>; [89.00%]
else
  goto <bb 7>; [11.00%]

<bb 4> [local count: 105119324]:
__builtin_memcpy (_34, aItr_35, iftmp.0_33);
sum_9 = MEM[(double *)_34];
_38 = _34 + iftmp.0_33;
if (_34 != _38)
  goto <bb 5>; [89.00%]
else
  goto <bb 6>; [11.00%]

(gdb) p debug_bb_n (6)
<bb 6> [local count: 1271944]:
operator delete [] (_38);
goto <bb 10>; [100.00%]

there's a missed optimization.  We are on the path iftmp.0_33 != 0 so
the _34 != _38 check should evaluate to true and BB 6 with the deallocation
be unreachable.

The "fix" on trunk looks bogus and more like a missed optimization somewhere
causing this not to be exposed.

At VRP2 time we see

  <bb 3> [local count: 118111600]:
  aItr_35 = err._data;
  endp_39 = aItr_35 + iftmp.0_33;
  if (aItr_35 != endp_39)

and

  _38 = _34 + iftmp.0_33;
  if (_38 != _34)

it looks like we fail to infer a range for iftmp.0_33 from the BB3 condition
and fail to use that to simplify the later check.

The first check is rewritten to iftmp.0_33 != 0 by forwprop4 but that
doesn't rewrite the later check, likely because _39 has a single-use
but _38 does not.  On trunk both are rewritten to iftmp.0_33 != 0 by

 (simplify
  (op:c (nop_convert?@3 (pointer_plus@2 (convert1? @0) @1)) (convert2? @0))
  (if (tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0))
       && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0))
       && (CONSTANT_CLASS_P (@1) || (single_use (@2) && single_use (@3))))
   (op @1 { build_zero_cst (TREE_TYPE (@1)); }))))

because _38 there _is_ a single use, likely due to that missed optimization
(jump threading?).

As said, the question is why we do not derive a range for iftmp.0_33 here
("here" is the minF function).  The dumps say on trunk

=========== BB 3 ============
Imports: iftmp.0_33  aItr_35 
Exports: iftmp.0_33  aItr_35  endp_39
         endp_39 : iftmp.0_33(I)  aItr_35(I)
iftmp.0_33      [irange] long unsigned int [0, 34359738360] NONZERO 0x7fffffff8
Equivalence set : [endp_39]
Equivalence set : [aItr_35]
    <bb 3> [local count: 118111600]:
    aItr_35 = err._data;
    endp_39 = aItr_35 + iftmp.0_33;
    if (aItr_35 != endp_39)
      goto <bb 4>; [89.00%]
    else
      goto <bb 7>; [11.00%]

3->4  (T) iftmp.0_33 :  [irange] long unsigned int [0, 34359738360] NONZERO
0x7fffffff8 
3->7  (F) iftmp.0_33 :  [irange] long unsigned int [0, 34359738360] NONZERO
0x7fffffff8

huh, so why for aItr_35 == endp_39 is the iftmp.0_33 range not zero?!

=========== BB 4 ============
Imports: iftmp.0_33  _34  
Exports: _16  iftmp.0_33  _34
         _15 : aItr_35(I)  
         _16 : iftmp.0_33(I)  _34(I)
         _47 : endp_39(I)   
_15     [irange] unsigned long [1, +INF]
iftmp.0_33      [irange] long unsigned int [0, 34359738360] NONZERO 0x7fffffff8
aItr_35 [irange] double * [1, +INF]
endp_39 [irange] double * VARYING
Equivalence set : [sum_9]
Equivalence set : [_16]
Partial equiv (_15 pe64 aItr_35)
Partial equiv (_47 pe64 endp_39)
Relational : (aItr_35 != endp_39)


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85316
[Bug 85316] [meta-bug] VRP range propagation missed cases

Reply via email to