Require Import Utf8.
Require Import Coqlib FastArith.
Require Import AbIdealEnv IdealExpr.
Require Import AbMachineEnv.
Require Import Integers.
Require Import FloatLib FloatIntervals ZIntervals IdealIntervals.
Require Import ZArith.
Require Import Cminor Ctypes.
Require Import AdomLib.
Require Import Maps ShareTree TreeAl Util Hash ToString Sets.
Require Import FactMsgHelpers.
Open Scope Z_scope.
Definition var0 :=
Cells.cell.
Section Functor.
Context (
abt abt_iter:
Type) {
IdD :
ab_ideal_env_nochan abt abt_iter}.
Inductive related :
mach_num ->
ideal_num ->
Prop :=
|
rel_int :
forall x,
related (
MNint (
Int.repr x)) (
INz x)
|
rel_long :
forall x,
related (
MNint64 (
Int64.repr x)) (
INz x)
|
rel_float :
forall x,
related (
MNfloat x) (
INf x)
|
rel_single :
forall x,
related (
MNsingle x) (
INf (
Float.of_single x)).
Hint Constructors related.
Lemma related_unsigned:
forall x,
related (
MNint x) (
INz (
Int.unsigned x)).
Proof.
Lemma related_signed:
forall x,
related (
MNint x) (
INz (
Int.signed x)).
Proof.
Lemma related_unsigned_long:
forall x,
related (
MNint64 x) (
INz (
Int64.unsigned x)).
Proof.
Lemma related_signed_long:
forall x,
related (
MNint64 x) (
INz (
Int64.signed x)).
Proof.
Instance gamma_mach :
gamma_op abt (
var0 ->
mach_num) :=
fun v ρ =>
∃ ρ':
var ->
ideal_num,
ρ' ∈ γ
v ∧ ∀
id,
related (ρ
id) (ρ' (
Real id)).
Instance gamma_mach_iter :
gamma_op abt_iter (
var0 ->
mach_num) :=
fun v ρ =>
∃ ρ':
var ->
ideal_num,
ρ' ∈ γ
v ∧ ∀
id,
related (ρ
id) (ρ' (
Real id)).
Definition typesmap :=
Cells.ACTree.t (
option signedness *
mach_num_ty).
Instance gamma_typs :
gamma_op typesmap (
var0 ->
mach_num) :=
fun typs ρ =>
∀
v t,
Cells.ACTree.get v typs =
Some t ->
match snd t with MNTfloat |
MNTsingle =>
fst t =
None |
_ =>
True end /\
ρ
v ∈ γ (
snd t).
Record ghosts_info :
Type := {
next_g:
positive;
typs_g:
PTree.t ideal_num_ty
}.
Definition init_ghost_info := {|
next_g := 1;
typs_g :=
PTree.empty _ |}.
Definition compat_gh (
gi:
ghosts_info) (ρ1 ρ2:
var ->
ideal_num) :=
(∀
id, ρ1 (
Real id) = ρ2 (
Real id)) /\
(∀
g, (
g <
gi.(
next_g))%
positive -> ρ1 (
Ghost g) = ρ2 (
Ghost g)).
Lemma compat_gh_refl:
∀
next_g ρ,
compat_gh next_g ρ ρ.
Proof.
intros. split; auto.
Qed.
Hint Resolve compat_gh_refl.
Lemma compat_gh_trans:
∀
gi1 gi2 ρ1 ρ2 ρ3,
(
gi1.(
next_g) <=
gi2.(
next_g))%
positive ->
compat_gh gi1 ρ1 ρ2 ->
compat_gh gi2 ρ2 ρ3 ->
compat_gh gi1 ρ1 ρ3.
Proof.
split; intros; (etransitivity; [apply H0|apply H1]).
auto. Psatz.lia.
Qed.
Hint Resolve compat_gh_trans.
Instance gamma_gh :
gamma_op ghosts_info (
var ->
ideal_num) :=
fun gi ρ =>
∀
p ty,
PTree.get p gi.(
typs_g) =
Some ty -> ρ (
Ghost p) ∈ γ
ty.
Lemma gamma_gh_init:
∀ ρ, ρ ∈ γ
init_ghost_info.
Proof.
Hint Resolve gamma_gh_init.
Definition signed_itv :=
ZITV Int.min_signed Int.max_signed.
Lemma signed_itv_correct:
∀
x,
Int.signed x ∈ γ
signed_itv.
Proof.
Definition unsigned_itv :=
ZITV F0 Int.max_unsigned.
Lemma unsigned_itv_correct:
∀
x,
Int.unsigned x ∈ γ
unsigned_itv.
Proof.
Definition signed64_itv :=
ZITV Int64.min_signed Int64.max_signed.
Lemma signed64_itv_correct:
∀
x,
Int64.signed x ∈ γ
signed64_itv.
Proof.
Definition unsigned64_itv :=
ZITV F0 Int64.max_unsigned.
Lemma unsigned64_itv_correct:
∀
x,
Int64.unsigned x ∈ γ
unsigned64_itv.
Proof.
Definition alias_sz :
Z := 100000.
Opaque alias_sz.
Definition simplify_expr_alias (
v:
abt+⊥) (
e:
iexpr) (
gi:
ghosts_info):
iexpr*
abt+⊥*
ghosts_info :=
let e :=
simplify_expr e in
if Z.leb (
iexpr_sz e)
alias_sz then (
e,
v,
gi)
else
(
IEvar (
iexpr_ty e) (
Ghost gi.(
next_g)),
do v <-
v;
idnc_assign (
Ghost gi.(
next_g))
e v,
{|
next_g :=
Pos.succ gi.(
next_g);
typs_g :=
PTree.set gi.(
next_g) (
iexpr_ty e)
gi.(
typs_g) |}).
Lemma simplify_expr_alias_correct:
∀
v e gi,
∀
e'
v'
gi',
simplify_expr_alias v e gi = (
e',
v',
gi') ->
∀ ρ
x, ρ ∈ γ
v -> ρ ∈ γ
gi ->
(∀ ρ',
compat_gh gi ρ ρ' ->
eval_iexpr ρ'
e x ) ->
∃ ρ',
compat_gh gi ρ ρ' /\ ρ' ∈ γ
v' /\ ρ' ∈ γ
gi' /\
(∀ ρ'',
compat_gh gi' ρ' ρ'' ->
eval_iexpr ρ''
e'
x).
Proof.
Lemma simplify_expr_alias_monotone:
∀
v e gi,
∀
e'
v'
gi',
simplify_expr_alias v e gi = (
e',
v',
gi') ->
(
gi.(
next_g) <=
gi'.(
next_g))%
positive.
Proof.
Definition itv_normalizer (
i:
zitv+⊤+⊥) (
min max:
Zfast) (
logdiv:
Zfast):
option Zfast :=
match i with
|
NotBot (
Just (
ZITV a b)) =>
if Zfasteqb (
Zfastshr (
Zfastsub b a)
logdiv)
F0 then
let q :=
Zfastshr (
Zfastsub a min)
logdiv in
if Zfastleb (
Zfastsub b (
Zfastshl q logdiv))
max
then Some q
else None
else None
|
_ =>
None
end.
Lemma itv_normalizer_correct:
∀
i (
min max logdiv:
Z), 0 <
logdiv ->
∀
q,
itv_normalizer i min max logdiv =
Some q ->
∀
n,
n ∈ γ
i ->
min <=
n -
q * 2 ^
logdiv <=
max.
Proof.
intros [|[|[[
a] [
b]]]]
min max logdiv Hlogdiv q Hq n Hn;
try discriminate Hq;
simpl in *;
fastunwrap.
rewrite Z.shiftl_mul_pow2, !
Z.shiftr_div_pow2 in Hq by omega.
simpl in Hq.
destruct (
Z.eqb_spec ((
b-
a) / (2 ^
logdiv)) 0). 2:
discriminate.
match goal with
|
H:
context [
Zle_bool ?
x ?
y] |-
_ =>
assert (
HZle:=
Zle_cases x y);
destruct (
Zle_bool x y)
end;
inv Hq.
assert (
Hlt:2^
logdiv > 0).
apply Z.lt_gt,
Z.pow_pos_nonneg;
omega.
assert (
Hmodeq:=
Zmod_eq (
a-
min)
_ Hlt).
assert (
Hmodlt:=
Z_mod_lt (
a-
min)
_ Hlt).
destruct Hn.
fastunwrap.
omega.
Qed.
Definition normalize_expr (
v:
abt+⊥) (
e:
iexpr) (
min max:
Zfast)
(
logdiv:
Zfast) (
gi:
ghosts_info):
iexpr*
abt+⊥*
ghosts_info*
bool :=
let '(
e,
v,
gi) :=
simplify_expr_alias v e gi in
match v with
|
NotBot v =>
let itv :=
do x <- (
idnc_get_query_chan v).(
AbIdealEnv.get_itv)
e;
in_z x
in
match itv_normalizer itv min max logdiv with
|
Some q =>
let e :=
if Zfasteqb q F0 then e
else
let shift :=
Zfastshl q logdiv in
IEbinop IOsub e (
IEconst (
INz shift))
in
(
e,
NotBot v,
gi,
true)
|
None => (
e,
NotBot v,
gi,
false)
end
|
Bot => (
e,
v,
gi,
false)
end.
Lemma normalize_expr_correct:
∀
v e (
min max logdiv:
Z)
gi, 0 <
logdiv ->
∀
e'
v'
gi'
b,
normalize_expr v e min max logdiv gi = (
e',
v',
gi',
b) ->
∀ ρ (
x:
Z), ρ ∈ γ
v -> ρ ∈ γ
gi ->
(∀ ρ',
compat_gh gi ρ ρ' ->
eval_iexpr ρ'
e (
INz x)) ->
∃ ρ',
compat_gh gi ρ ρ' /\ ρ' ∈ γ
v' /\ ρ' ∈ γ
gi' /\
if b then
∃ (
x':
Z),
min <=
x' <=
max ∧
Int.eqmod (
two_p logdiv)
x x' /\
(∀ ρ'',
compat_gh gi' ρ' ρ'' ->
eval_iexpr ρ''
e' (
INz x'))
else
∀ ρ'',
compat_gh gi' ρ' ρ'' ->
eval_iexpr ρ''
e' (
INz x).
Proof.
Lemma normalize_expr_next_g_monotone:
∀
v e min max logdiv gi e'
v'
gi'
b,
normalize_expr v e min max logdiv gi = (
e',
v',
gi',
b) ->
(
gi.(
next_g) <=
gi'.(
next_g))%
positive.
Proof.
Definition intrange := (
Int.min_signed:
Zfast,
Int.max_signed:
Zfast).
Definition intrangeu := (
F0:
Zfast,
Int.max_unsigned:
Zfast).
Definition intzwordsize :
Zfast :=
Int.zwordsize.
Definition normalize_expr_signedness (
v:
abt+⊥) (
e:
iexpr) (
f:
signedness) (
gi:
ghosts_info):
iexpr *
abt+⊥ *
ghosts_info :=
let '(
min,
max) :=
match f with Signed =>
intrange |
Unsigned =>
intrangeu end
in
match normalize_expr v e min max intzwordsize gi with
| (
e,
v,
ng,
true) => (
e,
v,
ng)
|
_ => (
IEZitv (
ZITV min max),
v,
gi)
end.
Lemma normalize_expr_signedness_correct:
∀
v e f,
∀ ρ (
x:
Z)
gi, ρ ∈ γ
v -> ρ ∈ γ
gi ->
(∀ ρ',
compat_gh gi ρ ρ' ->
eval_iexpr ρ'
e (
INz x)) ->
∀
e'
v'
gi',
normalize_expr_signedness v e f gi = (
e',
v',
gi') ->
∃ ρ',
compat_gh gi ρ ρ' /\ ρ' ∈ γ
v' /\ ρ' ∈ γ
gi' /\
∃ (
x':
Z),
x' ∈ γ (
match f with Signed =>
signed_itv |
Unsigned =>
unsigned_itv end) ∧
Int.eqm x x' ∧
(∀ ρ'',
compat_gh gi' ρ' ρ'' ->
eval_iexpr ρ''
e' (
INz x')).
Proof.
Lemma normalize_expr_signedness_next_g_monotone:
∀
v e f gi e'
v'
gi',
normalize_expr_signedness v e f gi = (
e',
v',
gi') ->
(
gi.(
next_g) <=
gi'.(
next_g))%
positive.
Proof.
Definition int64range := (
Int64.min_signed:
Zfast,
Int64.max_signed:
Zfast).
Definition int64rangeu := (
F0:
Zfast,
Int64.max_unsigned:
Zfast).
Definition int64zwordsize :
Zfast :=
Int64.zwordsize.
Definition normalize_expr_signedness64 (
v:
abt+⊥) (
e:
iexpr) (
f:
signedness) (
gi:
ghosts_info):
iexpr *
abt+⊥ *
ghosts_info :=
let '(
min,
max) :=
match f with Signed =>
int64range |
Unsigned =>
int64rangeu end
in
match normalize_expr v e min max int64zwordsize gi with
| (
e,
v,
ng,
true) => (
e,
v,
ng)
|
_ => (
IEZitv (
ZITV min max),
v,
gi)
end.
Lemma normalize_expr_signedness64_correct:
∀
v e f,
∀ ρ (
x:
Z)
gi, ρ ∈ γ
v -> ρ ∈ γ
gi ->
(∀ ρ',
compat_gh gi ρ ρ' ->
eval_iexpr ρ'
e (
INz x)) ->
∀
e'
v'
gi',
normalize_expr_signedness64 v e f gi = (
e',
v',
gi') ->
∃ ρ',
compat_gh gi ρ ρ' /\ ρ' ∈ γ
v' /\ ρ' ∈ γ
gi' /\
∃ (
x':
Z),
x' ∈ γ (
match f with Signed =>
signed64_itv |
Unsigned =>
unsigned64_itv end) ∧
Int64.eqm x x' ∧
(∀ ρ'',
compat_gh gi' ρ' ρ'' ->
eval_iexpr ρ''
e' (
INz x')).
Proof.
Lemma normalize_expr_signedness64_next_g_monotone:
∀
v e f gi e'
v'
gi',
normalize_expr_signedness64 v e f gi = (
e',
v',
gi') ->
(
gi.(
next_g) <=
gi'.(
next_g))%
positive.
Proof.
Definition assume_cmp (
c:
comparison) (
e:
iexpr) (
z:
Zfast) (
v:
abt+⊥):
abt+⊥ :=
do v <-
v;
idnc_assume (
IEbinop (
IOcmp c)
e (
IEconst (
INz z)))
true v.
Lemma assume_cmp_correct:
∀
c e (
x:
Z)
z ρ
ab,
ρ ∈ γ
ab ->
INz x ∈
eval_iexpr ρ
e ->
Zcmp c x z =
true ->
ρ ∈ γ (
assume_cmp c e z ab).
Proof.
Definition check_finitef (
e:
iexpr) (
v:
abt+⊥):
bool :=
match v with
|
Bot =>
true
|
NotBot v =>
is_bot (
idnc_assume
(
IEbinop (
IOcmpf Cgt)
e (
IEconst (
INf (
B754_infinity true))))
false v) &&
is_bot (
idnc_assume
(
IEbinop (
IOcmpf Clt)
e (
IEconst (
INf (
B754_infinity false))))
false v)
end.
Lemma check_finitef_correct:
∀
e x ρ
ab,
check_finitef e ab =
true ->
ρ ∈ γ
ab ->
INf x ∈
eval_iexpr ρ
e ->
is_finite x =
true.
Proof.
Fixpoint convert_expr (
e:
mexpr var0) (
v:
abt+⊥) (
nerr:
bool) (
gi:
ghosts_info) :
(
iexpr *
abt+⊥ *
bool *
ghosts_info) :=
match e with
|
MEvar (
MNTint |
MNTint64)
x => (
IEvar INTz (
Real x),
v,
nerr,
gi)
|
MEvar (
MNTfloat |
MNTsingle)
x => (
IEvar INTf (
Real x),
v,
nerr,
gi)
|
MEconst (
MNint i) => (
IEconst (
INz (
Int.signed i)),
v,
nerr,
gi)
|
MEconst (
MNint64 i) => (
IEconst (
INz (
Int64.signed i)),
v,
nerr,
gi)
|
MEconst (
MNfloat f) => (
IEconst (
INf f),
v,
nerr,
gi)
|
MEconst (
MNsingle f) => (
IEconst (
INf (
Float.of_single f)),
v,
nerr,
gi)
|
MEunop op e =>
let '(
e,
v,
nerr,
gi) :=
convert_expr e v nerr gi in
match op with
|
Ocast8unsigned =>
match normalize_expr v e F0 F255 F8 gi with
| (
e,
v,
gi,
true) => (
e,
v,
nerr,
gi)
|
_ => (
IEZitv (
ZITV F0 F255),
v,
nerr,
gi)
end
|
Ocast8signed =>
match normalize_expr v e (-128) 127
F8 gi with
| (
e,
v,
gi,
true) => (
e,
v,
nerr,
gi)
|
_ => (
IEZitv (
ZITV (-128) 127),
v,
nerr,
gi)
end
|
Ocast16unsigned =>
match normalize_expr v e F0 65535
F16 gi with
| (
e,
v,
gi,
true) => (
e,
v,
nerr,
gi)
|
_ => (
IEZitv (
ZITV F0 65535),
v,
nerr,
gi)
end
|
Ocast16signed =>
match normalize_expr v e (-32768) 32767
F16 gi with
| (
e,
v,
gi,
true) => (
e,
v,
nerr,
gi)
|
_ => (
IEZitv (
ZITV (-32768) 32767),
v,
nerr,
gi)
end
|
Olongofint =>
let '(
e,
v,
gi) :=
normalize_expr_signedness v e Signed gi in
(
e,
v,
nerr,
gi)
|
Olongofintu =>
let '(
e,
v,
gi) :=
normalize_expr_signedness v e Unsigned gi in
(
e,
v,
nerr,
gi)
|
Ointoflong => (
e,
v,
nerr,
gi)
|
Onegint => (
IEunop IOneg e,
v,
nerr,
gi)
|
Onotint => (
IEunop IOnot e,
v,
nerr,
gi)
|
Onegl => (
IEunop IOneg e,
v,
nerr,
gi)
|
Onotl => (
IEunop IOnot e,
v,
nerr,
gi)
|
Onegf |
Onegfs => (
IEunop IOnegf e,
v,
nerr,
gi)
|
Oabsf |
Oabsfs => (
IEunop IOabsf e,
v,
nerr,
gi)
|
Ofloatofsingle => (
e,
v,
nerr,
gi)
|
Osingleoffloat => (
IEunop IOsingleoffloat e,
v,
nerr,
gi)
|
Ointoffloat |
Ointofsingle =>
let '(
e,
v,
gi) :=
simplify_expr_alias v e gi in
let e' :=
IEunop IOzoffloat e in
let nerr :=
nerr &&
check_finitef e v &&
is_bot (
assume_cmp Clt e' (
fst intrange)
v) &&
is_bot (
assume_cmp Cgt e' (
snd intrange)
v)
in
(
e',
v,
nerr,
gi)
|
Ointuoffloat |
Ointuofsingle =>
let '(
e,
v,
gi) :=
simplify_expr_alias v e gi in
let e' :=
IEunop IOzoffloat e in
let nerr :=
nerr &&
check_finitef e v &&
is_bot (
assume_cmp Clt e'
F0 v) &&
is_bot (
assume_cmp Cgt e' (
snd intrangeu)
v)
in
(
e',
v,
nerr,
gi)
|
Ofloatofint =>
let '(
e,
v,
gi) :=
normalize_expr_signedness v e Signed gi in
(
IEunop IOfloatofz e,
v,
nerr,
gi)
|
Osingleofint =>
let '(
e,
v,
gi) :=
normalize_expr_signedness v e Signed gi in
(
IEunop IOsingleofz e,
v,
nerr,
gi)
|
Ofloatofintu =>
let '(
e,
v,
gi) :=
normalize_expr_signedness v e Unsigned gi in
(
IEunop IOfloatofz e,
v,
nerr,
gi)
|
Osingleofintu =>
let '(
e,
v,
gi) :=
normalize_expr_signedness v e Unsigned gi in
(
IEunop IOsingleofz e,
v,
nerr,
gi)
|
Olongoffloat |
Olongofsingle =>
let '(
e,
v,
gi) :=
simplify_expr_alias v e gi in
let e' :=
IEunop IOzoffloat e in
let nerr :=
nerr &&
check_finitef e v &&
is_bot (
assume_cmp Clt e' (
fst int64range)
v) &&
is_bot (
assume_cmp Cgt e' (
snd int64range)
v)
in
(
e',
v,
nerr,
gi)
|
Olonguoffloat |
Olonguofsingle =>
let '(
e,
v,
gi) :=
simplify_expr_alias v e gi in
let e' :=
IEunop IOzoffloat e in
let nerr :=
nerr &&
check_finitef e v &&
is_bot (
assume_cmp Clt e'
F0 v) &&
is_bot (
assume_cmp Cgt e' (
snd int64rangeu)
v)
in
(
e',
v,
nerr,
gi)
|
Ofloatoflong =>
let '(
e,
v,
gi) :=
normalize_expr_signedness64 v e Signed gi in
(
IEunop IOfloatofz e,
v,
nerr,
gi)
|
Ofloatoflongu =>
let '(
e,
v,
gi) :=
normalize_expr_signedness64 v e Unsigned gi in
(
IEunop IOfloatofz e,
v,
nerr,
gi)
|
Osingleoflong =>
let '(
e,
v,
gi) :=
normalize_expr_signedness64 v e Signed gi in
(
IEunop IOsingleofz e,
v,
nerr,
gi)
|
Osingleoflongu =>
let '(
e,
v,
gi) :=
normalize_expr_signedness64 v e Unsigned gi in
(
IEunop IOsingleofz e,
v,
nerr,
gi)
end
|
MEbinop op e1 e2 =>
let '(
e1,
v,
nerr,
gi) :=
convert_expr e1 v nerr gi in
let '(
e2,
v,
nerr,
gi) :=
convert_expr e2 v nerr gi in
match op with
|
Ocmp c =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Signed gi in
(
IEbinop (
IOcmp c)
e1 e2,
v,
nerr,
gi)
|
Ocmpu c =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
(
IEbinop (
IOcmp c)
e1 e2,
v,
nerr,
gi)
|
Ocmpl c =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness64 v e2 Signed gi in
(
IEbinop (
IOcmp c)
e1 e2,
v,
nerr,
gi)
|
Ocmplu c =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness64 v e2 Unsigned gi in
(
IEbinop (
IOcmp c)
e1 e2,
v,
nerr,
gi)
|
Oaddf => (
IEbinop IOaddf e1 e2,
v,
nerr,
gi)
|
Oaddfs => (
IEunop IOsingleoffloat (
IEbinop IOaddf e1 e2),
v,
nerr,
gi)
|
Osubf => (
IEbinop IOsubf e1 e2,
v,
nerr,
gi)
|
Osubfs => (
IEunop IOsingleoffloat (
IEbinop IOsubf e1 e2),
v,
nerr,
gi)
|
Omulf => (
IEbinop IOmulf e1 e2,
v,
nerr,
gi)
|
Omulfs => (
IEunop IOsingleoffloat (
IEbinop IOmulf e1 e2),
v,
nerr,
gi)
|
Odivf => (
IEbinop IOdivf e1 e2,
v,
nerr,
gi)
|
Odivfs => (
IEunop IOsingleoffloat (
IEbinop IOdivf e1 e2),
v,
nerr,
gi)
|
Ocmpf c |
Ocmpfs c => (
IEbinop (
IOcmpf c)
e1 e2,
v,
nerr,
gi)
|
Oadd |
Oaddl => (
IEbinop IOadd e1 e2,
v,
nerr,
gi)
|
Osub |
Osubl => (
IEbinop IOsub e1 e2,
v,
nerr,
gi)
|
Omul |
Omull => (
IEbinop IOmul e1 e2,
v,
nerr,
gi)
|
Odiv =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Signed gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v) &&
is_bot (
assume_cmp Cle e1 (
fst intrange) (
assume_cmp Ceq e2 Fm1 v))
in
(
IEbinop IOdiv e1 e2,
v,
nerr,
gi)
|
Odivl =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness64 v e2 Signed gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v) &&
is_bot (
assume_cmp Cle e1 (
fst int64range) (
assume_cmp Ceq e2 Fm1 v))
in
(
IEbinop IOdiv e1 e2,
v,
nerr,
gi)
|
Odivu =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v)
in
(
IEbinop IOdiv e1 e2,
v,
nerr,
gi)
|
Odivlu =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness64 v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v)
in
(
IEbinop IOdiv e1 e2,
v,
nerr,
gi)
|
Omod =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Signed gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v) &&
is_bot (
assume_cmp Cle e1 (
fst intrange) (
assume_cmp Ceq e2 Fm1 v))
in
(
IEbinop IOmod e1 e2,
v,
nerr,
gi)
|
Omodl =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness64 v e2 Signed gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v) &&
is_bot (
assume_cmp Cle e1 (
fst int64range) (
assume_cmp Ceq e2 Fm1 v))
in
(
IEbinop IOmod e1 e2,
v,
nerr,
gi)
|
Omodu =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v)
in
(
IEbinop IOmod e1 e2,
v,
nerr,
gi)
|
Omodlu =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness64 v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Ceq e2 F0 v)
in
(
IEbinop IOmod e1 e2,
v,
nerr,
gi)
|
Oand |
Oandl => (
IEbinop IOand e1 e2,
v,
nerr,
gi)
|
Oor |
Oorl => (
IEbinop IOor e1 e2,
v,
nerr,
gi)
|
Oxor |
Oxorl => (
IEbinop IOxor e1 e2,
v,
nerr,
gi)
|
Oshl =>
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Cge e2 intzwordsize v)
in
(
IEbinop IOshl e1 e2,
v,
nerr,
gi)
|
Oshll =>
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Cge e2 int64zwordsize v)
in
(
IEbinop IOshl e1 e2,
v,
nerr,
gi)
|
Oshr =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Cge e2 intzwordsize v)
in
(
IEbinop IOshr e1 e2,
v,
nerr,
gi)
|
Oshrl =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Signed gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Cge e2 int64zwordsize v)
in
(
IEbinop IOshr e1 e2,
v,
nerr,
gi)
|
Oshru =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Cge e2 intzwordsize v)
in
(
IEbinop IOshr e1 e2,
v,
nerr,
gi)
|
Oshrlu =>
let '(
e1,
v,
gi) :=
normalize_expr_signedness64 v e1 Unsigned gi in
let '(
e2,
v,
gi) :=
normalize_expr_signedness v e2 Unsigned gi in
let nerr :=
nerr &&
is_bot (
assume_cmp Cge e2 int64zwordsize v)
in
(
IEbinop IOshr e1 e2,
v,
nerr,
gi)
end
end.
Lemma convert_expr_next_g_monotone:
∀
e v nerr gi e'
v'
nerr'
gi',
convert_expr e v nerr gi = (
e',
v',
nerr',
gi') ->
(
gi.(
next_g) <=
gi'.(
next_g))%
positive.
Proof.
Lemma convert_expr_ok:
∀
e ρ
x,
eval_mexpr ρ
e x ->
∀
v ρ'1
gi, ρ'1 ∈ γ
v -> ρ'1 ∈ γ
gi -> (∀
id,
related (ρ
id) (ρ'1 (
Real id))) ->
∀
nerr e'
v'
nerr'
gi',
convert_expr e v nerr gi = (
e',
v',
nerr',
gi') ->
∃ ρ'2,
ρ'2 ∈ γ
v' /\ ρ'2 ∈ γ
gi' /\
compat_gh gi ρ'1 ρ'2 /\
∃
x',
(∀ ρ'3,
compat_gh gi' ρ'2 ρ'3 ->
eval_iexpr ρ'3
e'
x') ∧
related x x'.
Proof.
induction 1;
simpl convert_expr;
intros ab ρ'1
gi Hρ'1
Hgi Hρρ'1
nerr e'
v'
nerr'
gi'
EQ.
-
specialize (
Hρρ'1
id).
exists ρ'1.
split; [|
split;[|
split;[|
exists (ρ'1 (
Real id));
split]]].
+
destruct ty;
congruence.
+
destruct ty;
inv EQ;
auto.
+
auto.
+
destruct ty;
inv EQ;
inv H0;
inv Hρρ'1;
try congruence;
repeat constructor;
rewrite H2;
symmetry;
apply H0.
+
congruence.
-
exists ρ'1.
split.
destruct n;
congruence.
split.
destruct n;
inv EQ;
auto.
split.
auto.
destruct n;
inv EQ;
eexists;
(
split; [|
auto using related_signed,
related_signed_long]);
constructor;
constructor.
-
specialize (
IHeval_mexpr _ _ _ Hρ'1
Hgi Hρρ'1
nerr).
assert (
MONOe1:=
convert_expr_next_g_monotone a1 ab nerr gi).
destruct (
convert_expr a1 ab nerr gi)
as [[[
e2 ab2]
nerr2]
gi''].
specialize (
MONOe1 _ _ _ _ eq_refl).
specialize (
IHeval_mexpr _ _ _ _ eq_refl).
destruct IHeval_mexpr as (ρ'2 &
Hab2 &
Hgi'' &
Hρ'1ρ'2 &
x' &
EVAL &
Hx').
fastunwrap.
simpl Z.of_N in *.
destruct H0;
inv Hx';
repeat (
match type of EQ with
|
context [
simplify_expr_alias ?
ab ?
e ?
gi] =>
let SIMPL :=
fresh "
SIMPL"
in let SIMPL_MONO :=
fresh "
SIMPL_MONO"
in
destruct (
simplify_expr_alias ab e gi)
as [[] ?]
eqn:
SIMPL;
assert (
SIMPL_MONO:=
SIMPL);
apply simplify_expr_alias_monotone in SIMPL_MONO;
(
eapply simplify_expr_alias_correct in SIMPL;[|
now eauto|
now eauto|
now eauto]);
destruct SIMPL as (? & ? & ? & ? & ?)
|
context [
normalize_expr ?
ab ?
e ?
min ?
max ?
logmod ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr ab e min max logmod gi)
as [[[] ?][]]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_next_g_monotone in NORM_MONO;
(
eapply normalize_expr_correct in NORM;[|
reflexivity|
now eauto|
now eauto|
now eauto]);
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
destruct NORM as (? & ? & ? & ?)]
|
context [
normalize_expr_signedness ?
ab ?
e ?
sgn ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr_signedness ab e sgn gi)
as [[] ?]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_signedness_next_g_monotone in NORM_MONO;
eapply normalize_expr_signedness_correct in NORM;
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
now eauto|
now eauto|
now eauto]
|
context [
normalize_expr_signedness64 ?
ab ?
e ?
sgn ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr_signedness64 ab e sgn gi)
as [[] ?]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_signedness64_next_g_monotone in NORM_MONO;
eapply normalize_expr_signedness64_correct in NORM;
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
now eauto|
now eauto|
now eauto]
end);
inv EQ.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.zero_ext 8 (
Int.repr x))
with (
Int.repr x1).
constructor.
rewrite <-
Int.repr_unsigned with (
Int.zero_ext 8 (
Int.repr x)).
f_equal.
assert (8 <
Int.zwordsize)
by reflexivity.
apply Int.eqmod_small_eq with 256. 2:
omega. 2:
apply Int.zero_ext_range;
omega.
eapply Int.eqmod_trans.
eapply Int.eqmod_sym,
H4.
eapply Int.eqmod_trans,
Int.eqmod_sym,
Int.eqmod_zero_ext. 2:
omega.
eapply Int.eqmod_divides.
eapply Int.eqm_unsigned_repr.
apply Z.mod_divide.
discriminate.
reflexivity.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split. 2:
apply related_unsigned.
constructor.
destruct (
Int.zero_ext_range 8 (
Int.repr x)).
compute;
split;
congruence.
change (
two_p 8)
with 256
in H5.
split;
simpl;
omega.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.sign_ext 8 (
Int.repr x))
with (
Int.repr x1).
constructor.
rewrite <-
Int.repr_signed with (
Int.sign_ext 8 (
Int.repr x)).
f_equal.
assert (8 <
Int.zwordsize)
by reflexivity.
apply Z.add_cancel_r with (
p:=128).
apply Int.eqmod_small_eq with 256. 2:
omega.
apply Int.eqmod_add. 2:
apply Int.eqmod_refl.
eapply Int.eqmod_trans.
eapply Int.eqmod_sym,
H4.
eapply Int.eqmod_trans,
Int.eqmod_sym,
Int.eqmod_sign_ext. 2:
omega.
eapply Int.eqmod_divides.
eapply Int.eqm_unsigned_repr.
apply Z.mod_divide.
discriminate.
reflexivity.
destruct (
Int.sign_ext_range 8 (
Int.repr x)).
omega.
change (
two_p (8-1))
with 128
in H7,
H8.
omega.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split. 2:
apply related_signed.
constructor.
destruct (
Int.sign_ext_range 8 (
Int.repr x)).
compute;
split;
congruence.
change (
two_p (8-1))
with 128
in H4,
H5.
split;
simpl;
omega.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.zero_ext 16 (
Int.repr x))
with (
Int.repr x1).
constructor.
rewrite <-
Int.repr_unsigned with (
Int.zero_ext 16 (
Int.repr x)).
f_equal.
assert (16 <
Int.zwordsize)
by reflexivity.
apply Int.eqmod_small_eq with 65536. 2:
omega. 2:
apply Int.zero_ext_range;
omega.
eapply Int.eqmod_trans.
eapply Int.eqmod_sym,
H4.
eapply Int.eqmod_trans,
Int.eqmod_sym,
Int.eqmod_zero_ext. 2:
omega.
eapply Int.eqmod_divides.
eapply Int.eqm_unsigned_repr.
apply Z.mod_divide.
discriminate.
reflexivity.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split. 2:
apply related_unsigned.
constructor.
destruct (
Int.zero_ext_range 16 (
Int.repr x)).
compute;
split;
congruence.
change (
two_p 16)
with 65536
in H5.
split;
simpl;
omega.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.sign_ext 16 (
Int.repr x))
with (
Int.repr x1).
constructor.
rewrite <-
Int.repr_signed with (
Int.sign_ext 16 (
Int.repr x)).
f_equal.
assert (16 <
Int.zwordsize)
by reflexivity.
apply Z.add_cancel_r with (
p:=32768).
apply Int.eqmod_small_eq with 65536. 2:
omega.
apply Int.eqmod_add. 2:
apply Int.eqmod_refl.
eapply Int.eqmod_trans.
eapply Int.eqmod_sym,
H4.
eapply Int.eqmod_trans,
Int.eqmod_sym,
Int.eqmod_sign_ext. 2:
omega.
eapply Int.eqmod_divides.
eapply Int.eqm_unsigned_repr.
apply Z.mod_divide.
discriminate.
reflexivity.
destruct (
Int.sign_ext_range 16 (
Int.repr x)).
omega.
change (
two_p (16-1))
with 32768
in H7,
H8.
omega.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split. 2:
apply related_signed.
constructor.
destruct (
Int.sign_ext_range 16 (
Int.repr x)).
compute;
split;
congruence.
change (
two_p (16-1))
with 32768
in H4,
H5.
split;
simpl;
omega.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split.
eauto.
rewrite Int.neg_repr.
constructor.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split.
eauto.
replace (
Int.not (
Int.repr x))
with (
Int.repr (
Z.lnot x)).
constructor.
apply Int.same_bits_eq.
intros i Hi.
rewrite Int.bits_not, !
Int.testbit_repr,
Z.lnot_spec;
intuition.
+
eauto 10.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split. 2:
constructor.
Transparent Float.neg Float32.neg Float.of_single.
replace (
Float.of_single (
Float32.neg f))
with (
Float.neg (
Float.of_single f))
by (
apply Bconv_Bopp;
auto).
econstructor;
eauto.
+
eauto 10.
+
eexists.
split.
eauto.
split.
auto.
split.
auto.
eexists.
split. 2:
constructor.
Transparent Float.abs Float32.abs Float.of_single.
replace (
Float.of_single (
Float32.abs f))
with (
Float.abs (
Float.of_single f))
by (
apply Bconv_Babs;
auto).
econstructor;
eauto.
+
eauto 10.
+
eauto 10.
Transparent Float.to_int.
+
eexists.
split.
eauto.
split.
auto.
split.
eauto.
exists (
INz (
Int.signed i)).
split. 2:
apply related_signed.
intros.
apply eval_IEunop with (
n:=
INf f).
auto.
constructor.
unfold Float.to_int,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((
Int.min_signed <=?
z) && (
z <=?
Int.max_signed))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int.signed_repr by auto.
auto.
Transparent Float32.to_int.
+
eexists.
split.
eauto.
split.
auto.
split.
eauto.
exists (
INz (
Int.signed i)).
split. 2:
apply related_signed.
intros.
apply eval_IEunop with (
n:=
INf (
Float.of_single f)).
auto.
constructor.
unfold Float32.to_int,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((
Int.min_signed <=?
z) && (
z <=?
Int.max_signed))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int.signed_repr by auto.
rewrite ZofB_correct in *.
destruct (
floatofsingle_exact f), (
is_finite f);
inv Heqo.
rewrite H6,
H0;
auto.
Transparent Float.to_intu.
+
eexists.
split.
eauto.
split.
auto.
split.
eauto.
exists (
INz (
Int.unsigned i)).
split. 2:
apply related_unsigned.
intros.
apply eval_IEunop with (
n:=
INf f).
auto.
constructor.
unfold Float.to_intu,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((0 <=?
z) && (
z <=?
Int.max_unsigned))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int.unsigned_repr by auto.
auto.
Transparent Float32.to_intu.
+
eexists.
split.
eauto.
split.
auto.
split.
eauto.
exists (
INz (
Int.unsigned i)).
split. 2:
apply related_unsigned.
intros.
apply eval_IEunop with (
n:=
INf (
Float.of_single f)).
auto.
constructor.
unfold Float32.to_intu,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((0 <=?
z) && (
z <=?
Int.max_unsigned))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int.unsigned_repr by auto.
rewrite ZofB_correct in *.
destruct (
floatofsingle_exact f), (
is_finite f);
inv Heqo.
rewrite H6,
H0;
auto.
+
Transparent Float.of_int.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split. 2:
constructor.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float.of_int.
rewrite Int.signed_repr by auto.
econstructor.
eauto.
constructor.
+
Transparent Float32.of_int.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split. 2:
constructor.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float32.of_int.
rewrite Int.signed_repr by auto.
econstructor.
eauto.
constructor.
+
Transparent Float.of_intu.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split. 2:
constructor.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float.of_intu.
rewrite Int.unsigned_repr by auto.
econstructor.
eauto.
constructor.
+
Transparent Float32.of_intu.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split. 2:
constructor.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float32.of_intu.
rewrite Int.unsigned_repr by auto.
econstructor.
eauto.
constructor.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite Int64.neg_repr.
constructor.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
replace (
Int64.not (
Int64.repr x))
with (
Int64.repr (
Z.lnot x)).
constructor.
apply Int64.same_bits_eq.
intros i Hi.
rewrite Int64.bits_not, !
Int64.testbit_repr,
Z.lnot_spec;
intuition.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
replace (
Int64.loword (
Int64.repr x))
with (
Int.repr x).
constructor.
eapply Int.eqm_samerepr,
Int.eqmod_divides.
apply Int64.eqm_unsigned_repr.
exists Int.modulus.
reflexivity.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
rewrite Int.signed_repr by auto.
auto.
+
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
rewrite Int.unsigned_repr by auto.
auto.
+
Transparent Float.to_long.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
Int64.signed i)).
split. 2:
apply related_signed_long.
econstructor.
eauto.
constructor.
unfold Float.to_long,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((
Int64.min_signed <=?
z) && (
z <=?
Int64.max_signed))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int64.signed_repr by auto.
auto.
+
Transparent Float.to_longu.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
Int64.unsigned i)).
split. 2:
apply related_unsigned_long.
econstructor.
eauto.
constructor.
unfold Float.to_longu,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((0 <=?
z) && (
z <=?
Int64.max_unsigned))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int64.unsigned_repr by auto.
auto.
+
Transparent Float32.to_long.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
Int64.signed i)).
split. 2:
apply related_signed_long.
econstructor.
eauto.
constructor.
unfold Float32.to_long,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((
Int64.min_signed <=?
z) && (
z <=?
Int64.max_signed))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int64.signed_repr by auto.
rewrite ZofB_correct in *.
destruct (
is_finite f)
eqn:?.
rewrite (
proj2 (
floatofsingle_exact _)), (
proj1 (
floatofsingle_exact _));
auto.
discriminate.
+
Transparent Float32.to_longu.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
Int64.unsigned i)).
split. 2:
apply related_unsigned_long.
econstructor.
eauto.
constructor.
unfold Float32.to_longu,
ZofB_range in H0.
destruct (
ZofB f)
eqn:?; [|
discriminate].
destruct ((0 <=?
z) && (
z <=?
Int64.max_unsigned))%
bool eqn:?;
inv H0.
rewrite Bool.andb_true_iff, <- !
Zle_is_le_bool in Heqb.
rewrite Int64.unsigned_repr by auto.
rewrite ZofB_correct in *.
destruct (
is_finite f)
eqn:?.
rewrite (
proj2 (
floatofsingle_exact _)), (
proj1 (
floatofsingle_exact _));
auto.
discriminate.
+
Transparent Float.of_long.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float.of_long.
rewrite Int64.signed_repr by auto.
econstructor.
+
Transparent Float32.of_long.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float32.of_long.
rewrite Int64.signed_repr by auto.
econstructor.
+
Transparent Float.of_longu.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float.of_longu.
rewrite Int64.unsigned_repr by auto.
econstructor.
+
Transparent Float32.of_longu.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split;
eauto.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x1)
by trivial.
unfold Float32.of_longu.
rewrite Int64.unsigned_repr by auto.
econstructor.
-
specialize (
IHeval_mexpr1 _ _ _ Hρ'1
Hgi Hρρ'1
nerr).
assert (
MONO1:=
convert_expr_next_g_monotone a1 ab nerr gi).
destruct (
convert_expr a1 ab nerr gi)
as [[[
e1'
ab']
nerr1]
gi''].
specialize (
IHeval_mexpr1 _ _ _ _ eq_refl).
specialize (
MONO1 _ _ _ _ eq_refl).
edestruct IHeval_mexpr1 as (ρ'
e1 &
Hρ'
e1 &
Hgi'' &
Hρ'1ρ'
e1 &
x'
e1 &
EVAL1 &
Hx'
e1).
assert (
Hρρ'
e1 : ∀
id :
var0,
related (ρ
id) (ρ'
e1 (
Real id))).
{
intros.
rewrite <- (
proj1 Hρ'1ρ'
e1).
auto. }
specialize (
IHeval_mexpr2 _ _ _ Hρ'
e1 Hgi''
Hρρ'
e1 nerr1).
assert (
MONO2:=
convert_expr_next_g_monotone a2 ab'
nerr1 gi'').
destruct (
convert_expr a2 ab'
nerr1 gi'')
as [[[
e2'
ab'']
nerr2]
gi'''].
specialize (
IHeval_mexpr2 _ _ _ _ eq_refl).
specialize (
MONO2 _ _ _ _ eq_refl).
edestruct IHeval_mexpr2 as (ρ'
e2 &
Hρ'
e2 &
Hgi'''&
Hρ'
e1ρ'
e2 &
x'
e2 &
EVAL2 &
Hx'
e2).
destruct H1;
inv Hx'
e1;
inv Hx'
e2;
repeat (
match type of EQ with
|
context [
normalize_expr ?
ab ?
e ?
min ?
max ?
logmod ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr ab e min max logmod gi)
as [[[] ?][]]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_next_g_monotone in NORM_MONO;
(
eapply normalize_expr_correct in NORM; [|
reflexivity|
now eauto|
now eauto|
now eauto]);
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
destruct NORM as (? & ? & ? & ?)];
simpl in EQ
|
context [
normalize_expr_signedness ?
ab ?
e ?
sgn ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr_signedness ab e sgn gi)
as [[] ?]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_signedness_next_g_monotone in NORM_MONO;
eapply normalize_expr_signedness_correct in NORM;
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
now eauto|
now eauto|
now eauto]
|
context [
normalize_expr_signedness64 ?
ab ?
e ?
sgn ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr_signedness64 ab e sgn gi)
as [[] ?]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_signedness64_next_g_monotone in NORM_MONO;
eapply normalize_expr_signedness64_correct in NORM;
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
now eauto|
now eauto|
now eauto]
end).
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
rewrite Int.add_unsigned.
erewrite Int.eqm_samerepr.
constructor.
apply Int.eqm_add;
eauto with ints.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
unfold Int.sub.
erewrite Int.eqm_samerepr.
constructor.
apply Int.eqm_sub;
eauto with ints.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
unfold Int.mul.
erewrite Int.eqm_samerepr.
constructor.
apply Int.eqm_mult;
eauto with ints.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
unfold Int.divs.
rewrite !
Int.signed_repr;
eauto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
in *
by trivial.
unfold Int.divu.
rewrite !
Int.unsigned_repr;
eauto.
rewrite Int.Zquot_Zdiv.
destruct zlt.
simpl in *.
omega.
constructor.
cut (
x4 <> 0).
simpl in *.
omega.
intro.
subst.
discriminate.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
unfold Int.mods.
rewrite !
Int.signed_repr;
eauto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
in *
by trivial.
unfold Int.modu.
rewrite !
Int.unsigned_repr;
eauto.
rewrite Z.rem_mod_nonneg.
constructor.
simpl in *.
omega.
cut (
x4 <> 0).
simpl in *.
omega.
intro.
subst.
discriminate.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.and (
Int.repr x) (
Int.repr x0))
with (
Int.repr (
Z.land x x0)).
constructor.
apply Int.same_bits_eq.
intros.
rewrite Int.bits_and, !
Int.testbit_repr,
Z.land_spec by trivial.
reflexivity.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.or (
Int.repr x) (
Int.repr x0))
with (
Int.repr (
Z.lor x x0)).
constructor.
apply Int.same_bits_eq.
intros.
rewrite Int.bits_or, !
Int.testbit_repr,
Z.lor_spec by trivial.
reflexivity.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int.xor (
Int.repr x) (
Int.repr x0))
with (
Int.repr (
Z.lxor x x0)).
constructor.
apply Int.same_bits_eq.
intros.
rewrite Int.bits_xor, !
Int.testbit_repr,
Z.lxor_spec by trivial.
reflexivity.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x2)
by trivial.
replace (
Int.shl (
Int.repr x) (
Int.repr x2))
with (
Int.repr (
Z.shiftl x x2)).
constructor.
apply Int.same_bits_eq.
intros.
rewrite Int.bits_shl by trivial.
rewrite Int.unsigned_repr by trivial.
destruct zlt.
rewrite Int.testbit_repr,
Z.shiftl_spec by omega.
apply Z.testbit_neg_r.
omega.
simpl in H5.
rewrite !
Int.testbit_repr,
Z.shiftl_spec by omega.
auto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
unfold Int.shr.
rewrite Int.signed_repr,
Int.unsigned_repr by trivial.
constructor.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
unfold Int.shru.
rewrite !
Int.unsigned_repr by trivial.
constructor.
+
inv EQ.
eauto 15.
+
inv EQ.
eauto 15.
+
inv EQ.
eauto 15.
+
inv EQ.
eauto 15.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto 10.
rewrite plus_double_round.
auto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto 10.
rewrite sub_double_round.
auto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto 10.
rewrite mult_double_round.
auto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto 10.
rewrite div_double_round.
auto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto 10.
rewrite Int64.add_unsigned.
erewrite Int64.eqm_samerepr.
constructor.
apply Int64.eqm_add;
eauto with ints.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto 10.
unfold Int64.sub.
erewrite Int64.eqm_samerepr.
constructor.
apply Int64.eqm_add;
eauto with ints.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
unfold Int64.mul.
erewrite Int64.eqm_samerepr.
econstructor.
apply Int64.eqm_mult;
eauto with ints.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int64.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
unfold Int64.divs.
rewrite !
Int64.signed_repr;
eauto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int64.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x0) (
y:=
x4)
in *
by trivial.
unfold Int64.divu.
rewrite !
Int64.unsigned_repr;
eauto.
rewrite Int64.Zquot_Zdiv.
destruct zlt.
simpl in *.
omega.
constructor.
cut (
x4 <> 0).
simpl in *.
omega.
intro.
subst.
discriminate.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int64.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
unfold Int64.mods.
rewrite !
Int64.signed_repr;
eauto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
constructor.
*
intro.
subst.
rewrite Int64.eqm_samerepr with (
x:=
x0) (
y:=0)
in H1 by trivial.
discriminate.
*
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x0) (
y:=
x4)
in *
by trivial.
unfold Int64.modu.
rewrite !
Int64.unsigned_repr;
eauto.
rewrite Z.rem_mod_nonneg.
constructor.
simpl in *.
omega.
cut (
x4 <> 0).
simpl in *.
omega.
intro.
subst.
discriminate.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int64.and (
Int64.repr x) (
Int64.repr x0))
with (
Int64.repr (
Z.land x x0)).
constructor.
apply Int64.same_bits_eq.
intros.
rewrite Int64.bits_and, !
Int64.testbit_repr,
Z.land_spec by trivial.
reflexivity.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int64.or (
Int64.repr x) (
Int64.repr x0))
with (
Int64.repr (
Z.lor x x0)).
constructor.
apply Int64.same_bits_eq.
intros.
rewrite Int64.bits_or, !
Int64.testbit_repr,
Z.lor_spec by trivial.
reflexivity.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
replace (
Int64.xor (
Int64.repr x) (
Int64.repr x0))
with (
Int64.repr (
Z.lxor x x0)).
constructor.
apply Int64.same_bits_eq.
intros.
rewrite Int64.bits_xor, !
Int64.testbit_repr,
Z.lxor_spec by trivial.
reflexivity.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x2)
by trivial.
replace (
Int64.shl' (
Int64.repr x) (
Int.repr x2))
with (
Int64.repr (
Z.shiftl x x2)).
constructor.
apply Int64.same_bits_eq.
intros.
rewrite Int64.bits_shl'
by trivial.
rewrite Int.unsigned_repr by trivial.
destruct zlt.
rewrite Int64.testbit_repr,
Z.shiftl_spec by omega.
apply Z.testbit_neg_r.
omega.
simpl in H5.
rewrite !
Int64.testbit_repr,
Z.shiftl_spec by omega.
auto.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
unfold Int64.shr'.
rewrite Int64.signed_repr,
Int.unsigned_repr by trivial.
constructor.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
econstructor;
eauto.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
unfold Int64.shru'.
rewrite Int64.unsigned_repr,
Int.unsigned_repr by trivial.
constructor.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
if Int.cmp c (
Int.repr x) (
Int.repr x0)
then F1 else F0)).
split.
econstructor;
eauto. 2:
destruct Int.cmp;
constructor.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
replace (
Int.cmp c (
Int.repr x2) (
Int.repr x4))
with (
Zcmp c x2 x4).
constructor.
unfold Int.cmp,
Int.lt.
rewrite !
Int.signed_repr by eauto.
pose proof (
Int.eq_spec (
Int.repr x2) (
Int.repr x4)).
destruct c;
simpl.
*
destruct Int.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int.signed (
Int.repr x2) =
Int.signed (
Int.repr x4))
by congruence.
rewrite !
Int.signed_repr in H16 by trivial.
omega.
assert (
Int.signed (
Int.repr x2) =
Int.signed (
Int.repr x4))
by congruence.
rewrite !
Int.signed_repr in H16 by trivial.
omega.
congruence.
*
destruct Int.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int.signed (
Int.repr x2) =
Int.signed (
Int.repr x4))
by congruence.
rewrite !
Int.signed_repr in H16 by trivial.
omega.
assert (
Int.signed (
Int.repr x2) =
Int.signed (
Int.repr x4))
by congruence.
rewrite !
Int.signed_repr in H16 by trivial.
omega.
congruence.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
if Int.cmpu c (
Int.repr x) (
Int.repr x0)
then F1 else F0)).
split.
econstructor;
eauto. 2:
destruct Int.cmpu;
constructor.
rewrite !
Int.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
replace (
Int.cmpu c (
Int.repr x2) (
Int.repr x4))
with (
Zcmp c x2 x4).
constructor.
unfold Int.cmpu,
Int.ltu.
rewrite !
Int.unsigned_repr by auto.
pose proof (
Int.eq_spec (
Int.repr x2) (
Int.repr x4)).
destruct c;
simpl.
*
destruct Int.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int.unsigned (
Int.repr x2) =
Int.unsigned (
Int.repr x4))
by congruence.
rewrite !
Int.unsigned_repr in H16 by trivial.
omega.
assert (
Int.unsigned (
Int.repr x2) =
Int.unsigned (
Int.repr x4))
by congruence.
rewrite !
Int.unsigned_repr in H16 by trivial.
omega.
congruence.
*
destruct Int.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int.unsigned (
Int.repr x2) =
Int.unsigned (
Int.repr x4))
by congruence.
rewrite !
Int.unsigned_repr in H16 by trivial.
omega.
assert (
Int.unsigned (
Int.repr x2) =
Int.unsigned (
Int.repr x4))
by congruence.
rewrite !
Int.unsigned_repr in H16 by trivial.
omega.
congruence.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
if Int64.cmp c (
Int64.repr x) (
Int64.repr x0)
then F1 else F0)).
split.
econstructor;
eauto. 2:
destruct Int64.cmp;
constructor.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
replace (
Int64.cmp c (
Int64.repr x2) (
Int64.repr x4))
with (
Zcmp c x2 x4).
constructor.
unfold Int64.cmp,
Int64.lt.
rewrite !
Int64.signed_repr by eauto.
pose proof (
Int64.eq_spec (
Int64.repr x2) (
Int64.repr x4)).
destruct c;
simpl.
*
destruct Int64.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int64.signed (
Int64.repr x2) =
Int64.signed (
Int64.repr x4))
by congruence.
rewrite !
Int64.signed_repr in H16 by trivial.
omega.
assert (
Int64.signed (
Int64.repr x2) =
Int64.signed (
Int64.repr x4))
by congruence.
rewrite !
Int64.signed_repr in H16 by trivial.
omega.
congruence.
*
destruct Int64.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int64.signed (
Int64.repr x2) =
Int64.signed (
Int64.repr x4))
by congruence.
rewrite !
Int64.signed_repr in H16 by trivial.
omega.
assert (
Int64.signed (
Int64.repr x2) =
Int64.signed (
Int64.repr x4))
by congruence.
rewrite !
Int64.signed_repr in H16 by trivial.
omega.
congruence.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
exists (
INz (
if Int64.cmpu c (
Int64.repr x) (
Int64.repr x0)
then F1 else F0)).
split.
econstructor;
eauto. 2:
destruct Int64.cmpu;
constructor.
rewrite !
Int64.eqm_samerepr with (
x:=
x) (
y:=
x2)
by trivial.
rewrite !
Int64.eqm_samerepr with (
x:=
x0) (
y:=
x4)
by trivial.
replace (
Int64.cmpu c (
Int64.repr x2) (
Int64.repr x4))
with (
Zcmp c x2 x4).
constructor.
unfold Int64.cmpu,
Int64.ltu.
rewrite !
Int64.unsigned_repr by auto.
pose proof (
Int64.eq_spec (
Int64.repr x2) (
Int64.repr x4)).
destruct c;
simpl.
*
destruct Int64.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int64.unsigned (
Int64.repr x2) =
Int64.unsigned (
Int64.repr x4))
by congruence.
rewrite !
Int64.unsigned_repr in H16 by trivial.
omega.
assert (
Int64.unsigned (
Int64.repr x2) =
Int64.unsigned (
Int64.repr x4))
by congruence.
rewrite !
Int64.unsigned_repr in H16 by trivial.
omega.
congruence.
*
destruct Int64.eq;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso.
assert (
Int64.unsigned (
Int64.repr x2) =
Int64.unsigned (
Int64.repr x4))
by congruence.
rewrite !
Int64.unsigned_repr in H16 by trivial.
omega.
assert (
Int64.unsigned (
Int64.repr x2) =
Int64.unsigned (
Int64.repr x4))
by congruence.
rewrite !
Int64.unsigned_repr in H16 by trivial.
omega.
congruence.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
*
destruct Coqlib.zlt;
destruct (
Z.compare_spec x2 x4);
try constructor;
exfalso;
omega.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
destruct Float.cmp;
constructor.
+
inv EQ.
eexists.
split.
eauto.
split.
eauto.
split.
eauto.
eexists.
split.
eauto.
rewrite Float32.cmp_double.
unfold Float32.to_double.
destruct Float.cmp;
constructor.
Qed.
Lemma convert_expr_nerr_monotone:
∀
e v gi e'
v'
gi',
~
convert_expr e v false gi = (
e',
v',
true,
gi').
Proof.
Ltac leb_case H :=
match type of H with
|
context [?
A <=? ?
B] =>
pose proof Zle_cases A B;
destruct (
A <=?
B)
end.
Lemma convert_expr_noerror:
∀ ρ
e v ρ'1
gi, ρ'1 ∈ γ
v -> ρ'1 ∈ γ
gi ->
(∀
id,
related (ρ
id) (ρ'1 (
Real id))) ->
∀
e'
v'
gi',
convert_expr e v true gi = (
e',
v',
true,
gi') ->
¬
error_mexpr ρ
e.
Proof.
induction e;
intros ab ρ'1
gi Hρ'1
Hgi Hρρ'1
e'
ab'
gi'
EQCVT ERR;
inv ERR;
simpl convert_expr in EQCVT.
-
destruct (
convert_expr e ab true gi)
as [[[
e0 ab0]
nerr0]
gi'']
eqn:
EQCVT'.
eapply convert_expr_ok in EQCVT';
eauto.
destruct EQCVT'
as (ρ'2 &
Hρ'2 &
Hgi'' &
Hρ'1ρ'2 &
x' &
EVAL &
REL).
destruct H2;
inv REL;
match type of EQCVT with
|
context [
simplify_expr_alias ?
ab ?
e ?
gi] =>
let SIMPL :=
fresh "
SIMPL"
in let SIMPL_MONO :=
fresh "
SIMPL_MONO"
in
destruct (
simplify_expr_alias ab e gi)
as [[] ?]
eqn:
SIMPL;
assert (
SIMPL_MONO:=
SIMPL);
apply simplify_expr_alias_monotone in SIMPL_MONO;
(
eapply simplify_expr_alias_correct in SIMPL;[|
now eauto|
now eauto|
now eauto]);
destruct SIMPL as (? & ? & ? & ? & ?)
end;
inv EQCVT.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float.to_int,
ZofB_range in H.
assert (∃
z,
ZofB f =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
rewrite H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int.max_signed));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int.min_signed));
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float.to_intu,
ZofB_range in H.
assert (∃
z,
ZofB f =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
rewrite H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int.max_unsigned));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 0);
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float.to_long,
ZofB_range in H.
assert (∃
z,
ZofB f =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
rewrite H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int64.max_signed));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int64.min_signed));
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float.to_longu,
ZofB_range in H.
assert (∃
z,
ZofB f =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
rewrite H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int64.max_unsigned));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 0);
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float32.to_int,
ZofB_range in H.
assert (∃
z,
ZofB (
Float.of_single f) =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
assert (
ZofB (
Float.of_single f) =
ZofB f).
{
rewrite !
ZofB_correct.
destruct (
floatofsingle_exact f),
f;
auto.
rewrite H10,
H11;
auto. }
rewrite <-
H10,
H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int.max_signed));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int.min_signed));
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float32.to_intu,
ZofB_range in H.
assert (∃
z,
ZofB (
Float.of_single f) =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
assert (
ZofB (
Float.of_single f) =
ZofB f).
{
rewrite !
ZofB_correct.
destruct (
floatofsingle_exact f),
f;
auto.
rewrite H10,
H11;
auto. }
rewrite <-
H10,
H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int.max_unsigned));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 0);
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float32.to_long,
ZofB_range in H.
assert (∃
z,
ZofB (
Float.of_single f) =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
assert (
ZofB (
Float.of_single f) =
ZofB f).
{
rewrite !
ZofB_correct.
destruct (
floatofsingle_exact f),
f;
auto.
rewrite H10,
H11;
auto. }
rewrite <-
H10,
H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int64.max_signed));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int64.min_signed));
try Psatz.lia.
auto.
+
rewrite !
Bool.andb_true_iff in H8;
destruct H8 as [[[] ?] ?].
unfold Float32.to_longu,
ZofB_range in H.
assert (∃
z,
ZofB (
Float.of_single f) =
Some z).
{
erewrite ZofB_correct,
check_finitef_correct by eauto.
eauto. }
destruct H9.
assert (
ZofB (
Float.of_single f) =
ZofB f).
{
rewrite !
ZofB_correct.
destruct (
floatofsingle_exact f),
f;
auto.
rewrite H10,
H11;
auto. }
rewrite <-
H10,
H9 in H.
leb_case H.
leb_case H.
discriminate.
*
rewrite (
is_bot_spec x)
in H8.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 (
Int64.max_unsigned));
try Psatz.lia.
auto.
*
rewrite (
is_bot_spec x)
in H7.
discriminate.
eapply assume_cmp_correct;
eauto 3.
econstructor.
eauto.
constructor.
eauto.
simpl.
destruct (
Z.compare_spec x0 0);
try Psatz.lia.
auto.
-
destruct (
convert_expr e ab true gi)
as [[[
e0 ab0]
nerr0]
gi'']
eqn:
EQCVT'.
assert (
nerr0 =
true).
{
destruct u;
try congruence;
try (
destruct normalize_expr as [[[? ?] ?][]];
congruence);
try (
destruct normalize_expr_signedness as [[? ?] ?];
congruence);
try (
destruct normalize_expr_signedness64 as [[? ?] ?];
congruence);
destruct (
simplify_expr_alias ab0 e0 gi'')
as [[? ?] ?];
injection EQCVT;
destruct nerr0;
simpl;
congruence. }
subst.
eapply IHe;
eauto.
-
destruct (
convert_expr e1 ab true gi)
as [[[
e01 ab01]
nerr01]
gi'']
eqn:
EQCVT'1.
eapply convert_expr_ok in EQCVT'1;
eauto.
destruct EQCVT'1
as (ρ'
e1 &
Hρ'
e1 &
Hgi'' &
Hρ'1ρ'
e1 &
x'
e1 &
EVAL1 &
REL1).
assert (
MONO2:=
convert_expr_next_g_monotone e2 ab01 nerr01 gi'').
destruct (
convert_expr e2 ab01 nerr01 gi'')
as [[[
e02 ab02]
nerr02]
gi''']
eqn:
EQCVT'2.
specialize (
MONO2 _ _ _ _ eq_refl).
assert (
Hρρ'
e1 : ∀
id,
related (ρ
id) (ρ'
e1 (
Real id))).
{
intros.
rewrite <- (
proj1 (
Hρ'1ρ'
e1)).
auto. }
eapply convert_expr_ok in EQCVT'2;
eauto.
destruct EQCVT'2
as (ρ'
e2 &
Hρ'
e2 &
Hgi''' &
Hρ'
e1ρ'
e2 &
x'
e2 &
EVAL2 &
REL2).
assert (
EVAL1':∀ ρ'',
compat_gh gi''' ρ'
e2 ρ'' ->
eval_iexpr ρ''
e01 x'
e1).
{
intros.
apply EVAL1.
split;
intros;
etransitivity.
apply Hρ'
e1ρ'
e2.
apply H.
apply Hρ'
e1ρ'
e2.
auto.
apply H.
Psatz.lia. }
fastunwrap.
simpl Z.of_N in *.
destruct H4;
inv REL1;
inv REL2;
repeat (
match type of EQCVT with
|
context [
simplify_expr_alias ?
ab ?
e ?
gi] =>
let SIMPL :=
fresh "
SIMPL"
in let SIMPL_MONO :=
fresh "
SIMPL_MONO"
in
destruct (
simplify_expr_alias ab e gi)
as [[] ?]
eqn:
SIMPL;
assert (
SIMPL_MONO:=
SIMPL);
apply simplify_expr_alias_monotone in SIMPL_MONO;
(
eapply simplify_expr_alias_correct in SIMPL;[|
now eauto|
now eauto|
now eauto]);
destruct SIMPL as (? & ? & ? & ? & ?)
|
context [
normalize_expr ?
ab ?
e ?
min ?
max ?
logmod ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr ab e min max logmod gi)
as [[[] ?][]]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_next_g_monotone in NORM_MONO;
(
eapply normalize_expr_correct in NORM; [|
reflexivity|
now eauto|
now eauto|
now eauto]);
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
destruct NORM as (? & ? & ? & ?)];
simpl in EQCVT
|
context [
normalize_expr_signedness ?
ab ?
e ?
sgn ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr_signedness ab e sgn gi)
as [[] ?]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_signedness_next_g_monotone in NORM_MONO;
eapply normalize_expr_signedness_correct in NORM;
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
now eauto|
now eauto|
now eauto]
|
context [
normalize_expr_signedness64 ?
ab ?
e ?
sgn ?
gi] =>
let NORM :=
fresh "
NORM"
in let NORM_MONO :=
fresh "
NORM_MONO"
in
destruct (
normalize_expr_signedness64 ab e sgn gi)
as [[] ?]
eqn:
NORM;
assert (
NORM_MONO:=
NORM);
apply normalize_expr_signedness64_next_g_monotone in NORM_MONO;
eapply normalize_expr_signedness64_correct in NORM;
[
destruct NORM as (? & ? & ? & ? & ? & ? & ? & ?)|
now eauto|
now eauto|
now eauto]
end);
inv EQCVT;
repeat match goal with
|
HH :
_ &&
_ =
true |-
_ =>
rewrite Bool.andb_true_iff in HH;
destruct HH
end.
+
change (
Int.unsigned (
Int.repr x0) = 0)
in H0.
rewrite <-
Int.signed_eq_unsigned in H0 by (
rewrite H0;
compute;
congruence).
erewrite Int.eqm_samerepr,
Int.signed_repr in H0 by eauto.
subst.
erewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int.unsigned (
Int.repr x) =
Int.unsigned (
Int.repr (
Int.min_signed)))
in H0.
change (
Int.unsigned (
Int.repr x0) =
Int.unsigned (
Int.repr (-1)))
in H1.
eapply f_equal with (
f:=
Int.signed ∘
Int.repr)
in H0.
eapply f_equal with (
f:=
Int.signed ∘
Int.repr)
in H1.
rewrite !
Int.repr_unsigned in H0,
H1.
erewrite Int.eqm_samerepr,
Int.signed_repr in H0,
H1 by eauto.
subst.
erewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int.unsigned (
Int.repr x0) = 0)
in H0.
erewrite Int.eqm_samerepr,
Int.unsigned_repr in H0 by eauto.
subst.
erewrite (
is_bot_spec x3)
in H15.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int.unsigned (
Int.repr x0) = 0)
in H0.
rewrite <-
Int.signed_eq_unsigned in H0 by (
rewrite H0;
compute;
congruence).
erewrite Int.eqm_samerepr,
Int.signed_repr in H0 by eauto.
subst.
erewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int.unsigned (
Int.repr x) =
Int.unsigned (
Int.repr (
Int.min_signed)))
in H0.
change (
Int.unsigned (
Int.repr x0) =
Int.unsigned (
Int.repr (-1)))
in H1.
eapply f_equal with (
f:=
Int.signed ∘
Int.repr)
in H0.
eapply f_equal with (
f:=
Int.signed ∘
Int.repr)
in H1.
rewrite !
Int.repr_unsigned in H0,
H1.
erewrite Int.eqm_samerepr,
Int.signed_repr in H0,
H1 by eauto.
subst.
erewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int.unsigned (
Int.repr x0) = 0)
in H0.
erewrite Int.eqm_samerepr,
Int.unsigned_repr in H0 by eauto.
subst.
erewrite (
is_bot_spec x3)
in H15.
discriminate.
eauto using assume_cmp_correct.
+
rewrite (
is_bot_spec x1)
in H9.
discriminate.
eapply assume_cmp_correct;
eauto 2.
erewrite Int.eqm_samerepr in H by eauto.
unfold Int.ltu in H.
rewrite Int.unsigned_repr in H by auto.
destruct zlt.
discriminate.
change (
x2 >=
Int.zwordsize)
in g.
simpl.
destruct (
Z.compare_spec x2 Int.zwordsize);
try omega;
auto.
+
rewrite (
is_bot_spec x3)
in H15.
discriminate.
eapply assume_cmp_correct;
eauto 2.
erewrite Int.eqm_samerepr in H by eauto.
unfold Int.ltu in H.
rewrite Int.unsigned_repr in H by auto.
destruct zlt.
discriminate.
change (
x4 >=
Int.zwordsize)
in g0.
simpl.
destruct (
Z.compare_spec x4 Int.zwordsize);
try omega;
auto.
+
rewrite (
is_bot_spec x3)
in H15.
discriminate.
eapply assume_cmp_correct;
eauto 2.
erewrite Int.eqm_samerepr in H by eauto.
unfold Int.ltu in H.
rewrite Int.unsigned_repr in H by auto.
destruct zlt.
discriminate.
change (
x4 >=
Int.zwordsize)
in g0.
simpl.
destruct (
Z.compare_spec x4 Int.zwordsize);
try omega;
auto.
+
change (
Int64.unsigned (
Int64.repr x0) = 0)
in H0.
rewrite <-
Int64.signed_eq_unsigned in H0 by (
rewrite H0;
compute;
congruence).
erewrite Int64.eqm_samerepr,
Int64.signed_repr in H0 by eauto.
subst.
rewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int64.unsigned (
Int64.repr x) =
Int64.unsigned (
Int64.repr (
Int64.min_signed)))
in H0.
change (
Int64.unsigned (
Int64.repr x0) =
Int64.unsigned (
Int64.repr (-1)))
in H1.
eapply f_equal with (
f:=
Int64.signed ∘
Int64.repr)
in H0.
eapply f_equal with (
f:=
Int64.signed ∘
Int64.repr)
in H1.
rewrite !
Int64.repr_unsigned in H0,
H1.
erewrite Int64.eqm_samerepr,
Int64.signed_repr in H0,
H1 by eauto.
subst.
rewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int64.unsigned (
Int64.repr x0) = 0)
in H0.
erewrite Int64.eqm_samerepr,
Int64.unsigned_repr in H0 by eauto.
subst.
rewrite (
is_bot_spec x3)
in H15.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int64.unsigned (
Int64.repr x0) = 0)
in H0.
rewrite <-
Int64.signed_eq_unsigned in H0 by (
rewrite H0;
compute;
congruence).
erewrite Int64.eqm_samerepr,
Int64.signed_repr in H0 by eauto.
subst.
rewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int64.unsigned (
Int64.repr x) =
Int64.unsigned (
Int64.repr (
Int64.min_signed)))
in H0.
change (
Int64.unsigned (
Int64.repr x0) =
Int64.unsigned (
Int64.repr (-1)))
in H1.
eapply f_equal with (
f:=
Int64.signed ∘
Int64.repr)
in H0.
eapply f_equal with (
f:=
Int64.signed ∘
Int64.repr)
in H1.
rewrite !
Int64.repr_unsigned in H0,
H1.
erewrite Int64.eqm_samerepr,
Int64.signed_repr in H0,
H1 by eauto.
subst.
rewrite (
is_bot_spec x3)
in H16.
discriminate.
eauto using assume_cmp_correct.
+
change (
Int64.unsigned (
Int64.repr x0) = 0)
in H0.
erewrite Int64.eqm_samerepr,
Int64.unsigned_repr in H0 by eauto.
subst.
rewrite (
is_bot_spec x3)
in H15.
discriminate.
eauto using assume_cmp_correct.
+
rewrite (
is_bot_spec x1)
in H9.
discriminate.
eapply assume_cmp_correct;
eauto 2.
erewrite Int.eqm_samerepr in H by eauto.
unfold Int.ltu in H.
rewrite Int.unsigned_repr in H by auto.
destruct zlt.
discriminate.
change (
x2 >=
Int64.zwordsize)
in g.
simpl.
destruct (
Z.compare_spec x2 Int64.zwordsize);
try omega;
auto.
+
rewrite (
is_bot_spec x3)
in H15.
discriminate.
eapply assume_cmp_correct;
eauto 2.
erewrite Int.eqm_samerepr in H by eauto.
unfold Int.ltu in H.
rewrite Int.unsigned_repr in H by auto.
destruct zlt.
discriminate.
change (
x4 >=
Int64.zwordsize)
in g0.
simpl.
destruct (
Z.compare_spec x4 Int64.zwordsize);
try omega;
auto.
+
rewrite (
is_bot_spec x3)
in H15.
discriminate.
eapply assume_cmp_correct;
eauto 2.
erewrite Int.eqm_samerepr in H by eauto.
unfold Int.ltu in H.
rewrite Int.unsigned_repr in H by auto.
destruct zlt.
discriminate.
change (
x4 >=
Int64.zwordsize)
in g0.
simpl.
destruct (
Z.compare_spec x4 Int64.zwordsize);
try omega;
auto.
-
destruct (
convert_expr e1 ab true gi)
as [[[
e01 ab01]
nerr01]
gi'']
eqn:
EQCVT'1.
destruct (
convert_expr e2 ab01 nerr01 gi'')
as [[[
e02 ab02]
nerr02]
g''']
eqn:
EQCVT'2.
assert (
nerr01 =
true).
{
destruct nerr01,
nerr02;
auto.
apply convert_expr_nerr_monotone in EQCVT'2.
contradiction.
destruct b;
simpl in EQCVT;
repeat (
match type of EQCVT with
|
context [
normalize_expr ?
ab ?
e ?
min ?
max ?
logmod ?
gi] =>
destruct (
normalize_expr ab e min max logmod gi)
as [[[] ?][]]
|
context [
normalize_expr_signedness ?
ab ?
e ?
sgn ?
gi] =>
destruct (
normalize_expr_signedness ab e sgn gi)
as [[] ?]
|
context [
normalize_expr_signedness64 ?
ab ?
e ?
sgn ?
gi] =>
destruct (
normalize_expr_signedness64 ab e sgn gi)
as [[] ?]
end);
congruence. }
subst.
eapply IHe1;
eauto.
-
destruct (
convert_expr e1 ab true gi)
as [[[
e01 ab01]
nerr01]
gi'']
eqn:
EQCVT'1.
edestruct convert_expr_ok as (ρ'
e1 &
Hρ'
e1 &
Hgi'' &
Hρ'1ρ'
e1 &
x'
e1 &
EVAL &
Hx'
e1);
eauto.
destruct (
convert_expr e2 ab01 nerr01 gi'')
as [[[
e02 ab02]
nerr02]
gi''']
eqn:
EQCVT'2.
assert (
nerr01 =
true /\
nerr02 =
true).
{
destruct nerr01,
nerr02;
auto;
try (
destruct b;
simpl in EQCVT;
repeat (
match type of EQCVT with
|
context [
normalize_expr ?
ab ?
e ?
min ?
max ?
logmod ?
gi] =>
destruct (
normalize_expr ab e min max logmod gi)
as [[[] ?][]]
|
context [
normalize_expr_signedness ?
ab ?
e ?
sgn ?
gi] =>
destruct (
normalize_expr_signedness ab e sgn gi)
as [[] ?]
|
context [
normalize_expr_signedness64 ?
ab ?
e ?
sgn ?
gi] =>
destruct (
normalize_expr_signedness64 ab e sgn gi)
as [[] ?]
end);
congruence).
apply convert_expr_nerr_monotone in EQCVT'2.
contradiction. }
destruct H.
subst.
eapply IHe2;
eauto.
intros.
rewrite <- (
proj1 Hρ'1ρ'
e1).
auto.
Qed.
Definition forget_temps (
v:
abt) (
gi:
ghosts_info) :
abt+⊥ :=
positive_rec _ (
NotBot v)
(
fun x v =>
do v <-
v;
idnc_forget (
Ghost x)
v)
gi.(
next_g).
Lemma forget_temps_correct:
∀
ab (ρ:
var ->
ideal_num)
gi, ρ ∈ γ
ab ->
ρ ∈ γ (
forget_temps ab gi).
Proof.
Definition get_itv (
e:
mexpr var0) (
v:
abt *
typesmap) :
mach_num_itv+⊥ :=
let '(
ie,
v,
_,
gi) :=
convert_expr e (
NotBot (
fst v))
false init_ghost_info in
do v <-
v;
do itv <- (
idnc_get_query_chan v).(
AbIdealEnv.get_itv) (
simplify_expr ie);
match itv,
mexpr_ty e with
|
Just (
Az ((
ZITV a b)
as itv')),
MNTint =>
NotBot (
MNIint
(
match itv_normalizer (
NotBot (
Just itv'))
(
fst intrange) (
snd intrangeu)
intzwordsize with
|
Some q =>
Just (
ZITV (
Zfastsub a (
Zfastshl q intzwordsize))
(
Zfastsub b (
Zfastshl q intzwordsize)))
|
None =>
All
end))
|
All,
MNTint =>
NotBot (
MNIint All)
|
Just (
Az ((
ZITV a b)
as itv')),
MNTint64 =>
NotBot (
MNIint64
(
match itv_normalizer (
NotBot (
Just itv'))
(
fst int64range) (
snd int64rangeu)
int64zwordsize with
|
Some q =>
Just (
ZITV (
Zfastsub a (
Zfastshl q int64zwordsize))
(
Zfastsub b (
Zfastshl q int64zwordsize)))
|
None =>
All
end))
|
All,
MNTint64 =>
ret (
MNIint64 All)
|
Just (
Af itv),
MNTfloat =>
ret (
MNIfloat (
Just itv))
|
Just (
Af itv),
MNTsingle =>
ret (
MNIsingle (
Just itv))
|
All,
MNTfloat =>
ret (
MNIfloat All)
|
All,
MNTsingle =>
ret (
MNIsingle All)
|
_,
_ =>
Bot
end.
Lemma get_itv_correct:
∀
e ρ
ab, ρ ∈ γ
ab ->
eval_mexpr ρ
e ⊆ γ (
get_itv e ab).
Proof.
Definition forget (
x:
var0) (
v:
abt *
typesmap) : (
abt *
typesmap)+⊥ :=
do fstres <-
idnc_forget (
Real x) (
fst v);
ret (
fstres,
Cells.ACTree.remove x (
snd v)).
Lemma forget_correct:
∀
x ρ, ∀
n ab,
ρ ∈ γ
ab ->
(
upd ρ
x n) ∈ γ (
forget x ab).
Proof.
Fixpoint infer_var_types (
e:
mexpr var0) (
ctx:
option signedness) (
typs:
typesmap)
:
typesmap :=
match e with
|
MEvar nvt x =>
match ctx with
|
None =>
match Cells.ACTree.get x typs with
|
None =>
match nvt with
|
MNTfloat |
MNTsingle =>
typs
|
_ =>
Cells.ACTree.set x (
None,
nvt)
typs
end
|
Some _ =>
typs
end
|
Some _ =>
Cells.ACTree.set x (
ctx,
nvt)
typs
end
|
MEconst _ =>
typs
|
MEunop op e =>
let ctx :=
match op with
| (
Ofloatofint |
Ofloatoflong |
Olongofint |
Osingleofint |
Osingleoflong |
Ocast16signed |
Ocast8signed) =>
Some Signed
| (
Ofloatofintu |
Ofloatoflongu |
Olongofintu |
Osingleofintu |
Osingleoflongu |
Ocast16unsigned |
Ocast8unsigned) =>
Some Unsigned
|
_ =>
None
end
in
infer_var_types e ctx typs
|
MEbinop op e1 e2 =>
let ctx1 :=
match op with
| (
Odiv |
Omod |
Odivl |
Omodl |
Ocmp _ |
Ocmpl _ |
Oshr |
Oshrl) =>
Some Signed
| (
Odivu |
Omodu |
Odivlu |
Omodlu |
Ocmpu _ |
Ocmplu _ |
Oshru |
Oshrlu) =>
Some Unsigned
|
_ =>
None
end
in
let ctx2 :=
match op with
| (
Odiv |
Omod |
Odivl |
Omodl |
Ocmp _ |
Ocmpl _) =>
Some Signed
| (
Odivu |
Omodu |
Odivlu |
Omodlu |
Ocmpu _ |
Ocmplu _ |
Oshl |
Oshr |
Oshru |
Oshll |
Oshrl |
Oshrlu) =>
Some Unsigned
|
_ =>
None
end
in
(
infer_var_types e2 ctx2 (
infer_var_types e1 ctx1 typs))
end.
Lemma infer_var_types_consistent :
∀ ρ
e nv ctx typs,
eval_mexpr ρ
e nv ->
ρ ∈ γ
typs ->
(
match nv with MNfloat _ |
MNsingle _ =>
ctx =
None |
_ =>
True end) ->
ρ ∈ γ (
infer_var_types e ctx typs).
Proof.
induction e;
simpl;
intros nv ctx typs H Htyps Hfl v' [
s ty]
Hmap;
inv H;
simpl.
-
destruct ctx.
+
erewrite Cells.ACTree.gsspec in Hmap;
eauto.
destruct Cells.ACTree.elt_eq.
inv Hmap.
split;
auto.
inv H4;
try easy.
rewrite <-
H1 in Hfl.
destruct Hfl.
congruence.
rewrite <-
H1 in Hfl.
destruct Hfl.
congruence.
apply Htyps in Hmap.
auto.
+
destruct (
Cells.ACTree.get v typs)
eqn:?.
apply Htyps in Hmap.
auto.
destruct m.
*
erewrite Cells.ACTree.gsspec in Hmap;
eauto.
destruct Cells.ACTree.elt_eq.
inv Hmap.
auto.
apply Htyps in Hmap.
auto.
*
erewrite Cells.ACTree.gsspec in Hmap;
eauto.
destruct Cells.ACTree.elt_eq.
inv Hmap.
auto.
apply Htyps in Hmap.
auto.
*
apply Htyps in Hmap.
auto.
*
apply Htyps in Hmap.
auto.
-
apply Htyps in Hmap.
auto.
-
match goal with Hmap :
context [
infer_var_types e ?
ctx'
typs] |-
_ =>
set ctx'
in Hmap end.
edestruct (
IHe _ o typs H2);
eauto.
destruct H4;
auto.
-
match goal with Hmap :
context [
infer_var_types e1 ?
ctx'
typs] |-
_ =>
set ctx'
in Hmap end.
match goal with Hmap :
context [
infer_var_types e2 ?
ctx'
_] |-
_ =>
set ctx'
in Hmap end.
edestruct (
fun typs =>
IHe2 _ o0 typs H5). 3:
eauto. 2:
destruct H6;
auto. 2:
auto.
intros v [
s'
ty']
Hmap'.
edestruct (
IHe1 _ o typs H3);
eauto.
destruct H6;
auto.
Qed.
Definition assign_vars_to_top (
e:
mexpr var0) (
v:
abt *
typesmap) : (
abt *
typesmap)+⊥ :=
let types :=
infer_var_types e None (
Cells.ACTree.empty _)
in
Cells.ACTree.fold (
fun ab v sty =>
do (
ab,
typs) <-
ab;
match sty with
| (
Some s,
ty) =>
let typs :=
Cells.ACTree.set v sty typs in
match get_itv (
MEvar ty v) (
ab,
typs)
with
|
NotBot (
MNIint All) |
NotBot (
MNIint64 All) =>
do ab <- (
idnc_assign (
Real v) (
IEZitv
(
match s,
ty with
|
Signed,
MNTint =>
signed_itv
|
Unsigned,
MNTint =>
unsigned_itv
|
Signed,
MNTint64 =>
signed64_itv
|
Unsigned,
MNTint64 =>
unsigned64_itv
|
_,
_ =>
signed_itv
end))
ab);
ret (
ab,
typs)
|
_ =>
ret (
ab,
typs)
end
| (
None,
_) =>
let typs :=
match Cells.ACTree.get v typs with
|
None =>
Cells.ACTree.set v sty typs
|
Some _ =>
typs
end
in
ret (
ab,
typs)
end)
types (
NotBot v).
Lemma assign_vars_to_top_correct:
forall ab e ρ
v,
eval_mexpr ρ
e v ->
γ
ab ρ -> γ (
assign_vars_to_top e ab) ρ.
Proof.
unfold assign_vars_to_top.
intros.
pose proof infer_var_types_consistent ρ
e _ None (
Cells.ACTree.empty _)
H.
lapply H1. 2:
intro;
rewrite Cells.ACTree.gempty;
discriminate.
clear H1.
intro.
lapply H1. 2:
destruct v;
now auto.
clear H1.
change (γ (
NotBot ab) ρ)
in H0.
revert H0.
generalize (
NotBot ab).
clear ab.
generalize (
infer_var_types e None).
clear e v H.
intros.
revert ρ
H0 H.
assert (∀
v s0,
Cells.ACTree.get v (
t (
Cells.ACTree.empty _)) =
Some s0 <->
List.In (
v,
s0) (
Cells.ACTree.elements (
t (
Cells.ACTree.empty _)))).
{
split.
apply Cells.ACTree.elements_correct.
apply Cells.ACTree.elements_complete. }
simpl.
unfold gamma_typs.
setoid_rewrite H.
clear H.
rewrite Cells.ACTree.fold_spec, <-
fold_left_rev_right.
setoid_rewrite in_rev.
induction (
rev (
Cells.ACTree.elements (
t (
Cells.ACTree.empty _)))).
auto.
simpl.
intros.
eapply botbind_spec with ρ; [|
apply IHl];
eauto.
intros.
destruct a.
specialize (
H0 _ _ (
or_introl eq_refl)).
destruct H0,
p.
destruct a0,
H1 as [[? []] ?].
destruct o.
2:
simpl;
destruct (
Cells.ACTree.get e t0); (
split; [
eexists;
split;
now eauto|]);
auto;
simpl;
intro;
rewrite Cells.ACTree.gsspec;
destruct Cells.ACTree.elt_eq; [|
now apply H4];
intros s0 Hs0;
inv Hs0;
auto.
simpl.
assert (
eval_mexpr ρ (
MEvar m e) (ρ
e))
by (
constructor;
auto).
assert (γ (
Cells.ACTree.set e (
Some s,
m)
t0) ρ).
{
intro.
simpl.
rewrite Cells.ACTree.gsspec.
destruct Cells.ACTree.elt_eq.
-
intros.
inv H6.
auto.
-
apply H4. }
unfold snd in H2.
inv H2;
try discriminate.
+
assert (
ASS:=
idnc_assign_correct (
Real e)
(
e:=
IEZitv (
match s with
|
Signed =>
signed_itv
|
Unsigned =>
unsigned_itv
end))
(
n:=
INz (
Zwrap (
match s with
|
Signed =>
Int.signed i
|
Unsigned =>
Int.unsigned i
end)))
a H1).
lapply ASS.
2:
constructor;
destruct s;
[
apply signed_itv_correct|
apply unsigned_itv_correct].
clear ASS;
intro.
change Cells.ACTree.elt with var0 in *.
destruct idnc_assign.
contradiction.
assert (γ (
NotBot(
x0,
Cells.ACTree.set e (
Some s,
MNTint)
t0)) ρ).
{
split.
eexists.
split.
now eauto.
intro.
unfold upd.
destruct @
eq_dec;
auto.
inv e0.
rewrite <-
H9.
destruct s.
apply related_signed.
apply related_unsigned.
intro.
simpl.
rewrite Cells.ACTree.gsspec.
destruct Cells.ACTree.elt_eq.
intros.
inv H7.
split.
auto.
rewrite <-
H9.
constructor.
auto. }
destruct get_itv as [|[[]|[]| |]]; (
try now (
econstructor;
eauto));
eauto;
(
split; [
eexists;
eauto |
auto]).
+
assert (
ASS:=
idnc_assign_correct (
Real e)
(
e:=
IEZitv (
match s with
|
Signed =>
signed64_itv
|
Unsigned =>
unsigned64_itv
end))
(
n:=
INz (
Zwrap (
match s with
|
Signed =>
Int64.signed i
|
Unsigned =>
Int64.unsigned i
end)))
a H1).
lapply ASS.
2:
constructor;
destruct s;
[
apply signed64_itv_correct|
apply unsigned64_itv_correct].
clear ASS;
intro.
change Cells.ACTree.elt with var0 in *.
destruct idnc_assign.
contradiction.
assert (γ (
NotBot(
x0,
Cells.ACTree.set e (
Some s,
MNTint64)
t0)) ρ).
{
split.
eexists.
split.
now eauto.
intro.
unfold upd.
destruct @
eq_dec;
auto.
inv e0.
rewrite <-
H9.
destruct s.
apply related_signed_long.
apply related_unsigned_long.
intro.
simpl.
rewrite Cells.ACTree.gsspec.
destruct Cells.ACTree.elt_eq.
intros.
inv H7.
split.
auto.
rewrite <-
H9.
constructor.
auto. }
destruct get_itv as [|[[]|[]| |]]; (
try now (
econstructor;
eauto));
eauto;
(
split; [
eexists;
eauto |
auto]).
Qed.
Definition assign (
x:
var0) (
e:
mexpr var0) (
v:
abt*
typesmap) : (
abt*
typesmap)+⊥ :=
let v :=
assign_vars_to_top e v in
do (
v,
typs) <-
v;
let '(
e',
v,
_,
gi) :=
convert_expr e (
NotBot v)
false init_ghost_info in
do v <-
v;
let ty :=
mexpr_ty e in
let typs :=
Cells.ACTree.set x (
None,
ty)
typs in
let '(
v,
gi) :=
match ty with
|
MNTint =>
match normalize_expr (
NotBot v)
e'
(
fst intrange) (
snd intrangeu)
intzwordsize gi with
| (
e,
v,
gi,
true) =>
(
do v <-
v;
idnc_assign (
Real x)
e v,
gi)
|
_ =>
(
idnc_forget (
Real x)
v,
gi)
end
|
MNTint64 =>
match normalize_expr (
NotBot v)
e'
(
fst int64range) (
snd int64rangeu)
int64zwordsize gi with
| (
e,
v,
gi,
true) =>
(
do v <-
v;
idnc_assign (
Real x)
e v,
gi)
|
_ =>
(
idnc_forget (
Real x)
v,
gi)
end
|
MNTfloat |
MNTsingle =>
(
let e :=
simplify_expr e'
in idnc_assign (
Real x)
e v,
gi)
end
in
do v <-
v;
do v <-
forget_temps v gi;
ret (
v,
typs).
Lemma assign_correct:
∀
x e ρ, ∀
n ab,
ρ ∈ γ
ab ->
n ∈
eval_mexpr ρ
e ->
(
upd ρ
x n) ∈ γ (
assign x e ab).
Proof.
intros x e ρ
n ab0 Hρ
EVAL.
unfold assign,
intrange,
int64range,
intrangeu,
int64rangeu,
intzwordsize,
int64zwordsize,
fst,
snd.
apply botbind_spec with ρ.
2:
eauto using assign_vars_to_top_correct;
eauto.
clear Hρ.
intros [
ab typs] [[ρ' [
Hρ'
Hρρ']]
Htyps].
pose proof (
convert_expr_ok _ _ _ EVAL (
NotBot ab)
_ _ Hρ' (
gamma_gh_init _)
Hρρ'
false).
destruct convert_expr as [[[
e'
v']
nerr]
gi].
edestruct H as (ρ'2 &
Hρ'2 &
Hgi &
Hρ'ρ'2 &
x' &
Hx' &
Hnx');
auto.
clear H.
apply botbind_spec with ρ'2. 2:
now eauto.
intros.
pose proof (
mexpr_ty_correct EVAL).
destruct H0;
inv Hnx'.
-
destruct (
normalize_expr (
NotBot a)
e'
Int.min_signed Int.max_unsigned
Int.zwordsize gi)
as [[[
e1 ab1]
gi'][]]
eqn:
EQNORM.
edestruct normalize_expr_correct with (
b:=
true)
as
(ρ'3 &
Hρ'2ρ'3 &
Hρ'3 &
Hgi' &
x'0 &
Hx'0
bounded &
Hx'
x'0 &
EVALx'0);
eauto.
reflexivity.
{
eapply botbind_spec with (
upd ρ'3 (
Real x) (
INz x'0)).
-
intros.
eapply botbind_spec with (
upd ρ'3 (
Real x) (
INz x'0)).
2:
now apply forget_temps_correct,
H0.
split.
+
eexists.
split.
apply H1.
intro.
unfold upd.
destruct (
eq_dec id x), (
eq_dec (
Real id) (
Real x));
try congruence.
erewrite Int.eqm_samerepr.
econstructor.
auto.
rewrite <- (
proj1 Hρ'2ρ'3), <- (
proj1 Hρ'ρ'2).
auto.
+
intros y typsy.
simpl.
rewrite Cells.ACTree.gsspec.
unfold upd,
eq_dec,
Cells.ACellDec.
destruct Cells.ACTree.elt_eq.
intros eq.
inv eq.
split;
constructor.
auto.
-
eapply botbind_spec with ρ'3,
Hρ'3.
intros.
apply idnc_assign_correct;
auto. }
{
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INz x0)).
-
intros.
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INz x0)).
2:
now apply forget_temps_correct,
H0.
split.
+
eexists.
split.
apply H1.
intro.
unfold upd.
destruct (
eq_dec id x), (
eq_dec (
Real id) (
Real x));
try congruence.
auto.
rewrite <- (
proj1 Hρ'ρ'2).
auto.
+
intros y typsy.
simpl.
rewrite Cells.ACTree.gsspec.
unfold upd,
eq_dec,
Cells.ACellDec.
destruct Cells.ACTree.elt_eq.
intros eq.
inv eq.
split;
constructor.
auto.
-
apply idnc_forget_correct;
auto. }
-
destruct (
normalize_expr (
NotBot a)
e'
Int64.min_signed Int64.max_unsigned
Int64.zwordsize gi)
as [[[
e1 ab1]
gi'][]]
eqn:
EQNORM.
edestruct normalize_expr_correct with (
b:=
true)
as
(ρ'3 &
Hρ'2ρ'3 &
Hρ'3 &
Hgi' &
x'0 &
Hx'0
bounded &
Hx'
x'0 &
EVALx'0);
eauto.
reflexivity.
{
eapply botbind_spec with (
upd ρ'3 (
Real x) (
INz x'0)).
-
intros.
eapply botbind_spec with (
upd ρ'3 (
Real x) (
INz x'0)).
2:
now apply forget_temps_correct,
H0.
split.
+
eexists.
split.
apply H1.
intro.
unfold upd.
destruct (
eq_dec id x), (
eq_dec (
Real id) (
Real x));
try congruence.
erewrite Int64.eqm_samerepr.
econstructor.
auto.
rewrite <- (
proj1 Hρ'2ρ'3), <- (
proj1 Hρ'ρ'2).
auto.
+
intros y typsy.
simpl.
rewrite Cells.ACTree.gsspec.
unfold upd,
eq_dec,
Cells.ACellDec.
destruct Cells.ACTree.elt_eq.
intros eq.
inv eq.
split;
constructor.
auto.
-
eapply botbind_spec with ρ'3,
Hρ'3.
intros.
apply idnc_assign_correct;
auto. }
{
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INz x0)).
-
intros.
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INz x0)).
2:
now apply forget_temps_correct,
H0.
split.
+
eexists.
split.
apply H1.
intro.
unfold upd.
destruct (
eq_dec id x), (
eq_dec (
Real id) (
Real x));
try congruence.
auto.
rewrite <- (
proj1 Hρ'ρ'2).
auto.
+
intros y typsy.
simpl.
rewrite Cells.ACTree.gsspec.
unfold upd,
eq_dec,
Cells.ACellDec.
destruct Cells.ACTree.elt_eq.
intros eq.
inv eq.
split;
constructor.
auto.
-
apply idnc_forget_correct;
auto. }
-
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INf f)).
+
intros.
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INf f)).
2:
now apply forget_temps_correct,
H0.
split.
*
eexists.
split.
apply H1.
intro.
unfold upd.
destruct (
eq_dec id x), (
eq_dec (
Real id) (
Real x));
try congruence.
auto.
rewrite <- (
proj1 Hρ'ρ'2).
auto.
*
intros y typsy.
simpl.
rewrite Cells.ACTree.gsspec.
unfold upd,
eq_dec,
Cells.ACellDec.
destruct Cells.ACTree.elt_eq.
intro.
inv H2.
split.
reflexivity.
constructor.
auto.
+
apply idnc_assign_correct,
simplify_expr_correct;
auto.
-
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INf (
Float.of_single f))).
+
intros.
eapply botbind_spec with (
upd ρ'2 (
Real x) (
INf (
Float.of_single f))).
2:
now apply forget_temps_correct,
H0.
split.
*
eexists.
split.
apply H1.
intro.
unfold upd.
destruct (
eq_dec id x), (
eq_dec (
Real id) (
Real x));
try congruence.
auto.
rewrite <- (
proj1 Hρ'ρ'2).
auto.
*
intros y typsy.
simpl.
rewrite Cells.ACTree.gsspec.
unfold upd,
eq_dec,
Cells.ACellDec.
destruct Cells.ACTree.elt_eq.
intro.
inv H2.
split.
reflexivity.
constructor.
auto.
+
apply idnc_assign_correct,
simplify_expr_correct;
auto.
Qed.
Definition assume (
e:
mexpr var0) (
b:
bool) (
v:
abt *
typesmap) : (
abt*
typesmap)+⊥ :=
let v :=
assign_vars_to_top e v in
do (
v,
typs) <-
v;
let '(
e,
v,
_,
gi) :=
convert_expr e (
NotBot v)
false init_ghost_info in
do v <-
v;
match normalize_expr (
NotBot v)
e (
fst intrange) (
snd intrangeu)
intzwordsize gi with
| (
e,
v,
gi,
true) =>
do v <-
v;
do v <-
idnc_assume e b v;
do v <-
forget_temps v gi;
ret (
v,
typs)
|
_ =>
do v <-
forget_temps v gi;
ret (
v,
typs)
end.
Lemma assume_correct:
∀
e ρ
ab b,
ρ ∈ γ
ab ->
of_bool b ∈
eval_mexpr ρ
e ->
ρ ∈ γ (
assume e b ab).
Proof.
intros e ρ
ab b Hρ
EVAL.
unfold assume,
intrange,
intrangeu,
intzwordsize,
fst,
snd.
eapply botbind_spec with ρ. 2:
eauto using assign_vars_to_top_correct.
intros.
destruct a,
H as [[ρ' [
Hρ'
Hρρ']]
Htyps].
pose proof (
convert_expr_ok _ _ _ EVAL (
NotBot a)
_ _ Hρ' (
gamma_gh_init _)
Hρρ'
false).
destruct convert_expr as [[[
e'
v']
nerr']
gi].
edestruct H as (ρ'2 &
Hρ'2 &
Hgi &
Hρ'ρ'2 &
x' &
EVAL2 &
REL);
auto.
clear H.
eapply botbind_spec with ρ'2;
eauto.
assert (∃
z:
Z,
x' =
INz z)
by (
destruct b;
inv REL;
eauto).
destruct H;
subst.
intros.
destruct (
normalize_expr (
NotBot a0)
e'
Int.min_signed Int.max_unsigned
Int.zwordsize gi)
as [[[
e1 ab1]
gi'][]]
eqn:
EQNORM.
edestruct normalize_expr_correct with (
b:=
true)
as (ρ'3 &
Hρ'2ρ'3 &
Hρ'3 &
Hgi' &
x'0 &
Hx'0
bounded &
Hx'
x'0 &
EVALx'0);
eauto.
reflexivity.
-
eapply botbind_spec with ρ'3,
Hρ'3.
intros.
eapply botbind_spec with ρ'3.
intros.
+
eapply botbind_spec with ρ'3,
forget_temps_correct,
H1.
split.
exists ρ'3.
split.
auto.
intros.
rewrite <- (
proj1 Hρ'2ρ'3), <- (
proj1 Hρ'ρ'2).
auto.
auto.
+
apply idnc_assume_correct;
eauto.
replace (
if b return Zfast then F1 else F0)
with (
x'0:
Zfast).
auto.
inv REL. 2:
destruct b;
discriminate.
apply Int.eqm_samerepr in Hx'
x'0.
simpl in Hx'
x'0.
rewrite Hx'
x'0
in H2.
assert (
Int.repr x'0 =
if b then Int.one else Int.zero)
by
(
destruct b;
compute in H2;
unfold Int.one,
Int.zero;
congruence).
destruct (
Coqlib.zlt x'0 0).
*
exfalso.
apply (
f_equal Int.signed)
in H1.
rewrite Int.signed_repr in H1.
subst x'0.
destruct b;
discriminate.
split.
now intuition.
assert (0 <
Int.max_signed)
by reflexivity.
omega.
*
apply (
f_equal Int.unsigned)
in H1.
rewrite Int.unsigned_repr in H1 by intuition.
fastunwrap.
destruct b;
f_equal;
apply H1.
-
eapply botbind_spec with ρ'2,
forget_temps_correct,
H.
split.
exists ρ'2.
split.
eauto.
intros.
rewrite <- (
proj1 Hρ'ρ'2).
auto.
auto.
Qed.
Definition noerror (
e:
mexpr var0) (
v:
abt *
typesmap) :
bool :=
let '(
_,
_,
nerr,
_) :=
convert_expr e (
NotBot (
fst v))
true init_ghost_info in
nerr.
Lemma noerror_correct:
∀
e ρ
ab,
ρ ∈ γ
ab ->
noerror e ab =
true ->
error_mexpr ρ
e ->
False.
Proof.
Function zitv_concretize_int_aux (
from:
Z) (
nb:
N) (
acc:
ZSet.t) {
measure N.to_nat nb} :
ZSet.t :=
match nb with
|
N0 =>
acc
|
Npos p =>
let nb' :=
Pos.pred_N p in
zitv_concretize_int_aux (
Z.succ from)
nb' (
ZSet.add from acc)
end.
Proof.
Definition zitv_concretize_int (
max:
Nfast) (
i:
zitv) :
ZSet.t+⊤+⊥ :=
match i with
|
ZITV m M =>
if Zfastleb m M then
let n :=
Nfast_of_Zfast (
Zfastsub M m)
in
if Nfastleb n max
then NotBot (
Just (
zitv_concretize_int_aux m (
N.succ n)
ZSet.empty))
else NotBot All
else Bot
end.
Lemma zitv_concretize_int_correct:
∀
itv max z, γ
itv z ->
match zitv_concretize_int max itv with
|
NotBot (
Just ab) =>
ZSet.mem z ab
|
NotBot All =>
True
|
Bot =>
False
end.
Proof.
Definition concretize_int (
max:
N) (
e:
mexpr var0) (
ab:
abt*
typesmap) :
ZSet.t+⊤+⊥ :=
let ab :=
fst ab in
let '(
e,
ab,
_,
gi) :=
convert_expr e (
NotBot ab)
false init_ghost_info in
do ab <-
ab;
let e :=
simplify_expr e in
let c :=
idnc_get_query_chan ab in
do cong <-
c.(
get_congr)
e;
let '{|
ZCongruences_defs.zc_rem :=
rem;
ZCongruences_defs.zc_mod :=
modn |} :=
cong in
let modz :=
Zfast_of_Nfast modn in
if Nfastleb modn F0 then ret (
Just (
ZSetOp.singleton (
Int.unsigned (
Int.repr rem))))
else
do itv <-
c.(
AbIdealEnv.get_itv)
e;
do itv <-
in_z itv;
match itv with
|
All =>
ret All
|
Just (
ZITV a b) =>
let modn :=
Zfast_of_Nfast modn in
let itvdiv :=
ZITV (
Zfastopp (
Zfastdiv (
Zfastsub rem a)
modn))
(
Zfastdiv (
Zfastsub b rem)
modn)
in
do set <-
zitv_concretize_int max itvdiv;
ret (
fmap (
ZSetOp.map
(
fun x =>
Int.unsigned (
Int.repr (
Zfastadd (
Zfastmul x modn)
rem))))
set)
end.
Lemma concretize_int_correct :
∀
max e ρ
ab, ρ ∈ γ
ab ->
(
eval_mexpr ρ
e ∘
MNint) ⊆ γ (
concretize_int max e ab).
Proof.
Program Definition transfer_types (
v2:
abt) (
typs1 typs2:
typesmap) :
abt :=
let typs :=
Cells.ACTree.shcombine_diff (
fun _ s1 s2 =>
match s1,
s2 return _ with
|
Some (
Some s,
MNTint),
Some (
None,
MNTint) =>
Some (
Some s,
MNTint)
|
Some (
Some s,
MNTint64),
Some (
None,
MNTint64) =>
Some (
Some s,
MNTint64)
|
_,
_ =>
None
end)
_ typs1 typs2
in
Cells.ACTree.fold (
fun ab x sty =>
match sty return _ with
| (
Some s,
ty) =>
match get_itv (
MEvar ty x) (
ab,
typs2)
return _ with
| (
NotBot (
MNIint All)) |
NotBot (
MNIint64 All) =>
match idnc_assign (
Real x) (
IEZitv
(
match s,
ty return _ with
|
Signed,
MNTint =>
signed_itv
|
Unsigned,
MNTint =>
unsigned_itv
|
Signed,
MNTint64 =>
signed64_itv
|
Unsigned,
MNTint64 =>
unsigned64_itv
|
_,
_ =>
signed_itv
end))
ab
return _
with Bot =>
ab
|
NotBot ab =>
ab
end
|
_ =>
ab
end
|
_ =>
ab
end)
typs v2.
Next Obligation.
destruct v as [[[] []]|]; auto. Qed.
Lemma transfer_types_correct:
∀
typs1 typs2 v2 (ρ:
var0 ->
mach_num),
ρ ∈ γ (
v2,
typs2) ->
ρ ∈ γ (
transfer_types v2 typs1 typs2).
Proof.
Program Definition join_typs (
typs1 typs2:
typesmap) :
typesmap :=
Cells.ACTree.shcombine (
fun _ s1 s2 =>
match s1,
s2 return _ with
|
Some (
Some Signed,
MNTint),
Some (
Some Signed |
None,
MNTint)
|
Some (
Some Signed,
MNTint64),
Some (
Some Signed |
None,
MNTint64)
|
Some (
Some Unsigned,
MNTint),
Some (
Some Unsigned |
None,
MNTint)
|
Some (
Some Unsigned,
MNTint64),
Some (
Some Unsigned |
None,
MNTint64)
=>
s1
|
Some (
None,
MNTint),
Some (
Some Signed,
MNTint)
|
Some (
None,
MNTint64),
Some (
Some Signed,
MNTint64)
|
Some (
None,
MNTint),
Some (
Some Unsigned,
MNTint)
|
Some (
None,
MNTint64),
Some (
Some Unsigned,
MNTint64)
=>
s2
|
Some (
Some _,
MNTfloat),
Some (
Some _,
MNTfloat)
|
Some (
Some _,
MNTsingle),
Some (
Some _,
MNTsingle)
|
Some (
None,
MNTint),
Some (
None,
MNTint)
|
Some (
None,
MNTint64),
Some (
None,
MNTint64)
|
Some (
None,
MNTfloat),
Some (
None,
MNTfloat)
|
Some (
None,
MNTsingle),
Some (
None,
MNTsingle)
=>
s1
|
_,
_ =>
None
end)
_ typs1 typs2.
Next Obligation.
destruct v as [[[[]|] []]|]; auto. Qed.
Lemma join_typs_correct:
∀
a b, γ
a ∪ γ
b ⊆ γ (
join_typs a b).
Proof.
Instance top_ietme :
top_op ((
abt *
typesmap)+⊥) :=
do t <-
top;
ret (
t,
Cells.ACTree.empty _).
Program Instance leb_ietme :
leb_op (
abt *
typesmap) :=
fun ab1 ab2 =>
(
fst ab1) ⊑ (
fst ab2) &&
Cells.ACTree.shforall2 (
fun _ s1 s2 =>
match s1,
s2 return _ with
|
_,
None
|
Some (
_,
MNTint),
Some (
_,
MNTint)
|
Some (
_,
MNTint64),
Some (
_,
MNTint64)
|
Some (
_,
MNTsingle),
Some (
None,
MNTsingle)
|
Some (
_,
MNTfloat),
Some (
None,
MNTfloat)
|
Some (
Some _,
MNTsingle),
Some (
Some _,
MNTsingle)
|
Some (
Some _,
MNTfloat),
Some (
Some _,
MNTfloat) =>
true
|
_,
_ =>
false
end)
_
(
snd ab1) (
snd ab2).
Next Obligation.
destruct v as [[[] []]|]; auto. Qed.
Instance join_ietme :
join_op (
abt *
typesmap) ((
abt *
typesmap)+⊥) :=
fun ab1 ab2 =>
let ab1' :=
transfer_types (
fst ab1) (
snd ab2) (
snd ab1)
in
let ab2' :=
transfer_types (
fst ab2) (
snd ab1) (
snd ab2)
in
do j <-
ab1' ⊔
ab2';
ret (
j,
join_typs (
snd ab1) (
snd ab2)).
Instance widen_ietme :
widen_op (
abt_iter *
typesmap+⊥) ((
abt *
typesmap)+⊥) :=
{|
widen ab1 ab2 :=
let '(
w1,
w2) :=
fst ab1 ▽
do (
ab2,
_) <-
ab2;
ret (
ab2)
in
let typs :=
match ab1 with
| (
_,
Bot) =>
do (
_,
typs2) <-
ab2;
ret typs2
| (
_,
NotBot typs1) =>
match ab2 with
|
Bot =>
NotBot typs1
|
NotBot (
_,
typs2) =>
NotBot (
join_typs typs1 typs2)
end
end
in
((
w1,
typs),
do w <-
w2;
do typs <-
typs;
ret (
w,
typs));
init_iter x :=
match x with
|
Bot => (
init_iter Bot,
Bot)
|
NotBot x => (
init_iter (
NotBot (
fst x)),
NotBot (
snd x))
end |}.
Instance top_ietme_correct :
top_op_correct ((
abt *
typesmap)+⊥) (
var0->
mach_num).
Proof.
Instance leb_ietme_correct :
leb_op_correct (
abt *
typesmap) (
var0->
mach_num).
Proof.
Instance join_ietme_correct :
join_op_correct (
abt *
typesmap) ((
abt *
typesmap)+⊥) (
var0->
mach_num).
Proof.
Instance widen_ietme_correct :
widen_op_correct (
abt_iter *
typesmap+⊥) ((
abt *
typesmap)+⊥) (
var0->
mach_num).
Proof.
split.
-
destruct x.
contradiction.
destruct 1.
split.
destruct H as (? & ? & ?).
eexists.
split.
apply init_iter_correct.
eauto.
auto.
auto.
-
simpl.
intros [
x typsx]
ytypsy ρ [(ρ' &
Hρ' &
Hρρ')
Htyps].
match goal with
| |-
context [?
A ▽ ?
B] =>
pose proof (
widen_incr A B ρ'
Hρ');
destruct (
A ▽
B)
end.
destruct typsx.
contradiction.
split.
split.
eexists.
split.
apply H.
auto.
+
destruct ytypsy.
apply Htyps.
destruct x1.
apply join_typs_correct.
left.
apply Htyps.
+
apply botbind_spec with ρ'. 2:
apply H.
intros.
apply botbind_spec with ρ.
intros.
split.
eexists.
split.
apply H0.
auto.
apply H1.
destruct ytypsy.
apply Htyps.
destruct x1.
apply join_typs_correct.
left.
apply Htyps.
Qed.
Instance idealenv_to_machineenv:
ab_machine_env (
var:=
var0) (
abt *
typesmap) (
abt_iter *
typesmap+⊥) :=
{
assign :=
assign
;
forget :=
forget
;
assume :=
assume
;
get_itv :=
fun e v =>
do v <-
assign_vars_to_top e v;
get_itv e v
;
concretize_int :=
concretize_int
;
noerror :=
noerror }.
Proof.
End Functor.
Instance typesmap_TS :
ToString typesmap :=
fun _ => ""%
string.
Existing Instances idealenv_to_machineenv.