Module ExtrFacts := GenExtrFacts (Def) (Conseq) (Extr).

Theorem semax_set_ptr_compare_load_cast_load_backward: forall {CS: compspecs} {Espec: OracleKind} (Delta: tycontext),
forall (P: environ->mpred) id e,
@semax CS Espec Delta
((|> ( (tc_expr Delta e) &&
(tc_temp_id id (typeof e) Delta e) &&
subst id (eval_expr e) P)) ||
(EX cmp: Cop.binary_operation, EX e1: expr, EX e2: expr,
EX ty: type, EX sh1: share, EX sh2: share,
!! (e = Ebinop cmp e1 e2 ty /\
sepalg.nonidentity sh1 /\ sepalg.nonidentity sh2 /\
is_comparison cmp = true /\
eqb_type (typeof e1) int_or_ptr_type = false /\
eqb_type (typeof e2) int_or_ptr_type = false /\
typecheck_tid_ptr_compare Delta id = true) &&
( |> ( (tc_expr Delta e1) &&
(tc_expr Delta e2)  &&
local (`(blocks_match cmp) (eval_expr e1) (eval_expr e2)) &&
(`(mapsto_ sh1 (typeof e1)) (eval_expr e1) * TT) &&
(`(mapsto_ sh2 (typeof e2)) (eval_expr e2) * TT) &&
subst id (eval_expr (Ebinop cmp e1 e2 ty)) P))) ||
(EX sh: share, EX t2: type, EX v2: val,
!! (typeof_temp Delta id = Some t2 /\
is_neutral_cast (typeof e) t2 = true /\
readable_share sh) &&
|> ( (tc_lvalue Delta e) &&
local (`(tc_val (typeof e) v2)) &&
(`(mapsto sh (typeof e)) (eval_lvalue e) (`v2) * TT) &&
subst id (`v2) P)) ||
(EX sh: share, EX e1: expr, EX t1: type, EX v2: val,
!! (e = Ecast e1 t1 /\
typeof_temp Delta id = Some t1 /\
cast_pointer_to_bool (typeof e1) t1 = false /\
readable_share sh) &&
|> ( (tc_lvalue Delta e1) &&
local (`(tc_val t1) (`(eval_cast (typeof e1) t1 v2))) &&
(`(mapsto sh (typeof e1)) (eval_lvalue e1) (`v2) * TT) &&
subst id (`(force_val (sem_cast (typeof e1) t1 v2))) P)))
(Sset id e) (normal_ret_assert P).