Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Inductive val_casted: val -> type -> Prop :=
  | val_casted_int: forall sz si attr n,
      cast_int_int sz si n = n ->
      val_casted (Vint n) (Tint sz si attr)
  | val_casted_float: forall attr n,
       val_casted (Vfloat n) (Tfloat F64 attr)
  | val_casted_single: forall attr n,
       val_casted (Vsingle n) (Tfloat F32 attr)
  | val_casted_long: forall si attr n,
      val_casted (Vlong n) (Tlong si attr)
  | val_casted_ptr_ptr: forall b ofs ty attr,
      val_casted (Vptr b ofs) (Tpointer ty attr)
  | val_casted_int_ptr: forall n ty attr,
      Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
  | val_casted_ptr_int: forall b ofs si attr,
      Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
  | val_casted_long_ptr: forall n ty attr,
      Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
  | val_casted_ptr_long: forall b ofs si attr,
      Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
  | val_casted_struct: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tstruct id attr)
  | val_casted_union: forall id attr b ofs,
      val_casted (Vptr b ofs) (Tunion id attr)
  | val_casted_void: forall v,
      val_casted v Tvoid.Remark cast_int_int_idem:
  forall sz sg i, cast_int_int sz sg (cast_int_int sz sg i) = cast_int_int sz sg i.Ltac DestructCases :=
  match goal with
  | [H: match match ?x with _ => _ end with _ => _ end = Some _ |- _ ] => destruct x eqn:?; DestructCases
  | [H: match ?x with _ => _ end = Some _ |- _ ] => destruct x eqn:?; DestructCases
  | [H: Some _ = Some _ |- _ ] => inv H; DestructCases
  | [H: None = Some _ |- _ ] => discriminate H
  | [H: @eq intsize _ _ |- _ ] => discriminate H || (clear H; DestructCases)
  | [ |- val_casted (Vint (if ?x then Int.zero else Int.one)) _ ] =>
       try (constructor; destruct x; reflexivity)
  | [ |- val_casted (Vint _) (Tint ?sz ?sg _) ] =>
       try (constructor; apply (cast_int_int_idem sz sg))
  | _ => idtac
  end.

Lemma cast_idempotent: forall v ty ty' v' m, sem_cast v ty ty' m = Some v' -> sem_cast v' ty' ty' m = Some v'.