Section SHIFT_AMOUNT.
Variable l: Z.
Hypothesis l_range: 0 <= l < 32.
Variable N: int.
Hypothesis N_eq: Int.unsigned N = two_p l.
Remark mk_amount_range:
forall n, Int.ltu (Int.zero_ext l n) N = true.
Remark mk_amount_eq:
forall n, Int.ltu n N = true -> Int.zero_ext l n = n.
End SHIFT_AMOUNT.
Program Definition mk_amount32 (n: int): amount32 :=
{| a32_amount := Int.zero_ext 5 n |}.
Next Obligation.
apply mk_amount_range. omega. reflexivity.
Qed.
Program Definition mk_amount64 (n: int): amount64 :=
{| a64_amount := Int.zero_ext 6 n |}.
Next Obligation.
apply mk_amount_range. omega. reflexivity.
Qed.
(** Recognition of move operations. *)
Definition is_move_operation
(A: Type) (op: operation) (args: list A) : option A :=
match op, args with
| Omove, arg :: nil => Some arg
| _, _ => None
end.
(** [negate_condition cond] returns a condition that is logically equivalent to the negation of [cond]. *)
Definition negate_condition (cond: condition): condition :=
match cond with
| Ccomp c => Ccomp (negate_comparison c)
| Ccompu c => Ccompu (negate_comparison c)
| Ccompimm c n => Ccompimm (negate_comparison c) n
| Ccompuimm c n => Ccompuimm (negate_comparison c) n
| Ccompshift c s a => Ccompshift (negate_comparison c) s a
| Ccompushift c s a => Ccompushift (negate_comparison c) s a
| Cmaskzero n => Cmasknotzero n
| Cmasknotzero n => Cmaskzero n
| Ccompl c => Ccompl (negate_comparison c)
| Ccomplu c => Ccomplu (negate_comparison c)
| Ccomplimm c n => Ccomplimm (negate_comparison c) n
| Ccompluimm c n => Ccompluimm (negate_comparison c) n
| Ccomplshift c s a => Ccomplshift (negate_comparison c) s a
| Ccomplushift c s a => Ccomplushift (negate_comparison c) s a
| Cmasklzero n => Cmasklnotzero n
| Cmasklnotzero n => Cmasklzero n
| Ccompf c => Cnotcompf c
| Cnotcompf c => Ccompf c
| Ccompfzero c => Cnotcompfzero c
| Cnotcompfzero c => Ccompfzero c
| Ccompfs c => Cnotcompfs c
| Cnotcompfs c => Ccompfs c
| Ccompfszero c => Cnotcompfszero c
| Cnotcompfszero c => Ccompfszero c
end.
(** Shifting stack-relative references.  This is used in [Stacking]. *)
Definition shift_stack_addressing (delta: Z) (addr: addressing) :=
match addr with
| Ainstack ofs => Ainstack (Ptrofs.add ofs (Ptrofs.repr delta))
| _ => addr
end.
Definition shift_stack_operation (delta: Z) (op: operation) :=
match op with
| Oaddrstack ofs => Oaddrstack (Ptrofs.add ofs (Ptrofs.repr delta))
| _ => op
end.
(** Offset an addressing mode [addr] by a quantity [delta], so that it designates the pointer [delta] bytes past the pointer designated by [addr].  May be undefined, in which case [None] is returned. *)
Definition offset_addressing (addr: addressing) (delta: Z) : option addressing :=
match addr with
| Aindexed n => Some(Aindexed (Int64.add n (Int64.repr delta)))
| Aindexed2 => None
| Aindexed2shift _ => None
| Aindexed2ext _ _ => None
| Aglobal id n => Some(Aglobal id (Ptrofs.add n (Ptrofs.repr delta)))
| Ainstack n => Some(Ainstack (Ptrofs.add n (Ptrofs.repr delta)))
end.
(** Operations that are so cheap to recompute that CSE should not factor them out. *)
Definition is_trivial_op (op: operation) : bool :=
match op with
| Omove => true
| Ointconst n => Int.eq (Int.sign_ext 16 n) n
| Olongconst n => Int64.eq (Int64.sign_ext 16 n) n
| Oaddrstack _ => true
| _ => false
end.
(** Operations that depend on the memory state. *)
Definition cond_depends_on_memory (c: condition) : bool :=
match c with
| Ccomplu _ | Ccompluimm _ _ | Ccomplushift _ _ _ => true
| _ => false
end.
Definition op_depends_on_memory (op: operation) : bool :=
match op with
| Ocmp c => cond_depends_on_memory c
| Osel c yu => cond_depends_on_memory c
| _ => false
end.

Lemma op_depends_on_memory_correct:
forall (F V: Type) (ge: Genv.t F V) sp op args m1 m2,
op_depends_on_memory op = false ->
eval_operation ge sp op args m1 = eval_operation ge sp op args m2.