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