Correctness of instruction selection for integer division
Require Import Zquot Coqlib.
Require Import AST Integers Floats Values Memory Globalenvs Events.
Require Import Cminor Op CminorSel.
Require Import SelectOp SelectOpproof SplitLong SplitLongproof SelectLong SelectLongproof SelectDiv.
Require Import Blockset Footprint Op_fp CUAST helpers Cminor_local CminorSel_local
selectop_proof splitlong_proof selectlong_proof SelectDivproof.
Local Open Scope cminorsel_scope.
Correctness of the smart constructors for division and modulus
Section CMCONSTRS.
Variable cu:
cminorsel_comp_unit.
Variable hf:
helper_functions.
Hypothesis HELPERS:
helper_functions_declared cu hf.
Variable ge:
genv.
Hypothesis GEINIT:
globalenv_generic cu ge.
Variable sp:
val.
Variable e:
env.
Variable m:
mem.
Lemma subset_emp_emp:
forall fp,
FP.subset fp FP.emp ->
fp =
FP.emp.
Proof.
clear.
intros;
destruct fp;
unfold FP.emp;
inv H;
simpl in *;
f_equal;
do 2 (
apply Axioms.functional_extensionality;
intros);
match goal with
[
H:
context[?
x] |- ?
x _ _ =
Locs.emp _ _ ] =>
destruct x eqn:
A;
auto ;
apply H in A;
discriminate
end.
Qed.
Lemma eval_divu_mul_fp:
forall le x y p M,
divu_mul_params (
Int.unsigned y) =
Some(
p,
M) ->
nth_error le O =
Some (
Vint x) ->
eval_expr_fp ge sp e m le (
divu_mul p M)
FP.emp.
Proof.
Theorem eval_divuimm_fp:
forall le e1 x fpx n2 z,
eval_expr ge sp e m le e1 x ->
eval_expr_fp ge sp e m le e1 fpx ->
Val.divu x (
Vint n2) =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
divuimm e1 n2)
fp /\
FP.subset fp fpx.
Proof.
Theorem eval_divu_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.divu x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
divu a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Lemma eval_mod_from_div_fp:
forall le a n x y fpy,
eval_expr ge sp e m le a (
Vint y) ->
eval_expr_fp ge sp e m le a fpy ->
nth_error le O =
Some (
Vint x) ->
exists fp,
eval_expr_fp ge sp e m le (
mod_from_div a n)
fp /\
FP.subset fp fpy.
Proof.
unfold mod_from_div;
intros.
exploit eval_mulimm;
eauto.
instantiate (1 :=
n).
intros [
v [
A B]].
exploit eval_mulimm_fp;
try exact H;
eauto.
instantiate (1 :=
n).
intros [
fp' [
A'
B']].
Triv.
Qed.
Theorem eval_moduimm_fp:
forall le e1 x fpx n2 z,
eval_expr ge sp e m le e1 x ->
eval_expr_fp ge sp e m le e1 fpx ->
Val.modu x (
Vint n2) =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
moduimm e1 n2)
fp /\
FP.subset fp fpx.
Proof.
Theorem eval_modu_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.modu x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
modu a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
unfold modu;
intros until b.
destruct (
modu_match b);
intros.
InvEvalFP;
InvEval;
eqexpr.
exploit eval_moduimm;
try exacteval H;
eauto.
intros [
v [
A B]].
evalge A;
eauto with gegen.
exploit eval_moduimm_fp.
exact H.
eauto.
eauto.
intros [
fp [
A'
B']].
Triv.
eapply eval_modu_base_fp;
eauto.
Qed.
Lemma eval_divs_mul_fp:
forall le x y p M,
divs_mul_params (
Int.signed y) =
Some(
p,
M) ->
nth_error le O =
Some (
Vint x) ->
eval_expr_fp ge sp e m le (
divs_mul p M)
FP.emp.
Proof.
Theorem eval_divsimm_fp:
forall le e1 x fpx n2 z,
eval_expr ge sp e m le e1 x ->
eval_expr_fp ge sp e m le e1 fpx ->
Val.divs x (
Vint n2) =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
divsimm e1 n2)
fp /\
FP.subset fp fpx.
Proof.
Theorem eval_divs_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.divs x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
divs a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Theorem eval_modsimm_fp:
forall le e1 x fpx n2 z,
eval_expr ge sp e m le e1 x ->
eval_expr_fp ge sp e m le e1 fpx ->
Val.mods x (
Vint n2) =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
modsimm e1 n2)
fp /\
FP.subset fp fpx.
Proof.
Theorem eval_mods_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.mods x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
mods a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Lemma eval_modl_from_divl_fp:
forall le a n x y fpy,
eval_expr ge sp e m le a (
Vlong y) ->
eval_expr_fp ge sp e m le a fpy ->
nth_error le O =
Some (
Vlong x) ->
exists fp,
eval_expr_fp ge sp e m le (
modl_from_divl a n)
fp /\
FP.subset fp fpy.
Proof.
unfold modl_from_divl;
intros.
exploit eval_mullimm. 2:
exacteval H.
eauto.
instantiate (1 :=
n).
intros (
v1 &
A1 &
B1).
evalge A1;
eauto with gegen.
exploit eval_mullimm_fp;
try exact H;
eauto.
intros [
fp1 [
A1'
B1']].
assert (
A0:
eval_expr ge sp e m le (
Eletvar O) (
Vlong x))
by (
constructor;
auto).
exploit eval_subl;
auto.
exacteval A0.
exacteval A1.
intros (
v2 &
A2 &
B2).
evalge A2;
eauto with gegen.
exploit eval_subl_fp.
exact A0.
econstructor;
eauto.
exact A1.
eauto.
eauto.
TrivFP.
intros [
fp [
Y Z]].
eexists;
split;
eauto.
apply subset_trans with fp1;
auto.
Qed.
Lemma eval_divlu_mull_fp:
forall le x y p M,
divlu_mul_params (
Int64.unsigned y) =
Some(
p,
M) ->
nth_error le O =
Some (
Vlong x) ->
eval_expr_fp ge sp e m le (
divlu_mull p M)
FP.emp.
Proof.
Theorem eval_divlu_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.divlu x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
divlu a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Theorem eval_modlu_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.modlu x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
modlu a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Lemma eval_divls_mull_fp:
forall le x y p M,
divls_mul_params (
Int64.signed y) =
Some(
p,
M) ->
nth_error le O =
Some (
Vlong x) ->
eval_expr_fp ge sp e m le (
divls_mull p M)
FP.emp.
Proof.
Theorem eval_divls_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.divls x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
divls a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Theorem eval_modls_fp:
forall le a b x fpx y fpy z,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
Val.modls x y =
Some z ->
exists fp,
eval_expr_fp ge sp e m le (
modls a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
Floating-point division
Theorem eval_divf_fp:
forall le a b x fpx y fpy,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
exists fp,
eval_expr_fp ge sp e m le (
divf a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
intros until y.
unfold divf.
destruct (
divf_match b);
intros.
-
unfold divfimm.
destruct (
Float.exact_inverse n2)
as [
n2' | ]
eqn:
EINV.
+
InvEvalFP;
InvEval;
eqexpr;
InvEmpFP;
Triv.
+
Triv.
-
Triv.
Qed.
Theorem eval_divfs_fp:
forall le a b x fpx y fpy,
eval_expr ge sp e m le a x ->
eval_expr_fp ge sp e m le a fpx ->
eval_expr ge sp e m le b y ->
eval_expr_fp ge sp e m le b fpy ->
exists fp,
eval_expr_fp ge sp e m le (
divfs a b)
fp /\
FP.subset fp (
FP.union fpx fpy).
Proof.
End CMCONSTRS.