The compiler can preserve an induction variable across a call by copying it to a callee-saved register. For example: w1 = 0; loop: w7 = w1; call foo; w1 = w7; w1 += 2; if w7 < 10 goto loop; When building expressions for the loop body, each 32-bit move adds a zero extension: w7 = w1; r7 = (zext32 r1) w1 = w7; r1 = (zext32 (zext32 r1)) w1 += 2; r1 = (zext32 (+ (zext32 (zext32 r1)) 2)) The existing ALU32 simplification rules allow recognizing the header SCEV for r1 as: (zext32 (linear r1 2)) Substituting this SCEV into r7's expression at the latch produces: (zext32 (zext32 (linear r1 2))) Add the simplification rule: (zext32 (zext32 X)) -> (zext32 X) This allows recognizing the saved induction variable in r7 as a 32-bit linear SCEV and computing the loop iteration bound. Signed-off-by: Eduard Zingerman --- kernel/bpf/scev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/bpf/scev.c b/kernel/bpf/scev.c index e3c2220f89c9..12b147faa32a 100644 --- a/kernel/bpf/scev.c +++ b/kernel/bpf/scev.c @@ -1502,6 +1502,10 @@ static int simplify(struct scev *scev, u32 id, void *priv) return t; } + /* (zext32 (zext32 X)) -> (zext32 X) */ + if (is_zext32(scev, id, &a) && is_zext32(scev, a, &b)) + return a; + return id; } -- 2.53.0