File: x86Peephole.peep

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (141 lines) | stat: -rw-r--r-- 5,239 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
(* 
 * Note, this file contains conditional pattern matching rules.
 * You'll have to run it thru the tool wheregen 
 * (source for this is in the directory Tools/WhereGen) 
 * to generate the output.
 * 
 * -- Allen
 *)

local
 

   structure I =  
   struct
     include "x86Instr.sml" (* import instruction definitions *)
   end

in

functor X86Peephole
   (structure Instr : X86INSTR
    structure Eval  : MLTREE_EVAL
      (* sharing Instr.T = Eval.T *)
      where type T.Basis.cond = Instr.T.Basis.cond
        and type T.Basis.div_rounding_mode = Instr.T.Basis.div_rounding_mode
        and type T.Basis.ext = Instr.T.Basis.ext
        and type T.Basis.fcond = Instr.T.Basis.fcond
        and type T.Basis.rounding_mode = Instr.T.Basis.rounding_mode
        and type T.Constant.const = Instr.T.Constant.const
        and type ('s,'r,'f,'c) T.Extension.ccx = ('s,'r,'f,'c) Instr.T.Extension.ccx
        and type ('s,'r,'f,'c) T.Extension.fx = ('s,'r,'f,'c) Instr.T.Extension.fx
        and type ('s,'r,'f,'c) T.Extension.rx = ('s,'r,'f,'c) Instr.T.Extension.rx
        and type ('s,'r,'f,'c) T.Extension.sx = ('s,'r,'f,'c) Instr.T.Extension.sx
        and type T.I.div_rounding_mode = Instr.T.I.div_rounding_mode
        and type T.Region.region = Instr.T.Region.region
        and type T.ccexp = Instr.T.ccexp
        and type T.fexp = Instr.T.fexp
        (* and type T.labexp = Instr.T.labexp *)
        and type T.mlrisc = Instr.T.mlrisc
        and type T.oper = Instr.T.oper
        and type T.rep = Instr.T.rep
        and type T.rexp = Instr.T.rexp
        and type T.stm = Instr.T.stm
   ) : PEEPHOLE =
struct
   structure I = Instr
   structure C = I.C
   structure CBase = CellsBasis

   (* IMPORTANT: instructions are given in forward order *)
   fun peephole instrs =
   let fun isStackPtr(I.Direct r) = CBase.sameColor(r, C.esp)
         | isStackPtr _ = false

       fun isZeroLE le = (Eval.valueOf le = 0) handle _ => false

       fun isZero(I.Immed n) = n = 0
         | isZero(I.ImmedLabel le) = isZeroLE le
         | isZero _ = false

       fun isZeroOpt NONE = true
         | isZeroOpt (SOME opn) = isZero opn

       fun loop(code, instrs) = 
           (case code of
             [] => instrs

              (* x <- x +/- 0; 
               *)
           | I.INSTR(I.BINARY{binOp=(I.ADDL | I.SUBL),
                              src=I.ImmedLabel le, ...})::rest 
               where isZeroLE le => loop(rest, instrs)

              (* remove lea 0(r), r *)
           | I.INSTR(I.LEA{r32, 
                        addr=I.Displace{base, disp=I.ImmedLabel le,...}})::rest
                where (isZeroLE le) andalso 
                      CBase.sameColor(r32,base) => loop(rest, instrs)

             (*   addl n, %esp; subl m, %esp
              * => addl (n-m), %esp     ;; when m < n
              * => -                    ;; when m = n
              * => subl (m-n), %esp     ;; when m > n
              *)
           | I.INSTR(I.BINARY{binOp=I.ADDL, src=I.Immed n, dst=I.Direct d_i})::
             I.INSTR(I.BINARY{binOp=I.SUBL, src=I.Immed m, dst=I.Direct d_j})::
             rest
                where CBase.sameColor(d_i, C.esp) andalso
                      CBase.sameColor(d_j, C.esp) =>
                  if (m = n) then loop (rest, instrs)
                  else if (m < n) then 
                    loop(rest,
                         I.binary{binOp=I.ADDL, src=I.Immed(n-m), 
                                  dst=I.Direct(C.esp)}::instrs)
                  else 
                    loop(rest,
                         I.binary{binOp=I.SUBL, src=I.Immed(m-n), 
                                  dst=I.Direct(C.esp)}::instrs)

             (* push folding:
              *   subl 4, %esp
              *   movl src, 0(%esp)  (where src <> %esp !!! )
              * => 
              *   pushl src
              *)
           | I.INSTR(I.BINARY{binOp=I.SUBL,src=I.Immed 4,dst=I.Direct dst_i}):: 
             I.INSTR(I.MOVE{mvOp=I.MOVL,src,
                            dst=I.Displace{base,disp=I.Immed 0,...}})
             ::rest 
               where CBase.sameColor(base, C.esp) andalso
                     CBase.sameColor(dst_i, C.esp) andalso
                     not(isStackPtr src) =>
               loop(rest, I.pushl src::instrs)
               
             (* pop folding: 
              *   movl 0(%esp), dst   (where dst <> %esp!!!!)
              *   addl 4, %esp
              * => 
              *   popl dst
              *)
           | I.INSTR(I.MOVE{mvOp=I.MOVL, 
                            src=I.Displace{base, disp=I.Immed 0, ...}, dst})::
             I.INSTR(I.BINARY{binOp=I.ADDL, src=I.Immed 4, 
                              dst=I.Direct dst_i}):: 
             rest 
               where CBase.sameColor(base, C.esp) andalso
                     CBase.sameColor(dst_i,C.esp) andalso
                     not(isStackPtr dst) =>
               loop(rest, I.pop dst::instrs)

           | I.INSTR(I.MOVE{mvOp=I.MOVL, src, dst as I.Direct _})::rest 
              where isZero src => 
                loop(rest, I.binary{binOp=I.XORL, src=dst, dst=dst}::instrs)

           | i::rest => loop(rest, i::instrs)
           )
   in  loop(instrs, [])
   end
end 

end