summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2026-10-09 03:47:42 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-10-09 20:29:13 +0000
commit9ae7f5e8bf1d8be74797f937cdbeb730178a8c3d (patch)
tree49bfb8d4a10e8901ad5645e7714903635192b6d9 /include/linux
parent6254fb69328963be95ff9b2760e879a9220ae6c3 (diff)
downloadlinux-next-9ae7f5e8bf1d8be74797f937cdbeb730178a8c3d.tar.gz
linux-next-9ae7f5e8bf1d8be74797f937cdbeb730178a8c3d.zip
bpf: Compute loop hierarchy
SCEV needs to process loops from innermost to outermost, summarizing results for nested loops. Add a pass to compute the loop structure. Use a non-recursive adaptation of the algorithm from: "A New Algorithm for Identifying Loops in Decompilation" by Wei et al. Record the loop hierarchy per instruction: - The field insn_aux_data->loop_header records the innermost loop header containing it. - The field insn_aux_data->loop records additional information about the loop if this instruction is a loop header (exits, backedges, irreducibility). Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-24-bcba9bc53ac9@gmail.com
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bpf_verifier.h46
1 files changed, 46 insertions, 0 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 59c0670af0e9..d1ebbfef5455 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -655,6 +655,41 @@ struct bpf_iarray {
___idx < (arr)->cnt && ({ item = (arr)->items[___idx]; 1; }); \
___idx++)
+#define MAX_BACKEDGES 16
+#define MAX_LOOP_EXITS 256
+
+/* Number of exit conditions dominating a backedge. */
+#define MAX_LATCHES 4
+
+struct bpf_backedge {
+ int from;
+ /*
+ * Conditional jumps within the loop that dominate 'from' and have
+ * a successor outside the loop, nearest first. latches[0] is the
+ * latch; the remaining entries are additional exit conditions.
+ * Each usable condition gives an upper bound on the iteration count,
+ * so keeping only a subset is sound.
+ */
+ int latches[MAX_LATCHES];
+ u8 latches_cnt;
+};
+
+struct bpf_loop_exit {
+ int from; /* instruction inside the loop */
+ int to; /* instruction outside the loop */
+};
+
+struct bpf_loop {
+ struct bpf_backedge backedges[MAX_BACKEDGES];
+ /* edges exiting from this loop, includes edges from nested loops */
+ struct bpf_loop_exit *exits;
+ int backedges_cnt;
+ int exits_cnt;
+ bool irreducible;
+ bool backedges_overflow;
+ bool exits_overflow;
+};
+
struct bpf_insn_aux_data {
union {
enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
@@ -752,6 +787,13 @@ struct bpf_insn_aux_data {
u16 const_reg_map_mask;
u16 const_reg_subprog_mask;
u32 const_reg_vals[10];
+ /*
+ * Header index of the innermost loop containing this instruction, -1 if none.
+ * For a loop header, identifies the parent loop instead.
+ */
+ s32 loop_header;
+ /* additional information about the loop if this instruction is a loop header */
+ struct bpf_loop *loop;
};
#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
@@ -1879,6 +1921,7 @@ int bpf_check_attach_btf_id_multi(struct btf *btf, struct bpf_prog *prog, u32 bt
struct bpf_attach_target_info *tgt_info);
/* Functions in fixups.c, called from bpf_check() */
+void bpf_clear_insn_aux_data(struct bpf_verifier_env *env, int start, int len);
int bpf_remove_fastcall_spills_fills(struct bpf_verifier_env *env);
int bpf_optimize_bpf_loop(struct bpf_verifier_env *env);
void bpf_opt_hard_wire_dead_code_branches(struct bpf_verifier_env *env);
@@ -1895,5 +1938,8 @@ int bpf_flip_opcode(u32 opcode);
u8 bpf_rev_opcode(u8 opcode);
int bpf_compute_idoms(struct bpf_verifier_env *env);
+int bpf_compute_loops(struct bpf_verifier_env *env);
+int bpf_loop_at_index(struct bpf_verifier_env *env, u32 idx);
+bool bpf_is_nested_loop(struct bpf_verifier_env *env, int inner_header, int outer_header);
#endif /* _LINUX_BPF_VERIFIER_H */