Skip to content

Commit 1cb65d9

Browse files
vouillonhhugo
authored andcommitted
Make the code to recognize the implementation of the (^) operator more robust
1 parent e6ad732 commit 1cb65d9

File tree

1 file changed

+86
-63
lines changed

1 file changed

+86
-63
lines changed

compiler/lib/specialize_js.ml

Lines changed: 86 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -157,75 +157,95 @@ let specialize_instr ~target info i =
157157
| _ -> i)
158158
| _, _ -> i
159159

160-
let equal2 a b = Code.Var.equal a b
160+
let skip_event cont ((Event _, _) :: l | l) = cont l
161161

162-
let equal3 a b c = Code.Var.equal a b && Code.Var.equal b c
162+
let recognize_string_length cont =
163+
skip_event
164+
@@ fun l ->
165+
match l with
166+
| ((Let (len, Prim (Extern "caml_ml_string_length", [ Pv str ])), _) as i) :: l ->
167+
cont i ~len ~str l
168+
| _ -> None
163169

164-
let equal4 a b c d = Code.Var.equal a b && Code.Var.equal b c && Code.Var.equal c d
170+
let recognize_int_add ~x ~y cont =
171+
skip_event
172+
@@ fun l ->
173+
match l with
174+
| ((Let (res, Prim (Extern "%int_add", [ Pv x'; Pv y' ])), _) as i) :: l
175+
when Code.Var.equal x x' && Code.Var.equal y y' -> cont i ~res l
176+
| _ -> None
177+
178+
let recognize_create_bytes ~len cont =
179+
skip_event
180+
@@ fun l ->
181+
match l with
182+
| (Let (bytes, Prim (Extern "caml_create_bytes", [ Pv len' ])), _) :: l
183+
when Code.Var.equal len len' -> cont ~bytes l
184+
| _ -> None
185+
186+
let recognize_blit_string ~str ~bytes ~ofs ~len cont =
187+
skip_event
188+
@@ fun l ->
189+
match l with
190+
| ( Let
191+
( _
192+
, Prim
193+
( Extern "caml_blit_string"
194+
, [ Pv str'; Pc (Int zero); Pv bytes'; ofs'; Pv len' ] ) )
195+
, _ )
196+
:: l
197+
when Code.Var.equal str str'
198+
&& Targetint.is_zero zero
199+
&& Code.Var.equal bytes bytes'
200+
&& Code.Var.equal len len'
201+
&&
202+
match ofs, ofs' with
203+
| Pc (Int ofs), Pc (Int ofs') -> Targetint.equal ofs ofs'
204+
| Pv ofs, Pv ofs' -> Code.Var.equal ofs ofs'
205+
| _ -> false -> cont l
206+
| _ -> None
207+
208+
let recognize_string_of_bytes ~bytes cont =
209+
skip_event
210+
@@ fun l ->
211+
match l with
212+
| (Let (str, Prim (Extern "caml_string_of_bytes", [ Pv bytes' ])), _) :: l
213+
when Code.Var.equal bytes bytes' -> cont ~str l
214+
| _ -> None
215+
216+
let recognize_empty_body cont =
217+
skip_event @@ fun l -> if List.is_empty l then cont () else None
218+
219+
let specialize_string_concat l =
220+
Option.value
221+
~default:l
222+
(l
223+
|> recognize_string_length
224+
@@ fun len1 ~len:alen ~str:a ->
225+
recognize_string_length
226+
@@ fun len2 ~len:blen ~str:b ->
227+
recognize_int_add ~x:alen ~y:blen
228+
@@ fun len3 ~res:len ->
229+
recognize_create_bytes ~len
230+
@@ fun ~bytes ->
231+
recognize_blit_string ~str:a ~bytes ~ofs:(Pc (Int Targetint.zero)) ~len:alen
232+
@@ recognize_blit_string ~str:b ~bytes ~ofs:(Pv alen) ~len:blen
233+
@@ recognize_string_of_bytes ~bytes
234+
@@ fun ~str ->
235+
recognize_empty_body
236+
@@ fun () ->
237+
Some
238+
[ len1
239+
; len2
240+
; len3
241+
; Let (str, Prim (Extern "caml_string_concat", [ Pv a; Pv b ])), No
242+
; Let (bytes, Prim (Extern "caml_bytes_of_string", [ Pv str ])), No
243+
])
165244

166245
let specialize_instrs ~target info l =
167246
let rec aux info checks l acc =
168247
match l with
169248
| [] -> List.rev acc
170-
| [ ((Let (alen, Prim (Extern "caml_ml_string_length", [ Pv a ])), _) as len1)
171-
; ((Let (blen, Prim (Extern "caml_ml_string_length", [ Pv b ])), _) as len2)
172-
; ((Let (len, Prim (Extern "%int_add", [ Pv alen'; Pv blen' ])), _) as len3)
173-
; (Let (bytes, Prim (Extern "caml_create_bytes", [ Pv len' ])), _)
174-
; ( Let
175-
( u1
176-
, Prim
177-
( Extern "caml_blit_string"
178-
, [ Pv a'; Pc (Int zero1); Pv bytes'; Pc (Int zero2); Pv alen'' ] ) )
179-
, _ )
180-
; ( Let
181-
( u2
182-
, Prim
183-
( Extern "caml_blit_string"
184-
, [ Pv b'; Pc (Int zero3); Pv bytes''; Pv alen'''; Pv blen'' ] ) )
185-
, _ )
186-
; (Let (res, Prim (Extern "caml_string_of_bytes", [ Pv bytes''' ])), _)
187-
]
188-
| [ (Event _, _)
189-
; ((Let (alen, Prim (Extern "caml_ml_string_length", [ Pv a ])), _) as len1)
190-
; ((Let (blen, Prim (Extern "caml_ml_string_length", [ Pv b ])), _) as len2)
191-
; (Event _, _)
192-
; ((Let (len, Prim (Extern "%int_add", [ Pv alen'; Pv blen' ])), _) as len3)
193-
; (Event _, _)
194-
; (Let (bytes, Prim (Extern "caml_create_bytes", [ Pv len' ])), _)
195-
; (Event _, _)
196-
; ( Let
197-
( u1
198-
, Prim
199-
( Extern "caml_blit_string"
200-
, [ Pv a'; Pc (Int zero1); Pv bytes'; Pc (Int zero2); Pv alen'' ] ) )
201-
, _ )
202-
; (Event _, _)
203-
; ( Let
204-
( u2
205-
, Prim
206-
( Extern "caml_blit_string"
207-
, [ Pv b'; Pc (Int zero3); Pv bytes''; Pv alen'''; Pv blen'' ] ) )
208-
, _ )
209-
; (Event _, _)
210-
; (Let (res, Prim (Extern "caml_string_of_bytes", [ Pv bytes''' ])), _)
211-
]
212-
when Targetint.is_zero zero1
213-
&& Targetint.is_zero zero2
214-
&& Targetint.is_zero zero3
215-
&& equal2 a a'
216-
&& equal2 b b'
217-
&& equal2 len len'
218-
&& equal4 alen alen' alen'' alen'''
219-
&& equal3 blen blen' blen''
220-
&& equal4 bytes bytes' bytes'' bytes''' ->
221-
[ len1
222-
; len2
223-
; len3
224-
; Let (u1, Constant (Int Targetint.zero)), No
225-
; Let (u2, Constant (Int Targetint.zero)), No
226-
; Let (res, Prim (Extern "caml_string_concat", [ Pv a; Pv b ])), No
227-
; Let (bytes, Prim (Extern "caml_bytes_of_string", [ Pv res ])), No
228-
]
229249
| (i, loc) :: r -> (
230250
(* We make bound checking explicit. Then, we can remove duplicated
231251
bound checks. Also, it appears to be more efficient to inline
@@ -327,7 +347,10 @@ let specialize_instrs ~target info l =
327347
let specialize_all_instrs ~target info p =
328348
let blocks =
329349
Addr.Map.map
330-
(fun block -> { block with Code.body = specialize_instrs ~target info block.body })
350+
(fun block ->
351+
{ block with
352+
Code.body = specialize_instrs ~target info (specialize_string_concat block.body)
353+
})
331354
p.blocks
332355
in
333356
{ p with blocks }

0 commit comments

Comments
 (0)