Hint Resolve tail_nolabel_refl: labels.
Ltac TailNoLabel :=
eauto with labels;
match goal with
| [ |- tail_nolabel _ (_ :: _) ] => apply tail_nolabel_cons; [auto; exact I | TailNoLabel]
| [ H: Error _ = OK _ |- _ ] => discriminate
| [ H: assertion_failed = OK _ |- _ ] => discriminate
| [ H: OK _ = OK _ |- _ ] => inv H; TailNoLabel
| [ H: bind _ _ = OK _ |- _ ] => monadInv H;  TailNoLabel
| [ H: (if ?x then _ else _) = OK _ |- _ ] => destruct x; TailNoLabel
| [ H: match ?x with nil => _ | _ :: _ => _ end = OK _ |- _ ] => destruct x; TailNoLabel
| _ => idtac
end.
Remark tail_nolabel_find_label:
forall lbl k c, tail_nolabel k c -> find_label lbl c = find_label lbl k.
Remark tail_nolabel_is_tail:
forall k c, tail_nolabel k c -> is_tail k c.
(** * Execution of straight-line code *)
Section STRAIGHTLINE.
Variable ge: genv.
Variable fn: function.
(** Straight-line code is composed of processor instructions that execute in sequence (no branches, no function calls and returns). The following inductive predicate relates the machine states before and after executing a straight-line sequence of instructions. Instructions are taken from the first list instead of being fetched from memory. *)
Inductive exec_straight: code -> regset -> mem ->
code -> regset -> mem -> Prop :=
| exec_straight_one:
forall i1 c rs1 m1 rs2 m2,
exec_instr ge fn i1 rs1 m1 = Next rs2 m2 ->
rs2#PC = Val.offset_ptr rs1#PC Ptrofs.one ->
exec_straight (i1 :: c) rs1 m1 c rs2 m2
| exec_straight_step:
forall i c rs1 m1 rs2 m2 c' rs3 m3,
exec_instr ge fn i rs1 m1 = Next rs2 m2 ->
rs2#PC = Val.offset_ptr rs1#PC Ptrofs.one ->
exec_straight c rs2 m2 c' rs3 m3 ->
exec_straight (i :: c) rs1 m1 c' rs3 m3.

Lemma exec_straight_two:
forall i1 i2 c rs1 m1 rs2 m2 rs3 m3,
exec_instr ge fn i1 rs1 m1 = Next rs2 m2 ->
exec_instr ge fn i2 rs2 m2 = Next rs3 m3 ->
rs2#PC = Val.offset_ptr rs1#PC Ptrofs.one ->
rs3#PC = Val.offset_ptr rs2#PC Ptrofs.one ->
exec_straight (i1 :: i2 :: c) rs1 m1 c rs3 m3.