bpf: (zext32 (zext32 X)) -> (zext32 X) SCEV simplification rule

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 <eddyz87@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261026-scev-simpler-clamp-v2-5-f373aec9825f@gmail.com
This commit is contained in:
Eduard Zingerman 2026-10-26 16:38:25 -07:00 committed by Alexei Starovoitov
parent 86d654957d
commit abc9a76a88
No known key found for this signature in database

View File

@ -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;
}