aboutsummaryrefslogtreecommitdiffstats
path: root/aarch64/Peephole.v
diff options
context:
space:
mode:
Diffstat (limited to 'aarch64/Peephole.v')
-rw-r--r--aarch64/Peephole.v167
1 files changed, 167 insertions, 0 deletions
diff --git a/aarch64/Peephole.v b/aarch64/Peephole.v
new file mode 100644
index 00000000..2282326a
--- /dev/null
+++ b/aarch64/Peephole.v
@@ -0,0 +1,167 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+Require Import Coqlib.
+Require Import Asmblock.
+Require Import Values.
+Require Import Integers.
+Require Import AST.
+Require Compopts.
+
+(*Fixpoint gpreg_q_search_rec r0 r1 l :=
+ match l with
+ | h :: t =>
+ let (s0, s1) := gpreg_q_expand h in
+ if (gpreg_eq r0 s0) && (gpreg_eq r1 s1)
+ then Some h
+ else gpreg_q_search_rec r0 r1 t
+ | nil => None
+ end.
+
+Fixpoint gpreg_o_search_rec r0 r1 r2 r3 l :=
+ match l with
+ | h :: t =>
+ match gpreg_o_expand h with
+ | (((s0, s1), s2), s3) =>
+ if (gpreg_eq r0 s0) && (gpreg_eq r1 s1) &&
+ (gpreg_eq r2 s2) && (gpreg_eq r3 s3)
+ then Some h
+ else gpreg_o_search_rec r0 r1 r2 r3 t
+ end
+ | nil => None
+ end.
+
+Definition gpreg_q_search (r0 : gpreg) (r1 : gpreg) : option gpreg_q :=
+ gpreg_q_search_rec r0 r1 gpreg_q_list.
+
+Definition gpreg_o_search r0 r1 r2 r3 : option gpreg_o :=
+ gpreg_o_search_rec r0 r1 r2 r3 gpreg_o_list.
+
+Parameter print_found_store: forall A, Z -> A -> A.
+
+ Definition coalesce_octuples := true.*)
+
+Definition is_valid_immofs_32 (z: Z) : bool :=
+ if (zle z 252) && (zle (-256) z) && ((Z.modulo z 4) =? 0) then true else false.
+
+Definition is_valid_immofs_64 (z: Z) : bool :=
+ if (zle z 504) && (zle (-512) z) && ((Z.modulo z 8) =? 0) then true else false.
+
+Fixpoint ldp_rep (insns : list basic) : list basic :=
+ match insns with
+ | nil => nil
+ | h0 :: t0 =>
+ match t0 with
+ | h1 :: t1 =>
+ match h0, h1 with
+ | (PLd_rd_a Pldrw (IR (RR1 rd1)) (ADimm b1 n1)),
+ (PLd_rd_a Pldrw (IR (RR1 rd2)) (ADimm b2 n2)) =>
+ let z1 := Int64.signed n1 in
+ let z2 := Int64.signed n2 in
+
+ (* TODO This could be insteresting to add if compatible with the checker
+ When both load the same dest, and with no reuse of ld1 in ld2. *)
+ (* if (ireg_eq rd1 rd2) && (negb (iregsp_eq b2 (RR1 rd1))) then
+ Pnop :: (ldp_rep t0)
+ (* When two consec mem addr are loading two different dest. *)
+ else*)
+
+ if (negb (ireg_eq rd1 rd2)) && (iregsp_eq b1 b2) && (negb (iregsp_eq (RR1 rd1) b1))
+ && (z2 =? z1 + 4) && (is_valid_immofs_32 z1) then
+ (PLoad (Pldp Pldpw rd1 rd2 (ADimm b1 n1))) :: Pnop :: (ldp_rep t1)
+ (* When nothing can be optimized. *)
+ else
+ h0 :: (ldp_rep t0)
+ | (PLd_rd_a Pldrx (IR (RR1 rd1)) (ADimm b1 n1)),
+ (PLd_rd_a Pldrx (IR (RR1 rd2)) (ADimm b2 n2)) =>
+ let z1 := Int64.signed n1 in
+ let z2 := Int64.signed n2 in
+
+ (*if (ireg_eq rd1 rd2) && (negb (iregsp_eq b2 (RR1 rd1))) then
+ Pnop :: (ldp_rep t0)
+ else*)
+
+ if (negb (ireg_eq rd1 rd2)) && (iregsp_eq b1 b2) && (negb (iregsp_eq (RR1 rd1) b1))
+ && (z2 =? z1 + 8) && (is_valid_immofs_64 z1) then
+ (PLoad (Pldp Pldpx rd1 rd2 (ADimm b1 n1))) :: Pnop :: (ldp_rep t1)
+ else
+ h0 :: (ldp_rep t0)
+ (*| (PLd_rd_a Pldrw rd1 (ADimm b1 n1)), h1 => ldpw_follow rd1 b1 n1*)
+ (*| (PLd_rd_a Pldrx rd1 (ADimm b1 n1)), h1 => ldpx_follow rd1 b1 n1*)
+ | _, _ => h0 :: (ldp_rep t0)
+ end
+ | nil => h0 :: nil
+ end
+ end.
+
+Fixpoint stp_rep (insns : list basic) : list basic :=
+ match insns with
+ | nil => nil
+ | h0 :: t0 =>
+ match t0 with
+ | h1 :: t1 =>
+ match h0, h1 with
+ | (PSt_rs_a Pstrw (IR (RR1 rs1)) (ADimm b1 n1)),
+ (PSt_rs_a Pstrw (IR (RR1 rs2)) (ADimm b2 n2)) =>
+ let z1 := Int64.signed n1 in
+ let z2 := Int64.signed n2 in
+
+ (* When both store at the same addr, same ofs. *)
+ (*if (iregsp_eq b1 b2) && (z2 =? z1) then
+ Pnop :: (stp_rep t0)
+ (* When two consec mem addr are targeted by two store. *)
+ else*)
+
+ if (iregsp_eq b1 b2) && (z2 =? z1 + 4) && (is_valid_immofs_32 z1) then
+ (PStore (Pstp Pstpw rs1 rs2 (ADimm b1 n1))) :: Pnop :: (stp_rep t1)
+ (* When nothing can be optimized. *)
+ else
+ h0 :: (stp_rep t0)
+ | (PSt_rs_a Pstrx (IR (RR1 rs1)) (ADimm b1 n1)),
+ (PSt_rs_a Pstrx (IR (RR1 rs2)) (ADimm b2 n2)) =>
+ let z1 := Int64.signed n1 in
+ let z2 := Int64.signed n2 in
+
+ (*if (iregsp_eq b1 b2) && (z2 =? z1) then
+ Pnop :: (stp_rep t0)
+ else*)
+
+ if (iregsp_eq b1 b2) && (z2 =? z1 + 8) && (is_valid_immofs_64 z1) then
+ (PStore (Pstp Pstpx rs1 rs2 (ADimm b1 n1))) :: Pnop :: (stp_rep t1)
+ else
+ h0 :: (stp_rep t0)
+ (*| (PLd_rd_a Pldrw rd1 (ADimm b1 n1)), h1 => ldpw_follow rd1 b1 n1*)
+ (*| (PLd_rd_a Pldrx rd1 (ADimm b1 n1)), h1 => ldpx_follow rd1 b1 n1*)
+ | _, _ => h0 :: (stp_rep t0)
+ end
+ | nil => h0 :: nil
+ end
+ end.
+
+Definition optimize_body (insns : list basic) :=
+ stp_rep (ldp_rep insns).
+ (* TODO ADD A FLAG TO ENABLE PEEPHOLE *)
+ (*if Compopts.optim_coalesce_mem tt*)
+ (*then ldp_rep insns*)
+ (*else insns.*)
+
+Program Definition optimize_bblock (bb : bblock) :=
+ let optimized := optimize_body (body bb) in
+ let wf_ok := non_empty_bblockb optimized (exit bb) in
+ {| header := header bb;
+ body := if wf_ok then optimized else (body bb);
+ exit := exit bb |}.
+Next Obligation.
+ destruct (non_empty_bblockb (optimize_body (body bb))) eqn:Rwf.
+ - rewrite Rwf. cbn. trivial.
+ - exact (correct bb).
+Qed.