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.