https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103721
Jeffrey A. Law <law at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |law at gcc dot gnu.org --- Comment #4 from Jeffrey A. Law <law at gcc dot gnu.org> --- But what doesn't make any sense here is the folding in this block: <bb 9> [local count: 1073741824]: # searchVolume_5 = PHI <searchVolume_11(8), world_7(D)(2)> # currentVolume_6 = PHI <currentVolume_8(8), 0(2)> _2 = searchVolume_5 != currentVolume_6; _3 = searchVolume_5 != 0; _4 = _2 & _3; if (_4 != 0) goto <bb 3>; [89.00%] else goto <bb 7>; [11.00%] In fold_using_range::range_of_range_op we have: (gdb) p debug_tree (op1) <ssa_name 0x7ffff77fef30 type <integer_type 0x7ffff780e5e8 int sizes-gimplified public SI size <integer_cst 0x7ffff77f3f90 constant 32> unit-size <integer_cst 0x7ffff77f3fa8 constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set 1 canonical-type 0x7ffff780e5e8 precision:32 min <integer_cst 0x7ffff77f3f48 -2147483648> max <integer_cst 0x7ffff77f3f60 2147483647> pointer_to_this <pointer_type 0x7ffff7816a80>> visited var <var_decl 0x7ffff7a12cf0 searchVolume> def_stmt searchVolume_5 = PHI <searchVolume_11(8), world_7(D)(2)> version:5> $113 = void (gdb) p debug_tree (op2) <ssa_name 0x7ffff77fef78 type <integer_type 0x7ffff780e5e8 int sizes-gimplified public SI size <integer_cst 0x7ffff77f3f90 constant 32> unit-size <integer_cst 0x7ffff77f3fa8 constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set 1 canonical-type 0x7ffff780e5e8 precision:32 min <integer_cst 0x7ffff77f3f48 -2147483648> max <integer_cst 0x7ffff77f3f60 2147483647> pointer_to_this <pointer_type 0x7ffff7816a80>> visited var <var_decl 0x7ffff7a12d80 currentVolume> def_stmt currentVolume_6 = PHI <currentVolume_8(8), 0(2)> version:6> $114 = void (gdb) p rel $115 = EQ_EXPR If I'm reading the code correctly I think that means that the ranger has determined that _5 and _6 are equal. But I don't see how it can possibly make that determination with this CFG: int f (int world) { int currentVolume; int searchVolume; int ipos.0_1; _Bool _2; _Bool _3; _Bool _4; ;; basic block 2, loop depth 0 ;; pred: ENTRY goto <bb 9>; [100.00%] ;; succ: 9 ;; basic block 3, loop depth 1 ;; pred: 9 ipos.0_1 = ipos; if (ipos.0_1 != 0) goto <bb 8>; [50.00%] else goto <bb 4>; [50.00%] ;; succ: 8 ;; 4 ;; basic block 4, loop depth 1 ;; pred: 3 ;; succ: 8 ;; basic block 8, loop depth 1 ;; pred: 4 ;; 3 # searchVolume_11 = PHI <1(4), 0(3)> # currentVolume_8 = PHI <searchVolume_5(4), searchVolume_5(3)> ;; succ: 9 ;; basic block 9, loop depth 1 ;; pred: 8 ;; 2 # searchVolume_5 = PHI <searchVolume_11(8), world_7(D)(2)> # currentVolume_6 = PHI <currentVolume_8(8), 0(2)> _2 = searchVolume_5 != currentVolume_6; _3 = searchVolume_5 != 0; _4 = _2 & _3; if (_4 != 0) goto <bb 3>; [89.00%] else goto <bb 7>; [11.00%] ;; succ: 3 ;; 7 ;; basic block 7, loop depth 0 ;; pred: 9 return currentVolume_6; ;; succ: EXIT } This feels like it's got to be a problem in the equivalence handling -- it's largely outside the threader. My recollection of equivalences in loops is that they're exceedingly hard to get correct once you follow the backedge -- particularly since you have to invalidate some equivalences once you traverse that backedge. Finding the set that needed to be invalidated was expensive and the book keeping turned out to be too hard to do reliably so I ripped it all out. How does equivalence handling in the Ranger world work once you traverse the backedge of a loop?