Section STRENGTH_REDUCTION.
Variable bc: block_classification.
Variable ge: genv.
Hypothesis GENV: genv_match bc ge.
Variable sp: block.
Hypothesis STACK: bc sp = BCstack.
Variable ae: AE.t.
Variable rs: regset.
Variable m: mem.
Hypothesis MATCH: ematch bc rs ae.
Ltac InvApproxRegs :=
match goal with
| [ H: _ :: _ = _ :: _ |- _ ] =>
injection H; clear H; intros; InvApproxRegs
| [ H: ?v = AE.get ?r ae |- _ ] =>
generalize (MATCH r); rewrite <- H; clear H; intro; InvApproxRegs
| _ => idtac
end.
Ltac SimplVM :=
match goal with
| [ H: vmatch _ ?v (I ?n) |- _ ] =>
let E := fresh in
assert (E: v = Vint n) by (inversion H; auto);
rewrite E in *; clear H; SimplVM
| [ H: vmatch _ ?v (F ?n) |- _ ] =>
let E := fresh in
assert (E: v = Vfloat n) by (inversion H; auto);
rewrite E in *; clear H; SimplVM
| [ H: vmatch _ ?v (FS ?n) |- _ ] =>
let E := fresh in
assert (E: v = Vsingle n) by (inversion H; auto);
rewrite E in *; clear H; SimplVM
| [ H: vmatch _ ?v (Ptr(Gl ?id ?ofs)) |- _ ] =>
let E := fresh in
assert (E: Val.lessdef v (Genv.symbol_address ge id ofs)) by (eapply vmatch_ptr_gl; eauto);
clear H; SimplVM
| [ H: vmatch _ ?v (Ptr(Stk ?ofs)) |- _ ] =>
let E := fresh in
assert (E: Val.lessdef v (Vptr sp ofs)) by (eapply vmatch_ptr_stk; eauto);
clear H; SimplVM
| _ => idtac
end.

Lemma op_strength_reduction_correct:
forall op args vl v,
vl = map (fun r => AE.get r ae) args ->
eval_operation ge (Vptr sp Ptrofs.zero) op rs##args m = Some v ->
let (op', args') := op_strength_reduction op args vl in
exists w, eval_operation ge (Vptr sp Ptrofs.zero) op' rs##args' m = Some w /\ Val.lessdef v w.