@@ -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
166245let 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 =
327347let 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