};
 
 struct bpf_prog_offload_ops {
+       /* verifier basic callbacks */
        int (*insn_hook)(struct bpf_verifier_env *env,
                         int insn_idx, int prev_insn_idx);
        int (*finalize)(struct bpf_verifier_env *env);
+       /* verifier optimization callbacks (called after .finalize) */
+       int (*replace_insn)(struct bpf_verifier_env *env, u32 off,
+                           struct bpf_insn *insn);
+       int (*remove_insns)(struct bpf_verifier_env *env, u32 off, u32 cnt);
+       /* program management callbacks */
        int (*prepare)(struct bpf_prog *prog);
        int (*translate)(struct bpf_prog *prog);
        void (*destroy)(struct bpf_prog *prog);
        void                    *dev_priv;
        struct list_head        offloads;
        bool                    dev_state;
+       bool                    opt_failed;
        void                    *jited_image;
        u32                     jited_len;
 };
 
 int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env,
                                 int insn_idx, int prev_insn_idx);
 int bpf_prog_offload_finalize(struct bpf_verifier_env *env);
+void
+bpf_prog_offload_replace_insn(struct bpf_verifier_env *env, u32 off,
+                             struct bpf_insn *insn);
+void
+bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
 
 #endif /* _LINUX_BPF_VERIFIER_H */
 
        return ret;
 }
 
+void
+bpf_prog_offload_replace_insn(struct bpf_verifier_env *env, u32 off,
+                             struct bpf_insn *insn)
+{
+       const struct bpf_prog_offload_ops *ops;
+       struct bpf_prog_offload *offload;
+       int ret = -EOPNOTSUPP;
+
+       down_read(&bpf_devs_lock);
+       offload = env->prog->aux->offload;
+       if (offload) {
+               ops = offload->offdev->ops;
+               if (!offload->opt_failed && ops->replace_insn)
+                       ret = ops->replace_insn(env, off, insn);
+               offload->opt_failed |= ret;
+       }
+       up_read(&bpf_devs_lock);
+}
+
+void
+bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt)
+{
+       struct bpf_prog_offload *offload;
+       int ret = -EOPNOTSUPP;
+
+       down_read(&bpf_devs_lock);
+       offload = env->prog->aux->offload;
+       if (offload) {
+               if (!offload->opt_failed && offload->offdev->ops->remove_insns)
+                       ret = offload->offdev->ops->remove_insns(env, off, cnt);
+               offload->opt_failed |= ret;
+       }
+       up_read(&bpf_devs_lock);
+}
+
 static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
 {
        struct bpf_prog_offload *offload = prog->aux->offload;
 
        unsigned int orig_prog_len = env->prog->len;
        int err;
 
+       if (bpf_prog_is_dev_bound(env->prog->aux))
+               bpf_prog_offload_remove_insns(env, off, cnt);
+
        err = bpf_remove_insns(env->prog, off, cnt);
        if (err)
                return err;
                else
                        continue;
 
+               if (bpf_prog_is_dev_bound(env->prog->aux))
+                       bpf_prog_offload_replace_insn(env, i, &ja);
+
                memcpy(insn, &ja, sizeof(ja));
        }
 }