From: Eduard Zingerman <eddyz87@gmail.com>
To: bot+bpf-ci@kernel.org, bpf@vger.kernel.org, ast@kernel.org
Cc: andrii@kernel.org, daniel@iogearbox.net, kernel-team@fb.com,
yonghong.song@linux.dev, martin.lau@kernel.org,
mason@kernel.org, ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next v3 19/51] bpf: representation for intervals with steps
Date: Fri, 09 Oct 2026 11:55:21 -0700 [thread overview]
Message-ID: <faf14259573df35d2fc49a8445be5cd79a0a8565.camel@gmail.com> (raw)
In-Reply-To: <debf620cc082978bcb926bf13fa5af72f46e25607f0ca9289f4bb41ca15530d3@mail.kernel.org>
On Fri, 2026-10-09 at 12:07 +0000, bot+bpf-ci@kernel.org wrote:
> > bpf: representation for intervals with steps
>
> TL;DR:
> - Commit message says eq/neq branches ignore base/step, but they appear to
> change branch pruning
> - Comment in reg_bounds_sync() names reg_umin() where reg_smin() seems
> intended (nit)
>
> > bpf: representation for intervals with steps
> >
> > Extend scalar register tracking with a linear "base + step * k" description:
> > each scalar carries two u16 fields, base and step (invariant: base < step),
> > recording that its value is some point on the line base + step * k.
> > A fresh scalar starts as base=0, step=1, i.e. any integer.
> >
> > This lets the verifier reason about strided values, e.g. an index multiplied
> > by an element size, which neither the min/max bounds nor the tnum can capture
> > for a non-power-of-2 stride. Such reasoning is necessary to allow
> > array access with a variable offset through PTR_TO_BTF_ID, e.g.
> > for expressions like p->arr[i].field.
> >
> > reg_bounds_sync() uses the description in two ways:
> > - __reg_bound_offset() clears the low bits of var_off implied by the number
> > of trailing zeros shared by base and step.
> > - __update_bounds_from_step() intersects the 64-bit range with the line via
> > cnum64_intersect_linear(), snapping smin/smax to actual points on it.
> > This is the last step of the sync, as refining the range from var_off
> > can move the bounds off the line.
> >
> > range_within() is extended to check whether the cur register's equation
> > describes a subset of the points described by the old register's equation.
> >
> > Scalar ALU operations update base/step as follows:
> > - ADD of a constant (including pointer + scalar): keep step, shift base;
> > - MUL by a constant: scale step and base by the constant;
> > - LSH by a constant: scale step and base by the corresponding power of two;
> > - sign extension: keep the register unchanged if all values fit the target
> > type, reset to base=0, step=1 otherwise;
> > - All other operations reset to base=0, step=1.
> >
> > Branch (eq/neq) checks do not take into account base/step yet.
> >
> > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
>
> The changelog says "Branch (eq/neq) checks do not take into account base/step
> yet." Is that accurate for this patch?
>
> is_scalar_branch_taken() ends by calling simulate_both_branches_taken(). That
> function runs regs_refine_cond_op() and reg_bounds_sync() on copies of the
> registers, and treats range_bounds_violation() as proof that a branch is dead.
>
> reg_bounds_sync() now ends with __update_bounds_from_step(), and
> cnum64_intersect_linear() returns CNUM64_EMPTY when the refined range holds no
> point of base + step * k.
>
> For example, take r1 in [0, 30] with step=3, base=0 (say from r0 *= 3 with r0
> in [0, 10]), followed by:
>
> if r1 == 4 goto L
>
> The tnum and min/max checks cannot decide this. In
> simulate_both_branches_taken() the true branch refines r64 to [4, 4], and then
> in cnum64_intersect_linear():
>
> d = imod(base - imod(smin, step), step); /* imod(0 - 1, 3) == 2 */
> if ((u64)smax - (u64)smin < d) /* 0 < 2 */
> return CNUM64_EMPTY;
>
> So the JEQ branch is treated as dead (pred = 0) purely because of
> base/step. JNE behaves the same way, and JNE against a range edge now snaps
> the bound onto the line ([0, 29] becomes [0, 27]).
>
> This looks sound as long as base/step are sound, but it is a real change to
> branch pruning, and mark_chain_precision() is called on the compared registers
> whenever pred >= 0. Should the changelog describe this instead of saying
> eq/neq branches ignore base/step?
Kind of. Sort of.
There is no explicit handling in is_scalar_branch_taken(),
as well as it is not wired for pointers.
I didn't think through if simulate_both_branches_taken()
is sufficient or some explicit rules is_scalar_branch_taken()
might be of use as well.
>
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 47a632a6749a..f5b2500335a7 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
>
> [ ... ]
>
> > @@ -2208,6 +2337,15 @@ static void reg_bounds_sync(struct bpf_reg_state *reg)
> > * then new var_off is (0; 0x7f...fc) which improves our umax.
> > */
> > __update_reg_bounds(reg);
> > + /*
> > + * Both tnum and base+step define a sequence of points,
> > + * potentially w/o intersection, or intersecting after N
> > + * tnum_step()'s, where N can be large. On the other hand,
> > + * step+base *must* be in sync with r64 in order for
> > + * array traversal logic starting at reg_umin() to be sound.
> ^^^^^^^^^^
>
> This isn't a bug, but is reg_umin() the right function to name here? The
> array traversal logic isn't part of this patch.
Yes, this should be reg_smin().
next prev parent reply other threads:[~2026-10-09 18:55 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 10:47 [PATCH bpf-next v3 00/51] bpf: use scalar evolution to widen bounded loops Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 01/51] bpf: represent stack access effects with arg_access_info Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 02/51] bpf: describe helper stack accesses " Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 03/51] bpf: describe kfunc " Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 04/51] bpf: track may_write flags in liveness Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 05/51] bpf: summarize may write stack slots in insn_aux_data Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 06/51] bpf: summarize live " Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 07/51] bpf: summarize regs that may hold a frame pointer " Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 08/51] bpf: record write effects for atomic operations in liveness.c Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 09/51] bpf: fix arg_track_xfer() for atomic stack spills and fills Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 10/51] bpf: derive global subprog stack liveness from BTF signatures Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 18:49 ` Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 11/51] bpf: compute parameters liveness in bpf_compute_live_registers() Eduard Zingerman
2026-10-09 11:26 ` sashiko-bot
2026-10-09 18:46 ` Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 12/51] bpf: add tnum_alignment() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 13/51] bpf: add cnum{32,64}_union() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 14/51] bpf: add cnum64_intersect_linear() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 15/51] bpf: expose bpf_rev_opcode() and bpf_flip_opcode() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 16/51] bpf: expose bpf_grow_stack_state() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 17/51] bpf: expose bpf_verbose_snum() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 18/51] bpf: allow subrange relations for PTR_TO_STACK in regsafe() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 19/51] bpf: representation for intervals with steps Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 18:55 ` Eduard Zingerman [this message]
2026-10-09 10:47 ` [PATCH bpf-next v3 20/51] bpf: varying offset access support for PTR_TO_BTF_ID pointers Eduard Zingerman
2026-10-09 11:41 ` sashiko-bot
2026-10-09 19:43 ` Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 21/51] bpf: save DFS postorder numbers for program instructions Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 22/51] bpf: move the live-register and SCC printout to a standalone function Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 23/51] bpf: compute immediate dominators Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 24/51] bpf: compute loop hierarchy Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 10:47 ` [PATCH bpf-next v3 25/51] bpf: add bpf_set_reg_range() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 26/51] bpf: add bpf_mark_reg_known_scalar() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 27/51] bpf: add bpf_reg_union() and bpf_reg_union_compatible() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 28/51] bpf: add bpf_split_cur_state() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 29/51] bpf: add bpf_same_memory_origin() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 30/51] bpf: add bpf_spill_size() Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 31/51] bpf: record basic-block ends in insn_aux_data Eduard Zingerman
2026-10-09 11:45 ` bot+bpf-ci
2026-10-09 10:47 ` [PATCH bpf-next v3 32/51] bpf: allow precision backtracking between overlapping checkpoints Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 33/51] bpf: compute scalar evolution expressions for loops Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 10:47 ` [PATCH bpf-next v3 34/51] bpf: use SCEV to widen bounded loops Eduard Zingerman
2026-10-09 12:08 ` bot+bpf-ci
2026-10-10 1:25 ` kernel test robot
2026-10-10 14:55 ` Alexei Starovoitov
2026-10-10 20:02 ` Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 35/51] bpf: avoid widening registers that hinder exact stack-slot tracking Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 12:08 ` sashiko-bot
2026-10-09 10:47 ` [PATCH bpf-next v3 36/51] bpf: bpf_func_state size optimization Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 10:47 ` [PATCH bpf-next v3 37/51] selftests/bpf: __msg_next tag for matching messages on consecutive lines Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 38/51] selftests/bpf: bound UNIX socket path loops by sun_path size Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 39/51] selftests/bpf: test for stack-pointer subrange pruning Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 40/51] selftests/bpf: tests for may_write stack-liveness tracking Eduard Zingerman
2026-10-09 10:47 ` [PATCH bpf-next v3 41/51] selftests/bpf: tests for may_def marks of atomic RMW operations Eduard Zingerman
2026-10-09 10:48 ` [PATCH bpf-next v3 42/51] selftests/bpf: tests for stack pointer spills/fills through atomics Eduard Zingerman
2026-10-09 10:48 ` [PATCH bpf-next v3 43/51] selftests/bpf: tests for map special cases in bpf_helper_stack_access_bytes() Eduard Zingerman
2026-10-09 10:48 ` [PATCH bpf-next v3 44/51] selftests/bpf: tests for BTF-based global subprog stack liveness Eduard Zingerman
2026-10-09 11:45 ` bot+bpf-ci
2026-10-09 10:48 ` [PATCH bpf-next v3 45/51] selftests/bpf: test for register liveness of subprogram arguments Eduard Zingerman
2026-10-09 10:48 ` [PATCH bpf-next v3 46/51] selftests/bpf: tests for register base/step arithmetic Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 10:48 ` [PATCH bpf-next v3 47/51] selftests/bpf: tests for register base/step state pruning Eduard Zingerman
2026-10-09 12:22 ` sashiko-bot
2026-10-09 10:48 ` [PATCH bpf-next v3 48/51] selftests/bpf: tests for varying offset access to PTR_TO_BTF_ID Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 10:48 ` [PATCH bpf-next v3 49/51] selftests/bpf: tests for loop hierarchy computation Eduard Zingerman
2026-10-09 10:48 ` [PATCH bpf-next v3 50/51] selftests/bpf: tests for immediate dominator computation Eduard Zingerman
2026-10-09 10:48 ` [PATCH bpf-next v3 51/51] selftests/bpf: tests for SCEV analysis and loop widening Eduard Zingerman
2026-10-09 12:07 ` bot+bpf-ci
2026-10-09 20:40 ` [PATCH bpf-next v3 00/51] bpf: use scalar evolution to widen bounded loops patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=faf14259573df35d2fc49a8445be5cd79a0a8565.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bot+bpf-ci@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=ihor.solodrai@linux.dev \
--cc=kernel-team@fb.com \
--cc=martin.lau@kernel.org \
--cc=mason@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox