https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115934
--- Comment #4 from Tamar Christina <tnfchris at gcc dot gnu.org> --- This one looks a bit like costing, before the patch IVopts had: <Invariant Expressions>: inv_expr 1: -element_7(D) inv_expr 2: (signed int) rite_5(D) - (signed int) element_7(D) and after the patch it generates a few more alternatives: <Invariant Expressions>: inv_expr 1: -element_7(D) inv_expr 2: ((signed int) left_4(D) + (signed int) rite_5(D)) - (signed int) element_7(D) inv_expr 3: (signed int) left_4(D) + (signed int) rite_5(D) inv_expr 4: (signed int) rite_5(D) - (signed int) element_7(D) inv_expr 5: ((signed int) rite_5(D) - (signed int) element_7(D)) + (signed int) left_4(D) inv_expr 6: ((signed int) rite_5(D) + (signed int) element_7(D)) + (signed int) left_4(D) inv_expr 7: ((signed int) left_4(D) - (signed int) element_7(D)) + (signed int) rite_5(D) Before it decided it needed two separate IVs to satisfy these invariants: Initial set of candidates: cost: 122 (complexity 0) reg_cost: 114 cand_cost: 8 cand_group_cost: 0 (complexity 0) candidates: 7, 9 group:0 --> iv_cand:7, cost=(0,0) group:1 --> iv_cand:9, cost=(0,0) group:2 --> iv_cand:9, cost=(0,0) group:3 --> iv_cand:7, cost=(0,0) invariant variables: 1 invariant expressions: 1 Original cost 122 (complexity 0) Final cost 122 (complexity 0) Selected IV set for loop 1 at ../gcc-dsg/gcc/testsuite/gcc.dg/tree-ssa/pr43378.c:7, 10 avg niters, 2 IVs: Candidate 7: Var befor: left_14 Var after: left_10 Incr POS: orig biv IV struct: Type: int Base: left_4(D) Step: element_7(D) Biv: N Overflowness wrto loop niter: Overflow Candidate 9: Depend on inv.exprs: 1 Var befor: rite_15 Var after: rite_8 Incr POS: orig biv IV struct: Type: int Base: rite_5(D) Step: -element_7(D) Biv: N Overflowness wrto loop niter: Overflow with the patch it decided it only needed the one IV: Initial set of candidates: cost: 109 (complexity 0) reg_cost: 97 cand_cost: 4 cand_group_cost: 8 (complexity 0) candidates: 9 group:0 --> iv_cand:9, cost=(4,0) group:1 --> iv_cand:9, cost=(0,0) group:2 --> iv_cand:9, cost=(0,0) group:3 --> iv_cand:9, cost=(4,0) invariant variables: 1 invariant expressions: 1, 3 Initial set of candidates: cost: 109 (complexity 0) reg_cost: 97 cand_cost: 4 cand_group_cost: 8 (complexity 0) candidates: 9 group:0 --> iv_cand:9, cost=(4,0) group:1 --> iv_cand:9, cost=(0,0) group:2 --> iv_cand:9, cost=(0,0) group:3 --> iv_cand:9, cost=(4,0) invariant variables: 1 invariant expressions: 1, 3 Original cost 109 (complexity 0) Final cost 109 (complexity 0) Selected IV set for loop 1 at ../gcc-dsg/gcc/testsuite/gcc.dg/tree-ssa/pr43378.c:7, 10 avg niters, 1 IVs: Candidate 9: Depend on inv.exprs: 1 Var befor: rite_15 Var after: rite_8 Incr POS: orig biv IV struct: Type: int Base: rite_5(D) Step: -element_7(D) Biv: N Overflowness wrto loop niter: Overflow It realizes it can satisfy both IVs using 1 candidate and picks it because it thinks the costs are much lower. I don't however see an implementation of TARGET_ADDRESS_COST for the target. On AArch64 for instance this is rejected by costing because the combined IV requires more registers: Initial set of candidates: cost: 17 (complexity 0) reg_cost: 5 cand_cost: 4 cand_group_cost: 8 (complexity 0) candidates: 9 group:0 --> iv_cand:9, cost=(4,0) group:1 --> iv_cand:9, cost=(0,0) group:2 --> iv_cand:9, cost=(0,0) group:3 --> iv_cand:9, cost=(4,0) invariant variables: 1 invariant expressions: 1, 3 Improved to: cost: 14 (complexity 0) reg_cost: 6 cand_cost: 8 cand_group_cost: 0 (complexity 0) candidates: 7, 9 group:0 --> iv_cand:7, cost=(0,0) group:1 --> iv_cand:9, cost=(0,0) group:2 --> iv_cand:9, cost=(0,0) group:3 --> iv_cand:7, cost=(0,0) invariant variables: 1 invariant expressions: 1 Original cost 14 (complexity 0) Final cost 14 (complexity 0) Selected IV set for loop 1 at /app/example.c:4, 10 avg niters, 2 IVs: I'll have to take a look at what happens when a target has no cost model for IVopts.