Skip to content

Commit da0b51a

Browse files
committed
constant propogation to string/char too
1 parent 5ca767a commit da0b51a

11 files changed

+302
-55
lines changed

jscomp/bin/whole_compiler.ml

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95120,14 +95120,14 @@ let rec eliminate_ref id (lam : Lam.t) =
9512095120
Lam.prim ~primitive ~args:(List.map (eliminate_ref id) args) loc
9512195121
| Lswitch(e, sw) ->
9512295122
Lam.switch(eliminate_ref id e)
95123-
{sw_numconsts = sw.sw_numconsts;
95124-
sw_consts =
95125-
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_consts;
95126-
sw_numblocks = sw.sw_numblocks;
95127-
sw_blocks =
95128-
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_blocks;
95129-
sw_failaction =
95130-
Misc.may_map (eliminate_ref id) sw.sw_failaction; }
95123+
{sw_numconsts = sw.sw_numconsts;
95124+
sw_consts =
95125+
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_consts;
95126+
sw_numblocks = sw.sw_numblocks;
95127+
sw_blocks =
95128+
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_blocks;
95129+
sw_failaction =
95130+
Misc.may_map (eliminate_ref id) sw.sw_failaction; }
9513195131
| Lstringswitch(e, sw, default) ->
9513295132
Lam.stringswitch
9513395133
(eliminate_ref id e)
@@ -95163,7 +95163,8 @@ let rec eliminate_ref id (lam : Lam.t) =
9516395163

9516495164

9516595165
let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
95166-
let subst : Lam.t Ident_hashtbl.t = Ident_hashtbl.create 31 in
95166+
let subst : Lam.t Ident_hashtbl.t = Ident_hashtbl.create 32 in
95167+
let string_table : string Ident_hashtbl.t = Ident_hashtbl.create 32 in
9516795168
let used v = (count_var v ).times > 0 in
9516895169
let rec simplif (lam : Lam.t) =
9516995170
match lam with
@@ -95204,15 +95205,20 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
9520495205
| Const_pointer _ ) (* could be poly-variant [`A] -> [65a]*)
9520595206
| Lprim {primitive = Pfield (_);
9520695207
args = [Lprim {primitive = Pgetglobal _; _}]}
95207-
)
95208+
)
9520895209
(* Const_int64 is no longer primitive
9520995210
Note for some constant which is not
9521095211
inlined, we can still record it and
9521195212
do constant folding independently
9521295213
*)
9521395214
->
9521495215
Ident_hashtbl.add subst v (simplif l1); simplif l2
95216+
| _, Lconst (Const_base (Const_string (s,_)) ) ->
95217+
Ident_hashtbl.add string_table v s;
95218+
Lam.let_ Alias v l1 (simplif l2)
95219+
(* we need move [simplif l2] later, since adding Hashtbl does have side effect *)
9521595220
| _ -> Lam.let_ Alias v (simplif l1) (simplif l2)
95221+
(* for Alias, in most cases [l1] is already simplified *)
9521695222
end
9521795223
| Llet(StrictOpt as kind, v, l1, l2) ->
9521895224
(** can not be inlined since [l1] depend on the store
@@ -95224,7 +95230,16 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
9522495230
*)
9522595231
if not @@ used v
9522695232
then simplif l2
95227-
else Lam_util.refine_let ~kind v (simplif l1 ) (simplif l2)
95233+
else
95234+
let l1 = simplif l1 in
95235+
begin match l1 with
95236+
| Lconst(Const_base(Const_string(s,_))) ->
95237+
Ident_hashtbl.add string_table v s;
95238+
(* we need move [simplif l2] later, since adding Hashtbl does have side effect *)
95239+
Lam.let_ Alias v l1 (simplif l2)
95240+
| _ ->
95241+
Lam_util.refine_let ~kind v l1 (simplif l2)
95242+
end
9522895243
(* TODO: check if it is correct rollback to [StrictOpt]? *)
9522995244

9523095245
| Llet((Strict | Variable as kind), v, l1, l2) ->
@@ -95235,8 +95250,17 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
9523595250
if Lam_analysis.no_side_effects l1
9523695251
then l2
9523795252
else Lam.seq l1 l2
95238-
else Lam_util.refine_let ~kind v (simplif l1) (simplif l2)
95239-
95253+
else
95254+
let l1 = (simplif l1) in
95255+
95256+
begin match kind, l1 with
95257+
| Strict, Lconst(Const_base(Const_string(s,_)))
95258+
->
95259+
Ident_hashtbl.add string_table v s;
95260+
Lam.let_ Alias v l1 (simplif l2)
95261+
| _ ->
95262+
Lam_util.refine_let ~kind v l1 (simplif l2)
95263+
end
9524095264
| Lifused(v, l) ->
9524195265
if used v then
9524295266
simplif l
@@ -95251,7 +95275,7 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
9525195275
when Ext_list.same_length params args ->
9525295276
simplif (Lam_beta_reduce.beta_reduce params body args)
9525395277
| Lapply{ fn = Lfunction{kind = Tupled; params; body};
95254-
args = [Lprim {primitive = Pmakeblock _; args; _}]; _}
95278+
args = [Lprim {primitive = Pmakeblock _; args; _}]; _}
9525595279
(** TODO: keep track of this parameter in ocaml trunk,
9525695280
can we switch to the tupled backend?
9525795281
*)
@@ -95267,6 +95291,53 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
9526795291
Lam.letrec
9526895292
(List.map (fun (v, l) -> (v, simplif l)) bindings)
9526995293
(simplif body)
95294+
| Lprim {primitive=Pstringadd; args = [l;r]; loc } ->
95295+
begin
95296+
let l' = simplif l in
95297+
let r' = simplif r in
95298+
let opt_l =
95299+
match l' with
95300+
| Lconst(Const_base(Const_string(ls,_))) -> Some ls
95301+
| Lvar i -> Ident_hashtbl.find_opt string_table i
95302+
| _ -> None in
95303+
match opt_l with
95304+
| None -> Lam.prim ~primitive:Pstringadd ~args:[l';r'] loc
95305+
| Some l_s ->
95306+
let opt_r =
95307+
match r' with
95308+
| Lconst (Const_base (Const_string(rs,_))) -> Some rs
95309+
| Lvar i -> Ident_hashtbl.find_opt string_table i
95310+
| _ -> None in
95311+
begin match opt_r with
95312+
| None -> Lam.prim ~primitive:Pstringadd ~args:[l';r'] loc
95313+
| Some r_s ->
95314+
Lam.const ((Const_base(Const_string(l_s^r_s, None))))
95315+
end
95316+
end
95317+
95318+
| Lprim {primitive = (Pstringrefu|Pstringrefs) as primitive ;
95319+
args = [l;r] ; loc
95320+
} -> (* TODO: introudce new constant *)
95321+
let l' = simplif l in
95322+
let r' = simplif r in
95323+
let opt_l =
95324+
match l' with
95325+
| Lconst (Const_base(Const_string(ls,_))) ->
95326+
Some ls
95327+
| Lvar i -> Ident_hashtbl.find_opt string_table i
95328+
| _ -> None in
95329+
begin match opt_l with
95330+
| None -> Lam.prim ~primitive ~args:[l';r'] loc
95331+
| Some l_s ->
95332+
match r with
95333+
|Lconst(Const_base(Const_int i)) ->
95334+
if i < String.length l_s && i >=0 then
95335+
Lam.const (Const_base (Const_char l_s.[i]))
95336+
else
95337+
Lam.prim ~primitive ~args:[l';r'] loc
95338+
| _ ->
95339+
Lam.prim ~primitive ~args:[l';r'] loc
95340+
end
9527095341
| Lprim {primitive; args; loc}
9527195342
-> Lam.prim ~primitive ~args:(List.map simplif args) loc
9527295343
| Lswitch(l, sw) ->
@@ -95281,7 +95352,7 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
9528195352
| Lstringswitch (l,sw,d) ->
9528295353
Lam.stringswitch
9528395354
(simplif l) (List.map (fun (s,l) -> s,simplif l) sw)
95284-
(Misc.may_map simplif d)
95355+
(Misc.may_map simplif d)
9528595356
| Lstaticraise (i,ls) ->
9528695357
Lam.staticraise i (List.map simplif ls)
9528795358
| Lstaticcatch(l1, (i,args), l2) ->

jscomp/core/lam_pass_lets_dce.ml

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ let rec eliminate_ref id (lam : Lam.t) =
7171
Lam.prim ~primitive ~args:(List.map (eliminate_ref id) args) loc
7272
| Lswitch(e, sw) ->
7373
Lam.switch(eliminate_ref id e)
74-
{sw_numconsts = sw.sw_numconsts;
75-
sw_consts =
76-
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_consts;
77-
sw_numblocks = sw.sw_numblocks;
78-
sw_blocks =
79-
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_blocks;
80-
sw_failaction =
81-
Misc.may_map (eliminate_ref id) sw.sw_failaction; }
74+
{sw_numconsts = sw.sw_numconsts;
75+
sw_consts =
76+
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_consts;
77+
sw_numblocks = sw.sw_numblocks;
78+
sw_blocks =
79+
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_blocks;
80+
sw_failaction =
81+
Misc.may_map (eliminate_ref id) sw.sw_failaction; }
8282
| Lstringswitch(e, sw, default) ->
8383
Lam.stringswitch
8484
(eliminate_ref id e)
@@ -114,7 +114,8 @@ let rec eliminate_ref id (lam : Lam.t) =
114114

115115

116116
let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
117-
let subst : Lam.t Ident_hashtbl.t = Ident_hashtbl.create 31 in
117+
let subst : Lam.t Ident_hashtbl.t = Ident_hashtbl.create 32 in
118+
let string_table : string Ident_hashtbl.t = Ident_hashtbl.create 32 in
118119
let used v = (count_var v ).times > 0 in
119120
let rec simplif (lam : Lam.t) =
120121
match lam with
@@ -155,15 +156,20 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
155156
| Const_pointer _ ) (* could be poly-variant [`A] -> [65a]*)
156157
| Lprim {primitive = Pfield (_);
157158
args = [Lprim {primitive = Pgetglobal _; _}]}
158-
)
159+
)
159160
(* Const_int64 is no longer primitive
160161
Note for some constant which is not
161162
inlined, we can still record it and
162163
do constant folding independently
163164
*)
164165
->
165166
Ident_hashtbl.add subst v (simplif l1); simplif l2
167+
| _, Lconst (Const_base (Const_string (s,_)) ) ->
168+
Ident_hashtbl.add string_table v s;
169+
Lam.let_ Alias v l1 (simplif l2)
170+
(* we need move [simplif l2] later, since adding Hashtbl does have side effect *)
166171
| _ -> Lam.let_ Alias v (simplif l1) (simplif l2)
172+
(* for Alias, in most cases [l1] is already simplified *)
167173
end
168174
| Llet(StrictOpt as kind, v, l1, l2) ->
169175
(** can not be inlined since [l1] depend on the store
@@ -175,7 +181,16 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
175181
*)
176182
if not @@ used v
177183
then simplif l2
178-
else Lam_util.refine_let ~kind v (simplif l1 ) (simplif l2)
184+
else
185+
let l1 = simplif l1 in
186+
begin match l1 with
187+
| Lconst(Const_base(Const_string(s,_))) ->
188+
Ident_hashtbl.add string_table v s;
189+
(* we need move [simplif l2] later, since adding Hashtbl does have side effect *)
190+
Lam.let_ Alias v l1 (simplif l2)
191+
| _ ->
192+
Lam_util.refine_let ~kind v l1 (simplif l2)
193+
end
179194
(* TODO: check if it is correct rollback to [StrictOpt]? *)
180195

181196
| Llet((Strict | Variable as kind), v, l1, l2) ->
@@ -186,8 +201,17 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
186201
if Lam_analysis.no_side_effects l1
187202
then l2
188203
else Lam.seq l1 l2
189-
else Lam_util.refine_let ~kind v (simplif l1) (simplif l2)
190-
204+
else
205+
let l1 = (simplif l1) in
206+
207+
begin match kind, l1 with
208+
| Strict, Lconst(Const_base(Const_string(s,_)))
209+
->
210+
Ident_hashtbl.add string_table v s;
211+
Lam.let_ Alias v l1 (simplif l2)
212+
| _ ->
213+
Lam_util.refine_let ~kind v l1 (simplif l2)
214+
end
191215
| Lifused(v, l) ->
192216
if used v then
193217
simplif l
@@ -202,7 +226,7 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
202226
when Ext_list.same_length params args ->
203227
simplif (Lam_beta_reduce.beta_reduce params body args)
204228
| Lapply{ fn = Lfunction{kind = Tupled; params; body};
205-
args = [Lprim {primitive = Pmakeblock _; args; _}]; _}
229+
args = [Lprim {primitive = Pmakeblock _; args; _}]; _}
206230
(** TODO: keep track of this parameter in ocaml trunk,
207231
can we switch to the tupled backend?
208232
*)
@@ -218,6 +242,53 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
218242
Lam.letrec
219243
(List.map (fun (v, l) -> (v, simplif l)) bindings)
220244
(simplif body)
245+
| Lprim {primitive=Pstringadd; args = [l;r]; loc } ->
246+
begin
247+
let l' = simplif l in
248+
let r' = simplif r in
249+
let opt_l =
250+
match l' with
251+
| Lconst(Const_base(Const_string(ls,_))) -> Some ls
252+
| Lvar i -> Ident_hashtbl.find_opt string_table i
253+
| _ -> None in
254+
match opt_l with
255+
| None -> Lam.prim ~primitive:Pstringadd ~args:[l';r'] loc
256+
| Some l_s ->
257+
let opt_r =
258+
match r' with
259+
| Lconst (Const_base (Const_string(rs,_))) -> Some rs
260+
| Lvar i -> Ident_hashtbl.find_opt string_table i
261+
| _ -> None in
262+
begin match opt_r with
263+
| None -> Lam.prim ~primitive:Pstringadd ~args:[l';r'] loc
264+
| Some r_s ->
265+
Lam.const ((Const_base(Const_string(l_s^r_s, None))))
266+
end
267+
end
268+
269+
| Lprim {primitive = (Pstringrefu|Pstringrefs) as primitive ;
270+
args = [l;r] ; loc
271+
} -> (* TODO: introudce new constant *)
272+
let l' = simplif l in
273+
let r' = simplif r in
274+
let opt_l =
275+
match l' with
276+
| Lconst (Const_base(Const_string(ls,_))) ->
277+
Some ls
278+
| Lvar i -> Ident_hashtbl.find_opt string_table i
279+
| _ -> None in
280+
begin match opt_l with
281+
| None -> Lam.prim ~primitive ~args:[l';r'] loc
282+
| Some l_s ->
283+
match r with
284+
|Lconst(Const_base(Const_int i)) ->
285+
if i < String.length l_s && i >=0 then
286+
Lam.const (Const_base (Const_char l_s.[i]))
287+
else
288+
Lam.prim ~primitive ~args:[l';r'] loc
289+
| _ ->
290+
Lam.prim ~primitive ~args:[l';r'] loc
291+
end
221292
| Lprim {primitive; args; loc}
222293
-> Lam.prim ~primitive ~args:(List.map simplif args) loc
223294
| Lswitch(l, sw) ->
@@ -232,7 +303,7 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam =
232303
| Lstringswitch (l,sw,d) ->
233304
Lam.stringswitch
234305
(simplif l) (List.map (fun (s,l) -> s,simplif l) sw)
235-
(Misc.may_map simplif d)
306+
(Misc.may_map simplif d)
236307
| Lstaticraise (i,ls) ->
237308
Lam.staticraise i (List.map simplif ls)
238309
| Lstaticcatch(l1, (i,args), l2) ->

jscomp/test/.depend

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
a_recursive_type.cmi :
22
abstract_type.cmi : mt.cmi
3+
alias_test.cmi :
34
ari_regress_test.cmi :
45
array_test.cmi :
56
basic_module_test.cmi :
@@ -44,6 +45,7 @@ a_recursive_type.cmj : a_recursive_type.cmi
4445
a_scope_bug.cmj :
4546
a_string_test.cmj : mt.cmj ../stdlib/list.cmj ext_string.cmj
4647
abstract_type.cmj : abstract_type.cmi
48+
alias_test.cmj : ../stdlib/string.cmj alias_test.cmi
4749
and_or_tailcall_test.cmj : mt.cmj
4850
app_root_finder.cmj : ../others/node.cmj ../runtime/js.cmj
4951
ari_regress_test.cmj : mt.cmj ari_regress_test.cmi

jscomp/test/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ OTHERS := literals a test_ari test_export2 test_internalOO test_obj_simple_ffi t
7474
math_test bal_set_mini gpr_974_test test_cpp\
7575
global_module_alias_test class_fib_open_recursion_test\
7676
topsort_test flexible_array_test\
77-
gray_code_test
77+
gray_code_test alias_test
7878

7979

8080

jscomp/test/alias_test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
4+
var a10 = "hello world";
5+
6+
var v = 1;
7+
8+
var a21 = "hello worldnothello worldnot";
9+
10+
var a15 = a10;
11+
12+
var b15 = 111;
13+
14+
exports.a15 = a15;
15+
exports.b15 = b15;
16+
exports.a21 = a21;
17+
exports.v = v;
18+
/* No side effect */

0 commit comments

Comments
 (0)