https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104547
--- Comment #7 from Andrew Macleod <amacleod at redhat dot com> --- Created attachment 52447 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52447&action=edit proposed patch (In reply to Jakub Jelinek from comment #5) > If you mean with -O3 on the > #include <vector> > > void shrink(std::vector<int>& v, unsigned n) { > if (v.size() < n) > __builtin_unreachable(); > v.resize(v.size() - n); > } > testcase (with -O2 _M_default_append isn't nlined), then I think it is > something that ideally ranger's symbolic handling should figure out but > doesn't. > We have: > long unsigned int _1; > ... > long unsigned int _11; > ... > if (_1 > _11) > goto <bb 3>; [0.00%] > else > goto <bb 4>; [100.00%] > > <bb 3> [count: 0]: > __builtin_unreachable (); > > <bb 4> [local count: 1073741824]: > # RANGE ~[2305843009213693952, 16140901060200890368] > _2 = _11 - _1; > if (_2 > _11) > and we don't figure out that _2 > _11 is always false, because we earlier > assert that _1 <= _11 and so _11 - _1 will not wrap around and so the result > _2 <= _11. Relational : (_1 <= _11) <bb 4> [local count: 1073741824]: _2 = _11 - _1; if (_2 > _11) goto <bb 5>; [33.00%] else goto <bb 6>; [67.00%] Looks like we know _1 is <= _11, but what seems to be missing is the extra relation that _2 > _11 as a result. normally we'd handle this by providing operator_minus::lhs_op1_relation() routine, but unfortunately, it does not currently take a relation between op1 and op2 like the corresponding fold does.. it should be trivial to add it however. The attached patch does the basics... adds the parameter and provides a very simple operator_minus::lhs_op1_relation () which then achieves the goal of the PR. It hasn't been bootstrapped or anything. I didn't try to flush out anything else, or make any enhancements because I don't trust myself at this late stage to get it right :-) Feel free to work with it if you want. ie, I don't even look at the ranges.. if op1 >= op2, we return LHS <= op1. We could also check if the range of op2 does not contain 0, then we could return LSH < OP1. There is probably some sign checking that could be done too. There is also the routine fold uses (minus_op1_op2_relation_effect) which could possibly be leveraged as well, but I don't want to delve into that Note that this will affect all minus operations everywhere... for instance, this patch ends up enabling a much earlier threading pass to eliminate the branch.. so it never makes it to VRP2. I also didn't implement lhs_op2 relation.. again, I don't trust myself to get it right. So I can either package this up and submit it, or someone more trustworthy can take it an run with it and add whatever tweaks you feel are safe.