--- /dev/null
+(* L3 compiler
+ * peephole optimizer
+ * optimizes away redundant insns such as:
+ mov a, b
+ mov a, b
+
+ mov a, b
+ mov b, a
+
+ mov a, a
+
+ neg a
+ neg a
+ * Author: Chris Lu <czl@andrew.cmu.edu>
+ *)
+
+structure Peephole :> OPTIMIZATION =
+struct
+ structure X = x86
+
+ (* val peephole : x86.insn list -> x86.insn list *)
+ fun peephole ((insn1 as X.MOV(d1, s1 as (X.REL a,_)))::(insn2 as X.MOV(d2, s2 as (X.REL(a2,b2,m),_)))::l) =
+ if(X.opereq(a2,d1) orelse X.opereq(b2,d1)) then
+ insn1::(peephole (insn2::l))
+ else if(X.opereq(s1,s2) andalso X.opereq (d1,d2)) then
+ peephole (insn2::l)
+ else
+ insn1::(peephole (insn2::l))
+ | peephole ((insn1 as X.MOV(a1,b1))::(insn2 as X.MOV(a2,b2))::l) =
+ if(X.opereq(a1, b1) orelse (X.opereq(a1, a2) andalso X.opereq(b1, b2))) then
+ peephole (insn2::l)
+ else if(X.opereq(a2, b2) orelse (X.opereq(a1, b2) andalso X.opereq(b1, a2))) then
+ peephole (insn1::l)
+ else
+ insn1::(peephole (insn2::l))
+ | peephole (X.MOV (a as (X.REG r,s), (X.CONST 0w0,_))::l) = (X.XOR (a, a))::(peephole l)
+ | peephole ((insn as X.MOV(a,b))::l) = if X.opereq(a, b) then peephole l else insn::(peephole l)
+ | peephole ((insn1 as X.NEG(a))::(insn2 as X.NEG(b))::l) = if X.opereq(a, b) then peephole l else insn1::(peephole (insn2::l))
+ | peephole (X.ADD (_, (X.CONST 0w0,_))::l) = peephole l
+ | peephole (X.SUB (_, (X.CONST 0w0,_))::l) = peephole l
+(* | peephole (X.CMP ((X.REG r,s), (X.CONST 0w0,_))::l) = (X.TEST ((X.REG r,s), (X.REG r,s)))::(peephole l) *)
+ | peephole ((X.JMP a)::(X.JMP b)::l) = peephole ((X.JMP a)::l) (* What the cock? Yes, we actually generate this. *)
+ | peephole ((X.JMP l1)::(X.LABEL l2)::l) = if (Label.compare (l1,l2) = EQUAL) then (X.LABEL l2)::(peephole l) else (X.JMP l1)::(X.LABEL l2)::(peephole l)
+ | peephole (a::l) = a::(peephole l)
+ | peephole nil = nil
+
+ val optimizer = { shortname = "peephole", description = "Peephole analysis", func = Optimizer.FINAL peephole }
+end