Section CENV_SUB.
Context {CS CS': compspecs}
(CSUB: cenv_sub (@cenv_cs CS) (@cenv_cs CS')).
Definition is_tc_FF (a: tc_assert) :=
match a with tc_FF _ => True | _ => False end.
Definition dec_tc_FF (a: tc_assert) : {is_tc_FF a}+{~is_tc_FF a}.
Ltac tc_expr_cenv_sub_tac :=
repeat
match goal with
| H: app_pred (@denote_tc_assert _ (tc_andp _ _) _) _ |- _ =>
rewrite denote_tc_assert_andp in H; destruct H
| |- app_pred (@denote_tc_assert _ (tc_andp _ _) _) _ =>
rewrite denote_tc_assert_andp; split
| H: app_pred (@denote_tc_assert _ (tc_andp' _ _) _) _ |- _ =>
destruct H
| |- app_pred (@denote_tc_assert _ (tc_andp' _ _) _) _ =>
split
| |- _ => solve [simple apply tc_bool_i; auto]
| H: app_pred (@denote_tc_assert _ (tc_bool _ _) _) _ |- _ =>
apply tc_bool_e in H; rewrite ?H in *
| |- app_pred (@denote_tc_assert _ (tc_bool true _) _) _ =>
apply I
| |- app_pred (@denote_tc_assert _ (tc_isptr ?a) _) _  =>
apply (isptr_eval_expr_cenv_sub CSUB); auto
| |- app_pred (@denote_tc_assert _ tc_TT _) _ => apply I
| |- app_pred (@denote_tc_assert _ (tc_bool (complete_type _ _) _) _) _ =>
solve [rewrite (cenv_sub_complete_type _ _ CSUB); simpl; auto]
| |- context [tc_int_or_ptr_type] =>
solve [unfold tc_int_or_ptr_type in *; tc_expr_cenv_sub_tac]
| |- _ => solve [simple apply tc_nodivover'_cenv_sub; auto]
| |- _ => solve [simple apply tc_samebase_cenv_sub; auto]
| |- _ => solve [simple apply tc_nonzero'_cenv_sub; auto]
| |- _ => solve [simple apply tc_ilt'_cenv_sub; auto]
| |- _ => solve [simple apply tc_llt'_cenv_sub; auto]
| |- _ => solve [simple apply tc_test_eq'_cenv_sub; auto]
| |- _ => solve [simple apply tc_test_eq_cenv_sub; auto]
| |- _ => solve [simple apply tc_test_order'_cenv_sub; auto]
| |- app_pred (denote_tc_assert (tc_bool ?A _) _) _ =>
match A with context [sizeof ?t] =>
rewrite (cenv_sub_sizeof CSUB t) by assumption;
solve [simple apply tc_bool_i; auto]
end
end;
try solve [eauto].
Ltac tc_expr_cenv_sub_tac2 :=
(match goal with
| H: app_pred (@denote_tc_assert _ match @eval_expr CS ?a ?rho with _ => _ end _) _ |- _ =>
let H' := fresh in
destruct (Val.eq (@eval_expr CS a rho) Vundef) as [H' | H' ];
[ rewrite H' in H;
try match goal with |- context [@eval_expr CS' a rho] =>
destruct (@eval_expr CS' a rho) eqn:?
end
| rewrite <- ?(eval_expr_cenv_sub_eq CSUB _ _ H');
destruct (@eval_expr CS a rho) eqn:?]
| |- app_pred (@denote_tc_assert _ match @eval_expr CS' ?a ?rho with _ => _ end _) _ =>
destruct (@eval_expr CS' a rho) eqn:?H
| |- app_pred (@denote_tc_assert _ (if _ then tc_TT else _) _) _ =>
simple_if_tac; [apply I | ]
end;
try assumption;
try (simple apply (denote_tc_assert_cenv_sub CSUB); auto)).

Lemma tc_nobinover_cenv_sub op a1 a2 rho w:
app_pred (@denote_tc_assert CS (@tc_nobinover op CS a1 a2) rho) w ->
app_pred (@denote_tc_assert CS' (@tc_nobinover op CS' a1 a2) rho) w.