https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113632
Andrew Macleod <amacleod at redhat dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amacleod at redhat dot com --- Comment #1 from Andrew Macleod <amacleod at redhat dot com> --- (In reply to Andrew Pinski from comment #0) > Take: > ``` > void dummy(); > _Bool f(unsigned long a) > { > _Bool cmp = a > 8192; > if (cmp) goto then; else goto e; > then: > unsigned long t = __builtin_clzl(a); // [0,50] > t^=63; // [13,63] > return t >= 13; > e: > dummy(); > return 0; > } > ``` > > Currently after the t^=63; we get: > ``` > # RANGE [irange] int [1, 63] MASK 0x3f VALUE 0x0 > _7 = _1 ^ 63; > ``` > > But this could/should be improved to [13,63]. > > If we change to using minus instead: > ``` > t = 63 - t; > ``` > > We get the better range and the comparison (t >= 13) is optimized away. > ``` > Folding statement: t_10 = 63 - t_9; > Global Exported: t_10 = [irange] long unsigned int [13, 63] MASK 0x3f VALUE > 0x0 > Not folded > ``` > > Yes this should up in real code, see the LLVM issue for more information on > that. I think the current implementation of "operator_bitwise_xor::wi_fold ()" in range-op.cc was simply ported from the original version we used in the old VRP code. so it is neither multi-range awre, nor been enhanced. If you put a break point there, you'll see its getting: (gdb) p lh_lb.dump() [0], precision = 32 $1 = void (gdb) p lh_ub.dump() [0x32], precision = 32 $2 = void (gdb) p rh_ub.dump() [0x3f], precision = 32 $3 = void (gdb) p rh_lb.dump() [0x3f], precision = 32 $4 = void One could conceivable do something much better than the general masking stuff that goes on if rh_lb == rh_ub. I suspect we could probably do a better job in general, but have never looked at it. It also looks like we make some minor attempts with signed values in wi_optimize_signed_bitwise_op (), but again, I do not think anyone has tried to make this code do anything new yet.