253
253
%% each cluster is dense.
255
255
minclusters(Cases) when is_list(Cases) ->
256
minclusters(list_to_tuple(Cases));
256
minclusters(list_to_tuple(Cases));
257
257
minclusters(Cases) when is_tuple(Cases) ->
259
MinClusters = list_to_tuple([0|n_list(N,inf)]),
260
i_loop(1,N,MinClusters,Cases).
259
MinClusters = list_to_tuple([0|n_list(N,inf)]),
260
i_loop(1,N,MinClusters,Cases).
262
262
%% Create a list with N elements initialized to Init
263
263
n_list(0,_) -> [];
264
264
n_list(N,Init) -> [Init | n_list(N-1,Init)].
268
267
%% Do the dirty work of minclusters
269
268
i_loop(I,N,MinClusters,_Cases) when I > N ->
271
270
i_loop(I,N,MinClusters,Cases) when I =< N ->
272
M = j_loop(0, I-1, MinClusters, Cases),
273
i_loop(I+1, N, M, Cases).
271
M = j_loop(0, I-1, MinClusters, Cases),
272
i_loop(I+1, N, M, Cases).
275
274
%% More dirty work
276
275
j_loop(J,I1,MinClusters,_Cases) when J > I1 ->
278
277
j_loop(J,I1,MinClusters,Cases) when J =< I1 ->
279
D = density(Cases,J+1,I1+1),
280
A0 = element(J+1,MinClusters),
287
B = element(I1+2,MinClusters),
289
D >= ?MINDENSITY, A<B ->
290
setelement(I1+2,MinClusters,A);
294
j_loop(J+1,I1,M,Cases).
278
D = density(Cases,J+1,I1+1),
279
A0 = element(J+1,MinClusters),
286
B = element(I1+2,MinClusters),
288
D >= ?MINDENSITY, A<B ->
289
setelement(I1+2,MinClusters,A);
293
j_loop(J+1,I1,M,Cases).
297
296
%% Determine the density of a (subset of a) case list
298
297
%% A is a tuple with the cases in order from smallest to largest
299
298
%% I is the index of the first element and J of the last
301
300
density(A,I,J) ->
304
(J-I+1)/(hipe_icode:const_value(AJ)-hipe_icode:const_value(AI)+1).
301
{AI,_} = element(I,A),
302
{AJ,_} = element(J,A),
303
(J-I+1)/(hipe_icode:const_value(AJ)-hipe_icode:const_value(AI)+1).
307
306
%% Split a case list into dense clusters
308
307
%% Returns a list of lists of cases.
309
%% Cases is the case list and Clust is a list describing the optimal clustering
310
%% as returned by minclusters
312
%% If the value in the last place in minclusters is M then we can split the case
313
%% list into M clusters. We then search for the last (== right-most) occurance of
314
%% the value M-1 in minclusters. That indicates the largest number of cases that
315
%% can be split into M-1 clusters. This means that the cases in between constitute
316
%% one cluster. Then we recurse on the remainder of the cases.
318
%% The various calls to lists:reverse are just to ensure that the cases remain in
319
%% the correct, sorted order.
309
%% Cases is the case list and Clust is a list describing the optimal
310
%% clustering as returned by minclusters
312
%% If the value in the last place in minclusters is M then we can
313
%% split the case list into M clusters. We then search for the last
314
%% (== right-most) occurance of the value M-1 in minclusters. That
315
%% indicates the largest number of cases that can be split into M-1
316
%% clusters. This means that the cases in between constitute one
317
%% cluster. Then we recurse on the remainder of the cases.
319
%% The various calls to lists:reverse are just to ensure that the
320
%% cases remain in the correct, sorted order.
321
322
cluster_split(Cases,Clust) ->
322
A=tl(tuple_to_list(Clust)),
323
Max = element(size(Clust),Clust),
324
L1=lists:reverse(Cases),
326
cluster_split(Max,[],[],L1,L2).
323
A = tl(tuple_to_list(Clust)),
324
Max = element(size(Clust),Clust),
325
L1 = lists:reverse(Cases),
326
L2 = lists:reverse(A),
327
cluster_split(Max,[],[],L1,L2).
328
329
cluster_split(0,[],Res,Cases,_Clust) ->
329
L=lists:reverse(Cases),
332
[{dense,hipe_icode:const_value(H),hipe_icode:const_value(T),L}|Res];
330
L = lists:reverse(Cases),
333
[{dense,hipe_icode:const_value(H),hipe_icode:const_value(T),L}|Res];
334
335
cluster_split(N,[],Res,Cases,[N|Clust]) ->
335
cluster_split(N-1,[],Res,Cases,[N|Clust]);
336
cluster_split(N-1,[],Res,Cases,[N|Clust]);
337
338
cluster_split(N,Sofar,Res,Cases,[N|Clust]) ->
339
{T,_}=lists:last(Sofar),
340
cluster_split(N-1,[],[{dense,hipe_icode:const_value(H),hipe_icode:const_value(T),Sofar}|Res],Cases,[N|Clust]);
340
{T,_} = lists:last(Sofar),
341
cluster_split(N-1,[],[{dense,hipe_icode:const_value(H),hipe_icode:const_value(T),Sofar}|Res],Cases,[N|Clust]);
342
343
cluster_split(N,Sofar,Res,[C|Cases],[_|Clust]) ->
343
cluster_split(N,[C|Sofar],Res,Cases,Clust).
344
cluster_split(N,[C|Sofar],Res,Cases,Clust).
347
347
%% Merge adjacent small clusters into larger sparse clusters
349
349
cluster_merge([C]) -> [C];
351
351
cluster_merge([{dense,Min,Max,C}|T]) when length(C) >= ?MINFORJUMPTABLE ->
353
[{dense,Min,Max,C}|C2];
352
C2 = cluster_merge(T),
353
[{dense,Min,Max,C}|C2];
355
355
cluster_merge([{sparse,Min,_,C},{sparse,_,Max,D}|T]) ->
356
R = {sparse,Min,Max,C ++ D},
357
cluster_merge([R|T]);
356
R = {sparse,Min,Max,C ++ D},
357
cluster_merge([R|T]);
359
359
cluster_merge([{sparse,Min,_,C},{dense,_,Max,D}|T]) when length(D) < ?MINFORJUMPTABLE ->
360
R = {sparse,Min,Max,C ++ D},
361
cluster_merge([R|T]);
360
R = {sparse,Min,Max,C ++ D},
361
cluster_merge([R|T]);
363
363
cluster_merge([{dense,Min,_,C},{dense,_,Max,D}|T]) when length(C) < ?MINFORJUMPTABLE, length(D) < ?MINFORJUMPTABLE ->
364
R = {sparse,Min,Max,C ++ D},
365
cluster_merge([R|T]);
364
R = {sparse,Min,Max,C ++ D},
365
cluster_merge([R|T]);
367
367
cluster_merge([{dense,Min,_,D},{sparse,_,Max,C}|T]) when length(D) < ?MINFORJUMPTABLE ->
368
R = {sparse,Min,Max,C ++ D},
369
cluster_merge([R|T]);
368
R = {sparse,Min,Max,C ++ D},
369
cluster_merge([R|T]);
371
371
cluster_merge([A,{dense,Min,Max,C}|T]) when length(C) >= ?MINFORJUMPTABLE ->
372
R=cluster_merge([{dense,Min,Max,C}|T]),
372
R = cluster_merge([{dense,Min,Max,C}|T]),
376
376
%% Generate code to search for the correct cluster
378
378
find_cluster([{sparse,_Min,_Max,C}],VarMap,ConstTab,Options,Arg,Fail,_IcodeFail) ->
379
case length(C) < ?MINFORINTSEARCHTREE of
381
gen_small_switch_val(Arg,C,Fail,VarMap,ConstTab,Options);
383
gen_search_switch_val(Arg,C,Fail,VarMap,ConstTab,Options)
379
case length(C) < ?MINFORINTSEARCHTREE of
381
gen_small_switch_val(Arg,C,Fail,VarMap,ConstTab,Options);
383
gen_search_switch_val(Arg,C,Fail,VarMap,ConstTab,Options)
387
385
find_cluster([{dense,Min,_Max,C}],VarMap,ConstTab,Options,Arg,Fail,IcodeFail) ->
388
case length(C) < ?MINFORJUMPTABLE of
390
gen_small_switch_val(Arg,C,Fail,VarMap,ConstTab,Options);
392
gen_jump_table(Arg,Fail,IcodeFail,VarMap,ConstTab,C,Min)
386
case length(C) < ?MINFORJUMPTABLE of
388
gen_small_switch_val(Arg,C,Fail,VarMap,ConstTab,Options);
390
gen_jump_table(Arg,Fail,IcodeFail,VarMap,ConstTab,C,Min)
396
392
find_cluster([{Density,Min,Max,C}|T],VarMap,ConstTab,Options,Arg,Fail,IcodeFail) ->
398
ClustLab=hipe_rtl:mk_new_label(),
399
NextLab=hipe_rtl:mk_new_label(),
400
{ClustCode,V1,C1}=find_cluster([{Density,Min,Max,C}],VarMap,ConstTab,Options,Arg,Fail,IcodeFail),
402
{Rest,V2,C2}=find_cluster(T,V1,C1,Options,Arg,Fail,IcodeFail),
405
hipe_rtl:mk_branch(Arg , gt, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(Max)),
406
hipe_rtl:label_name(NextLab),
407
hipe_rtl:label_name(ClustLab) , 0.50),
393
ClustLab = hipe_rtl:mk_new_label(),
394
NextLab = hipe_rtl:mk_new_label(),
395
{ClustCode,V1,C1} = find_cluster([{Density,Min,Max,C}],VarMap,ConstTab,Options,Arg,Fail,IcodeFail),
397
{Rest,V2,C2} = find_cluster(T,V1,C1,Options,Arg,Fail,IcodeFail),
400
hipe_rtl:mk_branch(Arg, gt, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(Max)),
401
hipe_rtl:label_name(NextLab),
402
hipe_rtl:label_name(ClustLab), 0.50),
416
410
%% Generate efficient code for a linear search through the case list.
417
411
%% Only works for atoms and integer.
418
412
gen_linear_switch_val(Arg,Cases,Fail,VarMap,ConstTab,_Options) ->
419
{Values,_Labels} = split_cases(Cases),
420
{LabMap,VarMap1} = lbls_from_cases(Cases,VarMap),
422
Code = fast_linear_search(Arg,Values,LabMap,Fail),
423
{Code,VarMap1,ConstTab}.
413
{Values,_Labels} = split_cases(Cases),
414
{LabMap,VarMap1} = lbls_from_cases(Cases,VarMap),
415
Code = fast_linear_search(Arg,Values,LabMap,Fail),
416
{Code,VarMap1,ConstTab}.
425
418
fast_linear_search(_Arg,[],[],Fail) ->
427
hipe_rtl:mk_goto(hipe_rtl:label_name(Fail))
419
[hipe_rtl:mk_goto(hipe_rtl:label_name(Fail))];
429
420
fast_linear_search(Arg,[Case|Cases],[Label|Labels],Fail) ->
430
Reg= hipe_rtl:mk_new_reg(),
431
NextLab = hipe_rtl:mk_new_label(),
432
C2 = fast_linear_search(Arg,Cases,Labels,Fail),
436
TVal= hipe_tagscheme:mk_fixnum(Case),
438
hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(TVal)),
439
hipe_rtl:mk_branch(Arg,eq,Reg,
441
hipe_rtl:label_name(NextLab), 0.5),
446
hipe_rtl:mk_load_atom(Reg,Case),
447
hipe_rtl:mk_branch(Arg,eq,Reg,
449
hipe_rtl:label_name(NextLab), 0.5),
452
true -> % This should never happen !
453
?EXIT({internal_error_in_switch_val,Case})
421
Reg = hipe_rtl:mk_new_reg_gcsafe(),
422
NextLab = hipe_rtl:mk_new_label(),
423
C2 = fast_linear_search(Arg,Cases,Labels,Fail),
427
TVal = hipe_tagscheme:mk_fixnum(Case),
429
hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(TVal)),
430
hipe_rtl:mk_branch(Arg,eq,Reg,
432
hipe_rtl:label_name(NextLab), 0.5),
437
hipe_rtl:mk_load_atom(Reg,Case),
438
hipe_rtl:mk_branch(Arg,eq,Reg,
440
hipe_rtl:label_name(NextLab), 0.5),
443
true -> % This should never happen !
444
?EXIT({internal_error_in_switch_val,Case})
458
449
%% Generate code to search through a small cluster of integers using
460
451
gen_small_switch_val(Arg,Cases,Fail,VarMap,ConstTab,_Options) ->
461
{Values,_Labels} = split_cases(Cases),
462
{LabMap,VarMap1} = lbls_from_cases(Cases,VarMap),
463
Keys = [hipe_tagscheme:mk_fixnum(X) % Add tags to the values
465
Code = inline_search(Keys, LabMap, Arg, Fail),
466
{Code, VarMap1, ConstTab}.
452
{Values,_Labels} = split_cases(Cases),
453
{LabMap,VarMap1} = lbls_from_cases(Cases,VarMap),
454
Keys = [hipe_tagscheme:mk_fixnum(X) % Add tags to the values
456
Code = inline_search(Keys, LabMap, Arg, Fail),
457
{Code, VarMap1, ConstTab}.
469
460
%% Generate code to search through a small cluster of atoms
470
461
gen_atom_switch_val(Arg,Cases,Fail,VarMap,ConstTab,_Options) ->
471
{Values, _Labels} = split_cases(Cases),
472
{LabMap,VarMap1} = lbls_from_cases(Cases,VarMap),
473
LMap = [{label,L} || L <- LabMap],
475
{NewConstTab,Id} = hipe_consttab:insert_sorted_block(ConstTab, Values),
476
{NewConstTab2,LabId} = hipe_consttab:insert_sorted_block(NewConstTab, 4 , word, LMap, Values),
478
Code = inline_atom_search(0, length(Cases)-1, Id, LabId, Arg, Fail, LabMap),
480
{Code, VarMap1, NewConstTab2}.
483
%% calculate the middle position of a list (+ 1 because of 1-indexing of listes)
462
{Values, _Labels} = split_cases(Cases),
463
{LabMap,VarMap1} = lbls_from_cases(Cases,VarMap),
464
LMap = [{label,L} || L <- LabMap],
466
{NewConstTab,Id} = hipe_consttab:insert_sorted_block(ConstTab, Values),
467
{NewConstTab2,LabId} =
468
hipe_consttab:insert_sorted_block(NewConstTab, word, LMap, Values),
470
Code = inline_atom_search(0, length(Cases)-1, Id, LabId, Arg, Fail, LabMap),
472
{Code, VarMap1, NewConstTab2}.
475
%% calculate the middle position of a list (+ 1 because of 1-indexing of lists)
484
476
get_middle(List) ->
489
480
%% get element [N1, N2] from a list
490
481
get_cases(_, 0, 0) ->
492
483
get_cases([H|T], 0, N) ->
493
[H | get_cases(T, 0, N - 1)];
484
[H | get_cases(T, 0, N - 1)];
494
485
get_cases([_|T], N1, N2) ->
495
get_cases(T, N1 - 1, N2 - 1).
499
%% inline_search/4 creates rtl code for a inlined binary search.
486
get_cases(T, N1 - 1, N2 - 1).
489
%% inline_search/4 creates RTL code for a inlined binary search.
500
490
%% It requires two sorted tables - one with the keys to search
501
491
%% through and one with the corresponding labels to jump to.
510
500
inline_search([], _LabelList, _KeyReg, _Default) -> [];
511
501
inline_search(KeyList, LabelList, KeyReg, Default) ->
512
%% Create some registers and lables that we need.
513
Reg = hipe_rtl:mk_new_reg(),
514
Lab1 = hipe_rtl:mk_new_label(),
515
Lab2 = hipe_rtl:mk_new_label(),
516
Lab3 = hipe_rtl:mk_new_label(),
518
Length = length(KeyList),
523
%% Get middle element and keys/labels before that and after
524
Middle_pos = get_middle(KeyList),
525
Middle_key = lists:nth(Middle_pos, KeyList),
526
Keys_beginning = get_cases(KeyList, 0, Middle_pos - 1),
527
Labels_beginning = get_cases(LabelList, 0, Middle_pos - 1),
528
Keys_ending = get_cases(KeyList, Middle_pos, Length),
529
Labels_ending = get_cases(LabelList, Middle_pos, Length),
533
%% Get the label and build it up properly
534
Middle_label = lists:nth(Middle_pos, LabelList),
536
A =[hipe_rtl:mk_move(Reg, hipe_rtl:mk_imm(Middle_key)),
537
hipe_rtl:mk_branch(KeyReg, lt, Reg,
538
hipe_rtl:label_name(Lab2),
539
hipe_rtl:label_name(Lab1), 0.5),
541
hipe_rtl:mk_branch(KeyReg, gt, Reg,
542
hipe_rtl:label_name(Lab3),
545
%% build search tree for keys less than the middle element
546
B = inline_search(Keys_beginning, Labels_beginning, KeyReg, Default),
547
%% ...and for keys bigger than the middle element
548
D = inline_search(Keys_ending, Labels_ending, KeyReg, Default),
550
%% append the code and return it
551
A ++ B ++ [Lab3] ++ D;
554
%% get the first and second elements and theirs labels
555
Key_first = hd(KeyList),
556
First_label = hd(LabelList),
558
% Key_second = hipe_tagscheme:mk_fixnum(lists:nth(2, KeyList)),
559
Key_second = lists:nth(2, KeyList),
560
Second_label = lists:nth(2, LabelList),
562
NewLab = hipe_rtl:mk_new_label(),
565
A = [hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(Key_first)),
566
hipe_rtl:mk_branch(KeyReg, eq, Reg,
568
hipe_rtl:label_name(NewLab) , 0.5),
572
B = [hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(Key_second)),
573
hipe_rtl:mk_branch(KeyReg, eq, Reg,
575
hipe_rtl:label_name(Default) , 0.5)],
580
Label = hd(LabelList),
582
[hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(Key)),
583
hipe_rtl:mk_branch(KeyReg, eq, Reg,
585
hipe_rtl:label_name(Default) , 0.5)]
590
inline_atom_search(Start,End, Block, LBlock, KeyReg, Default, Labels) ->
591
Reg = hipe_rtl:mk_new_reg(),
593
Length = (End - Start) +1,
597
Lab1 = hipe_rtl:mk_new_label(),
598
Lab2 = hipe_rtl:mk_new_label(),
599
Lab3 = hipe_rtl:mk_new_label(),
600
Lab4 = hipe_rtl:mk_new_label(),
602
Mid = ((End-Start) div 2)+Start,
606
hipe_rtl:mk_load_word_index(Reg,Block,Mid),
607
hipe_rtl:mk_branch(KeyReg, lt, Reg,
608
hipe_rtl:label_name(Lab2),
609
hipe_rtl:label_name(Lab1), 0.5),
611
hipe_rtl:mk_branch(KeyReg, gt, Reg,
612
hipe_rtl:label_name(Lab3),
613
hipe_rtl:label_name(Lab4), 0.5),
615
hipe_rtl:mk_goto_index(LBlock, Mid, Labels),
618
B = [inline_atom_search(Start,End1,Block,LBlock,KeyReg,Default,Labels)],
619
C = [inline_atom_search(Start1,End,Block,LBlock,KeyReg,Default,Labels)],
620
A ++ B ++ [Lab3] ++ C;
623
L1 = hipe_rtl:mk_new_label(),
624
L2 = hipe_rtl:mk_new_label(),
625
L3 = hipe_rtl:mk_new_label(),
627
hipe_rtl:mk_load_word_index(Reg,Block,Start),
628
hipe_rtl:mk_branch(KeyReg,eq,Reg,
629
hipe_rtl:label_name(L1),
630
hipe_rtl:label_name(L2), 0.5),
632
hipe_rtl:mk_goto_index(LBlock,Start,Labels),
635
hipe_rtl:mk_load_word_index(Reg,Block,End),
636
hipe_rtl:mk_branch(KeyReg,eq,Reg,
637
hipe_rtl:label_name(L3),
638
hipe_rtl:label_name(Default), 0.5),
640
hipe_rtl:mk_goto_index(LBlock, End, Labels)
644
NewLab = hipe_rtl:mk_new_label(),
646
hipe_rtl:mk_load_word_index(Reg,Block,Start),
647
hipe_rtl:mk_branch(KeyReg, eq, Reg,
648
hipe_rtl:label_name(NewLab),
649
hipe_rtl:label_name(Default) , 0.9),
651
hipe_rtl:mk_goto_index(LBlock, Start, Labels)
502
%% Create some registers and labels that we need.
503
Reg = hipe_rtl:mk_new_reg_gcsafe(),
504
Lab1 = hipe_rtl:mk_new_label(),
505
Lab2 = hipe_rtl:mk_new_label(),
506
Lab3 = hipe_rtl:mk_new_label(),
508
Length = length(KeyList),
512
%% Get middle element and keys/labels before that and after
513
Middle_pos = get_middle(KeyList),
514
Middle_key = lists:nth(Middle_pos, KeyList),
515
Keys_beginning = get_cases(KeyList, 0, Middle_pos - 1),
516
Labels_beginning = get_cases(LabelList, 0, Middle_pos - 1),
517
Keys_ending = get_cases(KeyList, Middle_pos, Length),
518
Labels_ending = get_cases(LabelList, Middle_pos, Length),
522
%% Get the label and build it up properly
523
Middle_label = lists:nth(Middle_pos, LabelList),
525
A = [hipe_rtl:mk_move(Reg, hipe_rtl:mk_imm(Middle_key)),
526
hipe_rtl:mk_branch(KeyReg, lt, Reg,
527
hipe_rtl:label_name(Lab2),
528
hipe_rtl:label_name(Lab1), 0.5),
530
hipe_rtl:mk_branch(KeyReg, gt, Reg,
531
hipe_rtl:label_name(Lab3),
534
%% build search tree for keys less than the middle element
535
B = inline_search(Keys_beginning, Labels_beginning, KeyReg, Default),
536
%% ...and for keys bigger than the middle element
537
D = inline_search(Keys_ending, Labels_ending, KeyReg, Default),
539
%% append the code and return it
540
A ++ B ++ [Lab3] ++ D;
543
%% get the first and second elements and theirs labels
544
Key_first = hd(KeyList),
545
First_label = hd(LabelList),
547
%% Key_second = hipe_tagscheme:mk_fixnum(lists:nth(2, KeyList)),
548
Key_second = lists:nth(2, KeyList),
549
Second_label = lists:nth(2, LabelList),
551
NewLab = hipe_rtl:mk_new_label(),
554
A = [hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(Key_first)),
555
hipe_rtl:mk_branch(KeyReg, eq, Reg,
557
hipe_rtl:label_name(NewLab) , 0.5),
560
B = [hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(Key_second)),
561
hipe_rtl:mk_branch(KeyReg, eq, Reg,
563
hipe_rtl:label_name(Default) , 0.5)],
568
Label = hd(LabelList),
570
[hipe_rtl:mk_move(Reg,hipe_rtl:mk_imm(Key)),
571
hipe_rtl:mk_branch(KeyReg, eq, Reg,
573
hipe_rtl:label_name(Default) , 0.5)]
577
inline_atom_search(Start, End, Block, LBlock, KeyReg, Default, Labels) ->
578
Reg = hipe_rtl:mk_new_reg_gcsafe(),
580
Length = (End - Start) +1,
584
Lab1 = hipe_rtl:mk_new_label(),
585
Lab2 = hipe_rtl:mk_new_label(),
586
Lab3 = hipe_rtl:mk_new_label(),
587
Lab4 = hipe_rtl:mk_new_label(),
589
Mid = ((End-Start) div 2)+Start,
593
hipe_rtl:mk_load_word_index(Reg,Block,Mid),
594
hipe_rtl:mk_branch(KeyReg, lt, Reg,
595
hipe_rtl:label_name(Lab2),
596
hipe_rtl:label_name(Lab1), 0.5),
598
hipe_rtl:mk_branch(KeyReg, gt, Reg,
599
hipe_rtl:label_name(Lab3),
600
hipe_rtl:label_name(Lab4), 0.5),
602
hipe_rtl:mk_goto_index(LBlock, Mid, Labels),
605
B = [inline_atom_search(Start,End1,Block,LBlock,KeyReg,Default,Labels)],
606
C = [inline_atom_search(Start1,End,Block,LBlock,KeyReg,Default,Labels)],
607
A ++ B ++ [Lab3] ++ C;
610
L1 = hipe_rtl:mk_new_label(),
611
L2 = hipe_rtl:mk_new_label(),
612
L3 = hipe_rtl:mk_new_label(),
614
hipe_rtl:mk_load_word_index(Reg,Block,Start),
615
hipe_rtl:mk_branch(KeyReg,eq,Reg,
616
hipe_rtl:label_name(L1),
617
hipe_rtl:label_name(L2), 0.5),
619
hipe_rtl:mk_goto_index(LBlock,Start,Labels),
622
hipe_rtl:mk_load_word_index(Reg,Block,End),
623
hipe_rtl:mk_branch(KeyReg,eq,Reg,
624
hipe_rtl:label_name(L3),
625
hipe_rtl:label_name(Default), 0.5),
627
hipe_rtl:mk_goto_index(LBlock, End, Labels)
631
NewLab = hipe_rtl:mk_new_label(),
633
hipe_rtl:mk_load_word_index(Reg,Block,Start),
634
hipe_rtl:mk_branch(KeyReg, eq, Reg,
635
hipe_rtl:label_name(NewLab),
636
hipe_rtl:label_name(Default), 0.9),
638
hipe_rtl:mk_goto_index(LBlock, Start, Labels)
656
643
%% Create a jumptable
657
644
gen_jump_table(Arg,Fail,IcodeFail,VarMap,ConstTab,Cases,Min) ->
658
%% Map is a rtl mapping of Dense
659
{Max,DenseTbl} = dense_interval(Cases,Min,IcodeFail),
660
{Map,VarMap2} = lbls_from_cases(DenseTbl,VarMap),
662
%% Make some labels and registers that we need.
663
BelowLab = hipe_rtl:mk_new_label(),
664
UntaggedR = hipe_rtl:mk_new_reg(),
665
StartR = hipe_rtl:mk_new_reg(),
667
%% Generate the code to do the switch...
672
%% TODO: Use the tagscheme module for this!
673
hipe_rtl:mk_alu(UntaggedR, Arg, sra, hipe_rtl:mk_imm(4))|
674
%% Check that the index is within Min and Max.
676
0 -> %% First element is 0 this is simple.
677
[hipe_rtl:mk_branch(UntaggedR, gtu, hipe_rtl:mk_imm(Max),
678
hipe_rtl:label_name(Fail),
679
hipe_rtl:label_name(BelowLab) , 0.01),
681
%% StartR contains the index into the jumptable
682
hipe_rtl:mk_switch(UntaggedR, Map)];
683
_ -> %% First element is not 0
684
[hipe_rtl:mk_alu(StartR, UntaggedR, sub,
685
hipe_rtl:mk_imm(Min)),
686
hipe_rtl:mk_branch(StartR, gtu, hipe_rtl:mk_imm(Max-Min),
687
hipe_rtl:label_name(Fail),
688
hipe_rtl:label_name(BelowLab) , 0.01),
690
%% StartR contains the index into the jumptable
691
hipe_rtl:mk_switch(StartR, Map)]
697
% Generate the jumptable for Cases while filling in unused positions
698
% with the fail label
645
%% Map is a rtl mapping of Dense
646
{Max,DenseTbl} = dense_interval(Cases,Min,IcodeFail),
647
{Map,VarMap2} = lbls_from_cases(DenseTbl,VarMap),
649
%% Make some labels and registers that we need.
650
BelowLab = hipe_rtl:mk_new_label(),
651
UntaggedR = hipe_rtl:mk_new_reg_gcsafe(),
652
StartR = hipe_rtl:mk_new_reg_gcsafe(),
654
%% Generate the code to do the switch...
657
hipe_tagscheme:untag_fixnum(UntaggedR, Arg)|
658
%% Check that the index is within Min and Max.
660
0 -> %% First element is 0 this is simple.
661
[hipe_rtl:mk_branch(UntaggedR, gtu, hipe_rtl:mk_imm(Max),
662
hipe_rtl:label_name(Fail),
663
hipe_rtl:label_name(BelowLab), 0.01),
665
%% StartR contains the index into the jumptable
666
hipe_rtl:mk_switch(UntaggedR, Map)];
667
_ -> %% First element is not 0
668
[hipe_rtl:mk_alu(StartR, UntaggedR, sub,
669
hipe_rtl:mk_imm(Min)),
670
hipe_rtl:mk_branch(StartR, gtu, hipe_rtl:mk_imm(Max-Min),
671
hipe_rtl:label_name(Fail),
672
hipe_rtl:label_name(BelowLab), 0.01),
674
%% StartR contains the index into the jumptable
675
hipe_rtl:mk_switch(StartR, Map)]
681
%% Generate the jumptable for Cases while filling in unused positions
682
%% with the fail label
700
684
dense_interval(Cases, Min, IcodeFail) ->
701
dense_interval(Cases, Min, IcodeFail, 0, 0).
685
dense_interval(Cases, Min, IcodeFail, 0, 0).
702
686
dense_interval([Pair = {Const,_}|Rest], Pos, Fail, Range, NoEntries) ->
703
Val= hipe_icode:const_value(Const),
707
dense_interval([Pair|Rest], Pos+1, Fail, Range+1, NoEntries),
708
{Max,[{hipe_icode:mk_const(Pos), Fail}|Res]};
710
{Max, Res} = dense_interval(Rest, Pos+1, Fail, Range+1, NoEntries+1),
687
Val = hipe_icode:const_value(Const),
691
dense_interval([Pair|Rest], Pos+1, Fail, Range+1, NoEntries),
692
{Max,[{hipe_icode:mk_const(Pos), Fail}|Res]};
694
{Max, Res} = dense_interval(Rest, Pos+1, Fail, Range+1, NoEntries+1),
713
697
dense_interval([], Max, _, _, _) ->
717
701
%%-------------------------------------------------------------------------
718
702
%% switch_val without jumptable
721
gen_slow_switch_val(I, VarMap, ConstTab, Options, ExitInfo) ->
705
gen_slow_switch_val(I, VarMap, ConstTab, Options) ->
722
706
Is = rewrite_switch_val(I),
723
707
?IF_DEBUG_LEVEL(3,?msg("Switch: ~w\n",[Is]),no_debug),
724
hipe_icode2rtl:translate_instrs(Is, VarMap, ConstTab, Options, ExitInfo).
708
hipe_icode2rtl:translate_instrs(Is, VarMap, ConstTab, Options).
726
710
rewrite_switch_val(I) ->
727
Arg = hipe_icode:switch_val_arg(I),
728
Fail = hipe_icode:switch_val_fail_label(I),
729
Cases = hipe_icode:switch_val_cases(I),
730
rewrite_switch_val_cases(Cases, Fail, Arg).
711
Arg = hipe_icode:switch_val_arg(I),
712
Fail = hipe_icode:switch_val_fail_label(I),
713
Cases = hipe_icode:switch_val_cases(I),
714
rewrite_switch_val_cases(Cases, Fail, Arg).
732
716
rewrite_switch_val_cases([{C,L}|Cases], Fail, Arg) ->
733
Tmp = hipe_icode:mk_new_var(),
734
NextLab = hipe_icode:mk_new_label(),
735
[hipe_icode:mk_mov(Tmp, C),
736
hipe_icode:mk_if(op_exact_eqeq_2, [Arg, Tmp], L,
737
hipe_icode:label_name(NextLab)),
739
rewrite_switch_val_cases(Cases, Fail, Arg)];
717
Tmp = hipe_icode:mk_new_var(),
718
NextLab = hipe_icode:mk_new_label(),
719
[hipe_icode:mk_move(Tmp, C),
720
hipe_icode:mk_if(op_exact_eqeq_2, [Arg, Tmp], L,
721
hipe_icode:label_name(NextLab)),
723
rewrite_switch_val_cases(Cases, Fail, Arg)];
740
724
rewrite_switch_val_cases([], Fail, _Arg) ->
741
[hipe_icode:mk_goto(Fail)].
725
[hipe_icode:mk_goto(Fail)].
744
728
%%-------------------------------------------------------------------------
900
881
[hipe_rtl:mk_branch(IndexReg, gt, hipe_rtl:mk_imm(LastOffset),
901
882
hipe_rtl:label_name(Default),
902
hipe_rtl:label_name(Lab3) , 0.5),
883
hipe_rtl:label_name(Lab3), 0.5),
904
885
hipe_rtl:mk_load(Temp2,TablePntrReg,IndexReg),
905
886
hipe_rtl:mk_branch(Temp2, eq, KeyReg,
906
887
hipe_rtl:label_name(Lab4),
907
hipe_rtl:label_name(Default) , 0.9),
888
hipe_rtl:label_name(Default), 0.9),
909
hipe_rtl:mk_alu(IndexReg, IndexReg, sra,
911
hipe_rtl:mk_sorted_switch(IndexReg, LabelList, KeyList)]
914
step(?WORDSIZE,TablePntrReg,IndexReg,KeyReg) ->
915
Temp = hipe_rtl:mk_new_reg(),
916
TempIndex = hipe_rtl:mk_new_reg(),
917
Lab1 = hipe_rtl:mk_new_label(),
918
Lab2 = hipe_rtl:mk_new_label(),
920
[hipe_rtl:mk_alu(TempIndex, IndexReg, add,
921
hipe_rtl:mk_imm(?WORDSIZE)),
923
hipe_rtl:mk_load(Temp,TablePntrReg,TempIndex),
924
hipe_rtl:mk_branch(Temp, gt, KeyReg,
925
hipe_rtl:label_name(Lab2),
926
hipe_rtl:label_name(Lab1) , 0.5),
928
hipe_rtl:mk_alu(IndexReg, IndexReg, add,
929
hipe_rtl:mk_imm(?WORDSIZE)),
930
hipe_rtl:mk_goto(hipe_rtl:label_name(Lab2)),
890
hipe_rtl:mk_alu(IndexReg, IndexReg, sra,
891
hipe_rtl:mk_imm(hipe_rtl_arch:log2_word_size())),
892
hipe_rtl:mk_sorted_switch(IndexReg, LabelList, KeyList)
933
895
step(I,TablePntrReg,IndexReg,KeyReg) ->
934
Temp = hipe_rtl:mk_new_reg(),
935
TempIndex = hipe_rtl:mk_new_reg(),
896
Temp = hipe_rtl:mk_new_reg_gcsafe(),
897
TempIndex = hipe_rtl:mk_new_reg_gcsafe(),
936
898
Lab1 = hipe_rtl:mk_new_label(),
937
899
Lab2 = hipe_rtl:mk_new_label(),
939
900
[hipe_rtl:mk_alu(TempIndex, IndexReg, add, hipe_rtl:mk_imm(I)),
940
901
hipe_rtl:mk_load(Temp,TablePntrReg,TempIndex),
941
902
hipe_rtl:mk_branch(Temp, gt, KeyReg,
942
hipe_rtl:label_name(Lab2),
943
hipe_rtl:label_name(Lab1) , 0.5),
945
hipe_rtl:mk_move(IndexReg, TempIndex),
946
hipe_rtl:mk_goto(hipe_rtl:label_name(Lab2)),
948
step(I div 2,TablePntrReg,IndexReg,KeyReg)].
903
hipe_rtl:label_name(Lab2),
904
hipe_rtl:label_name(Lab1) , 0.5),
907
I -> %% Recursive base case
908
[hipe_rtl:mk_alu(IndexReg, IndexReg, add, hipe_rtl:mk_imm(I)),
909
hipe_rtl:mk_goto(hipe_rtl:label_name(Lab2)),
912
_ -> %% Recursion case
913
[hipe_rtl:mk_move(IndexReg, TempIndex),
914
hipe_rtl:mk_goto(hipe_rtl:label_name(Lab2)),
916
| step(I div 2,TablePntrReg,IndexReg,KeyReg)
952
920
%%-------------------------------------------------------------------------
979
943
%% switch_int(Hdr,Fail,[{H(A1),L1},...,{H(AN),LN}])
980
944
%% where H(Ai) = make_arityval(Ai)
946
%%-------------------------------------------------------------------------
983
gen_switch_tuple(I, Map, ConstTab, _Options, _ExitInfo) ->
948
gen_switch_tuple(I, Map, ConstTab, _Options) ->
985
950
hipe_rtl_varmap:icode_var2rtl_var(hipe_icode:switch_tuple_arity_arg(I), Map),
986
Fail0 = hipe_icode:switch_tuple_arity_fail_label(I),
988
hipe_rtl_varmap:icode_label2rtl_label(Fail0, Map1),
989
FailLab = hipe_rtl:label_name(Fail1),
991
lists:foldr(fun({A,L}, {Rest,M}) ->
992
{L1,M1} = hipe_rtl_varmap:icode_label2rtl_label(L, M),
993
L2 = hipe_rtl:label_name(L1),
994
A1 = hipe_icode:const_value(A),
995
H1 = hipe_tagscheme:mk_arityval(A1),
996
{[{H1,L2}|Rest], M1} end,
998
hipe_icode:switch_tuple_arity_cases(I)),
999
Hdr = hipe_rtl:mk_new_reg(),
1000
IsBoxedLab = hipe_rtl:mk_new_label(),
1001
{[hipe_tagscheme:test_is_boxed(X, hipe_rtl:label_name(IsBoxedLab),
1004
hipe_tagscheme:get_header(Hdr, X) |
1005
gen_switch_int(Hdr, FailLab, Cases)],
951
Fail0 = hipe_icode:switch_tuple_arity_fail_label(I),
952
{Fail1, Map2} = hipe_rtl_varmap:icode_label2rtl_label(Fail0, Map1),
953
FailLab = hipe_rtl:label_name(Fail1),
955
lists:foldr(fun({A,L}, {Rest,M}) ->
956
{L1,M1} = hipe_rtl_varmap:icode_label2rtl_label(L, M),
957
L2 = hipe_rtl:label_name(L1),
958
A1 = hipe_icode:const_value(A),
959
H1 = hipe_tagscheme:mk_arityval(A1),
960
{[{H1,L2}|Rest], M1} end,
962
hipe_icode:switch_tuple_arity_cases(I)),
963
Hdr = hipe_rtl:mk_new_reg_gcsafe(),
964
IsBoxedLab = hipe_rtl:mk_new_label(),
965
{[hipe_tagscheme:test_is_boxed(X, hipe_rtl:label_name(IsBoxedLab),
968
hipe_tagscheme:get_header(Hdr, X) |
969
gen_switch_int(Hdr, FailLab, Cases)],
1009
%% rtl-level switch-on-int
973
%% RTL-level switch-on-int
1012
976
gen_switch_int(X, FailLab, [{C,L}|Rest]) ->
1013
NextLab = hipe_rtl:mk_new_label(),
1014
[hipe_rtl:mk_branch(X, eq, hipe_rtl:mk_imm(C), L,
1015
hipe_rtl:label_name(NextLab), 0.5),
1017
gen_switch_int(X, FailLab, Rest)];
977
NextLab = hipe_rtl:mk_new_label(),
978
[hipe_rtl:mk_branch(X, eq, hipe_rtl:mk_imm(C), L,
979
hipe_rtl:label_name(NextLab), 0.5),
981
gen_switch_int(X, FailLab, Rest)];
1018
982
gen_switch_int(_, FailLab, []) ->
1019
[hipe_rtl:mk_goto(FailLab)].
983
[hipe_rtl:mk_goto(FailLab)].