1 /* optimizer.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2009 */
2
3 /*
4
5 Copyright (c) 2005-2009 Made to Order Software Corp.
6
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31
32 */
33
34 #define NEED_ISINF
35 #include "optimizer.h"
36
37
38
39 namespace sswf
40 {
41 namespace as
42 {
43
44
45 /**********************************************************************/
46 /**********************************************************************/
47 /*** OPTIMIZER CREATOR **********************************************/
48 /**********************************************************************/
49 /**********************************************************************/
50
CreateOptimizer(void)51 Optimizer *Optimizer::CreateOptimizer(void)
52 {
53 return new IntOptimizer();
54 }
55
56
Version(void)57 const char *Optimizer::Version(void)
58 {
59 return TO_STR(SSWF_VERSION);
60 }
61
62
63 /**********************************************************************/
64 /**********************************************************************/
65 /*** INTERNAL OPTIMIZER *********************************************/
66 /**********************************************************************/
67 /**********************************************************************/
68
IntOptimizer(void)69 IntOptimizer::IntOptimizer(void)
70 {
71 f_error_stream = &f_default_error_stream;
72 f_options = 0;
73 f_label = 0;
74 f_errcnt = 0;
75 }
76
77
~IntOptimizer()78 IntOptimizer::~IntOptimizer()
79 {
80 }
81
82
SetErrorStream(ErrorStream & error_stream)83 void IntOptimizer::SetErrorStream(ErrorStream& error_stream)
84 {
85 f_error_stream = &error_stream;
86 }
87
88
SetOptions(Options & options)89 void IntOptimizer::SetOptions(Options& options)
90 {
91 f_options = &options;
92 }
93
94
95
96
97 /**********************************************************************/
98 /**********************************************************************/
99 /*** OPTIMIZE *******************************************************/
100 /**********************************************************************/
101 /**********************************************************************/
102
Optimize(NodePtr & node)103 int IntOptimizer::Optimize(NodePtr& node)
104 {
105 f_errcnt = 0;
106
107 Run(node);
108
109 return f_errcnt;
110 }
111
112
113
Label(String & label)114 void IntOptimizer::Label(String& label)
115 {
116 char buf[256];
117
118 snprintf(buf, sizeof(buf), "__optimizer__%d", f_label);
119 f_label++;
120 label = buf;
121 }
122
GetLastLabel(void) const123 int IntOptimizer::GetLastLabel(void) const
124 {
125 return f_label;
126 }
127
SetFirstLabel(int label)128 void IntOptimizer::SetFirstLabel(int label)
129 {
130 f_label = label;
131 }
132
133
134
Run(NodePtr & node)135 void IntOptimizer::Run(NodePtr& node)
136 {
137 int idx, max;
138
139 // accept empty nodes, just ignore them
140 if(!node.HasNode()) {
141 return;
142 }
143
144 // we need to optimize the child most nodes first
145 max = node.GetChildCount();
146 for(idx = 0; idx < max; ++idx) {
147 NodePtr& child = node.GetChild(idx);
148 if(child.HasNode()) {
149 Run(child);
150
151 Data& data = child.GetData();
152 if(data.f_type == NODE_UNKNOWN) {
153 node.DeleteChild(idx);
154 idx--;
155 max--;
156 }
157 }
158 }
159
160 Data& data = node.GetData();
161 switch(data.f_type) {
162 case NODE_DIRECTIVE_LIST:
163 DirectiveList(node);
164 break;
165
166 case NODE_IF:
167 If(node);
168 break;
169
170 case NODE_WHILE:
171 While(node);
172 break;
173
174 case NODE_DO:
175 Do(node);
176 break;
177
178 case NODE_ASSIGNMENT:
179 Assignment(node);
180 break;
181
182 case NODE_ASSIGNMENT_ADD:
183 case NODE_ASSIGNMENT_SUBTRACT:
184 AssignmentAdd(node);
185 break;
186
187 case NODE_ASSIGNMENT_MULTIPLY:
188 AssignmentMultiply(node);
189 break;
190
191 case NODE_ASSIGNMENT_DIVIDE:
192 AssignmentDivide(node);
193 break;
194
195 case NODE_ASSIGNMENT_MODULO:
196 AssignmentModulo(node);
197 break;
198
199 case NODE_BITWISE_NOT:
200 BitwiseNot(node);
201 break;
202
203 case NODE_LOGICAL_NOT:
204 LogicalNot(node);
205 break;
206
207 case NODE_DECREMENT:
208 Decrement(node);
209 break;
210
211 case NODE_INCREMENT:
212 Increment(node);
213 break;
214
215 case NODE_POWER:
216 Power(node);
217 break;
218
219 case NODE_MULTIPLY:
220 Multiply(node);
221 break;
222
223 case NODE_DIVIDE:
224 Divide(node);
225 break;
226
227 case NODE_MODULO:
228 Modulo(node);
229 break;
230
231 case NODE_ADD:
232 Add(node);
233 break;
234
235 case NODE_SUBTRACT:
236 Subtract(node);
237 break;
238
239 case NODE_SHIFT_LEFT:
240 ShiftLeft(node);
241 break;
242
243 case NODE_SHIFT_RIGHT:
244 ShiftRight(node);
245 break;
246
247 case NODE_SHIFT_RIGHT_UNSIGNED:
248 ShiftRightUnsigned(node);
249 break;
250
251 case NODE_ROTATE_LEFT:
252 RotateLeft(node);
253 break;
254
255 case NODE_ROTATE_RIGHT:
256 RotateRight(node);
257 break;
258
259 case NODE_LESS:
260 Less(node);
261 break;
262
263 case NODE_LESS_EQUAL:
264 LessEqual(node);
265 break;
266
267 case NODE_GREATER:
268 Greater(node);
269 break;
270
271 case NODE_GREATER_EQUAL:
272 GreaterEqual(node);
273 break;
274
275 case NODE_EQUAL:
276 Equality(node, false, false);
277 break;
278
279 case NODE_STRICTLY_EQUAL:
280 Equality(node, true, false);
281 break;
282
283 case NODE_NOT_EQUAL:
284 Equality(node, false, true);
285 break;
286
287 case NODE_STRICTLY_NOT_EQUAL:
288 Equality(node, true, true);
289 break;
290
291 case NODE_BITWISE_AND:
292 BitwiseAnd(node);
293 break;
294
295 case NODE_BITWISE_XOR:
296 BitwiseXOr(node);
297 break;
298
299 case NODE_BITWISE_OR:
300 BitwiseOr(node);
301 break;
302
303 case NODE_LOGICAL_AND:
304 LogicalAnd(node);
305 break;
306
307 case NODE_LOGICAL_XOR:
308 LogicalXOr(node);
309 break;
310
311 case NODE_LOGICAL_OR:
312 LogicalOr(node);
313 break;
314
315 case NODE_MAXIMUM:
316 Maximum(node);
317 break;
318
319 case NODE_MINIMUM:
320 Minimum(node);
321 break;
322
323 case NODE_CONDITIONAL:
324 Conditional(node);
325 break;
326
327 default:
328 break;
329
330 }
331 }
332
333
334
DirectiveList(NodePtr & list)335 void IntOptimizer::DirectiveList(NodePtr& list)
336 {
337 int max = list.GetChildCount();
338 for(int idx = 0; idx < max; ++idx) {
339 NodePtr& child = list.GetChild(idx);
340 Data& data = child.GetData();
341 if(data.f_type == NODE_IDENTIFIER) {
342 NodePtr& instance = child.GetLink(NodePtr::LINK_INSTANCE);
343 if(instance.HasNode()) {
344 list.DeleteChild(idx);
345 --idx;
346 --max;
347 }
348 }
349 }
350 }
351
352
If(NodePtr & if_node)353 void IntOptimizer::If(NodePtr& if_node)
354 {
355 int max = if_node.GetChildCount();
356 if(max != 2 && max != 3) {
357 return;
358 }
359
360 NodePtr& condition = if_node.GetChild(0);
361 Data& data = condition.GetData();
362 if(data.ToBoolean()) {
363 if(data.f_type == NODE_TRUE) {
364 NodePtr then = if_node.GetChild(1);
365 if_node.DeleteChild(1);
366 if_node.ReplaceWith(then);
367 }
368 else if(max == 3) {
369 NodePtr else_node = if_node.GetChild(2);
370 if_node.DeleteChild(2);
371 if_node.ReplaceWith(else_node);
372 }
373 else {
374 // we want to delete the if_node, it serves
375 // no purpose! (another function is in charge
376 // of deleting; we just mark the node as unknown)
377 Data& data = if_node.GetData();
378 data.f_type = NODE_UNKNOWN;
379 }
380 }
381 }
382
383
While(NodePtr & while_node)384 void IntOptimizer::While(NodePtr& while_node)
385 {
386 int max = while_node.GetChildCount();
387 if(max != 2) {
388 return;
389 }
390
391 // TODO:
392 //
393 // if we detect something such as:
394 //
395 // cnt = 3
396 // while(cnt > 0) {
397 // ...
398 // }
399 //
400 // we can reduce to:
401 //
402 // cnt = 3;
403 // do {
404 // ...
405 // } while(cnt > 0);
406 //
407 // since the first time cnt > 0 will always be true.
408 //
409
410 NodePtr& condition = while_node.GetChild(0);
411 Data& data = condition.GetData();
412 if(data.ToBoolean()) {
413 if(data.f_type == NODE_TRUE) {
414 // TODO:
415 // Whenever we detect a forever loop we
416 // need to check whether it includes some
417 // break. If there isn't a break, we should
418 // err about it. It is likely a bad one!
419 // [except if the function returns Never]
420 //
421 // create a forever loop
422 NodePtr forever;
423 forever.CreateNode(NODE_DIRECTIVE_LIST);
424 forever.CopyInputInfo(while_node);
425
426 NodePtr label;
427 label.CreateNode(NODE_LABEL);
428 label.CopyInputInfo(while_node);
429 Data& label_data = label.GetData();
430 Label(label_data.f_str);
431 forever.AddChild(label);
432
433 NodePtr list = while_node.GetChild(1);
434 while_node.DeleteChild(1);
435 forever.AddChild(list);
436
437 NodePtr goto_label;
438 goto_label.CreateNode(NODE_GOTO);
439 goto_label.CopyInputInfo(while_node);
440 Data& goto_data = goto_label.GetData();
441 goto_data.f_str = label_data.f_str;
442 forever.AddChild(goto_label);
443
444 while_node.ReplaceWith(forever);
445 }
446 else {
447 // we want to delete the when_node, it serves
448 // not purpose! (another function is in charge
449 // of deleting; we just mark the node as unknown)
450 Data& data = while_node.GetData();
451 data.f_type = NODE_UNKNOWN;
452 }
453 }
454 }
455
456
Do(NodePtr & do_node)457 void IntOptimizer::Do(NodePtr& do_node)
458 {
459 int max = do_node.GetChildCount();
460 if(max != 2) {
461 return;
462 }
463
464 NodePtr& condition = do_node.GetChild(1);
465 Data& data = condition.GetData();
466 if(data.ToBoolean()) {
467 if(data.f_type == NODE_TRUE) {
468 // TODO:
469 // Whenever we detect a forever loop we
470 // need to check whether it includes some
471 // break. If there isn't a break, we should
472 // err about it. It is likely a bad one!
473 // [except if the function returns Never]
474 //
475 // create a forever loop
476 NodePtr forever;
477 forever.CreateNode(NODE_DIRECTIVE_LIST);
478 forever.CopyInputInfo(do_node);
479
480 NodePtr label;
481 label.CreateNode(NODE_LABEL);
482 label.CopyInputInfo(do_node);
483 Data& label_data = label.GetData();
484 Label(label_data.f_str);
485 forever.AddChild(label);
486
487 NodePtr list = do_node.GetChild(0);
488 do_node.DeleteChild(0);
489 forever.AddChild(list);
490
491 NodePtr goto_label;
492 goto_label.CreateNode(NODE_GOTO);
493 goto_label.CopyInputInfo(do_node);
494 Data& goto_data = goto_label.GetData();
495 goto_data.f_str = label_data.f_str;
496 forever.AddChild(goto_label);
497
498 do_node.ReplaceWith(forever);
499 }
500 else {
501 // in this case, we simply run the
502 // directives once
503 NodePtr list = do_node.GetChild(0);
504 do_node.DeleteChild(0);
505 do_node.ReplaceWith(do_node.GetChild(0));
506 }
507 }
508 }
509
510
Assignment(NodePtr & assignment)511 void IntOptimizer::Assignment(NodePtr& assignment)
512 {
513 if(assignment.GetChildCount() != 2) {
514 return;
515 }
516
517 NodePtr left = assignment.GetChild(0);
518 NodePtr& right = assignment.GetChild(1);
519
520 Data& ldata = left.GetData();
521 Data& rdata = right.GetData();
522
523 if(ldata.f_type == NODE_IDENTIFIER
524 && rdata.f_type == NODE_IDENTIFIER
525 && ldata.f_str == rdata.f_str) {
526 // TODO: fix the parenting whenever we copy a
527 // node in another! What we really need
528 // is a recurcive function which reparents
529 // all the children once in a while...
530 assignment.DeleteChild(0);
531 assignment.ReplaceWith(left);
532 // The following is valid ONLY if the offset is up to date
533 //assignment.GetParent().SetChild(assignment.GetOffset(), left);
534 }
535 }
536
537
AssignmentAdd(NodePtr & assignment)538 void IntOptimizer::AssignmentAdd(NodePtr& assignment)
539 {
540 // a += 0 -> a
541 // a -= 0 -> a
542 if(assignment.GetChildCount() != 2) {
543 return;
544 }
545
546 NodePtr& right = assignment.GetChild(1);
547 Data& data = right.GetData();
548 if(data.f_type == NODE_INT64) {
549 if(data.f_int.Get() == 0) {
550 NodePtr left = assignment.GetChild(0);
551 assignment.DeleteChild(0);
552 assignment.ReplaceWith(left);
553 }
554 }
555 else if(data.f_type == NODE_FLOAT64) {
556 if(data.f_float.Get() == 0) {
557 NodePtr left = assignment.GetChild(0);
558 assignment.DeleteChild(0);
559 assignment.ReplaceWith(left);
560 }
561 }
562 }
563
564
AssignmentMultiply(NodePtr & assignment)565 void IntOptimizer::AssignmentMultiply(NodePtr& assignment)
566 {
567 // a *= 0 -> 0
568 // a *= 1 -> a
569 if(assignment.GetChildCount() != 2) {
570 return;
571 }
572
573 NodePtr right = assignment.GetChild(1);
574 Data& data = right.GetData();
575 if(data.f_type == NODE_INT64) {
576 if(data.f_int.Get() == 0) {
577 assignment.DeleteChild(1);
578 assignment.ReplaceWith(right);
579 }
580 else if(data.f_int.Get() == 1) {
581 NodePtr left = assignment.GetChild(0);
582 assignment.DeleteChild(0);
583 assignment.ReplaceWith(left);
584 }
585 }
586 else if(data.f_type == NODE_FLOAT64) {
587 if(data.f_float.Get() == 0.0) {
588 assignment.DeleteChild(1);
589 assignment.ReplaceWith(right);
590 }
591 else if(data.f_float.Get() == 1.0) {
592 NodePtr left = assignment.GetChild(0);
593 assignment.DeleteChild(0);
594 assignment.ReplaceWith(left);
595 }
596 }
597 }
598
599
AssignmentDivide(NodePtr & assignment)600 void IntOptimizer::AssignmentDivide(NodePtr& assignment)
601 {
602 // a /= 1 -> a
603 // a /= 0 -> ERROR
604 if(assignment.GetChildCount() != 2) {
605 return;
606 }
607
608 NodePtr& right = assignment.GetChild(1);
609 Data& data = right.GetData();
610 if(data.f_type == NODE_INT64) {
611 if(data.f_int.Get() == 0) {
612 f_error_stream->ErrMsg(AS_ERR_DIVIDE_BY_ZERO, right, "dividing by zero is illegal");
613 f_errcnt++;
614 }
615 else if(data.f_int.Get() == 1) {
616 NodePtr left = assignment.GetChild(0);
617 assignment.DeleteChild(0);
618 assignment.ReplaceWith(left);
619 }
620 }
621 else if(data.f_type == NODE_FLOAT64) {
622 if(data.f_float.Get() == 0.0) {
623 f_error_stream->ErrMsg(AS_ERR_DIVIDE_BY_ZERO, right, "dividing by zero is illegal");
624 f_errcnt++;
625 }
626 else if(data.f_float.Get() == 1.0) {
627 NodePtr left = assignment.GetChild(0);
628 assignment.DeleteChild(0);
629 assignment.ReplaceWith(left);
630 }
631 }
632 }
633
634
AssignmentModulo(NodePtr & assignment)635 void IntOptimizer::AssignmentModulo(NodePtr& assignment)
636 {
637 // a %= 1 -> a
638 // a %= 0 -> ERROR
639 if(assignment.GetChildCount() != 2) {
640 return;
641 }
642
643 NodePtr& right = assignment.GetChild(1);
644 Data& data = right.GetData();
645 if(data.f_type == NODE_INT64) {
646 if(data.f_int.Get() == 0) {
647 f_error_stream->ErrMsg(AS_ERR_DIVIDE_BY_ZERO, right, "modulo by zero is illegal");
648 f_errcnt++;
649 }
650 }
651 else if(data.f_type == NODE_FLOAT64) {
652 if(data.f_float.Get() == 0.0) {
653 f_error_stream->ErrMsg(AS_ERR_DIVIDE_BY_ZERO, right, "modulo by zero is illegal");
654 f_errcnt++;
655 }
656 }
657 }
658
659
660
661 // TODO: all arithmetic operations need to be checked for overflows...
662 // toBoolean(NaN) == false
663
BitwiseNot(NodePtr & bitwise_not)664 void IntOptimizer::BitwiseNot(NodePtr& bitwise_not)
665 {
666 if(bitwise_not.GetChildCount() != 1) {
667 return;
668 }
669 Data& result = bitwise_not.GetData();
670
671 NodePtr child = bitwise_not.GetChild(0);
672 Data data = child.GetData();
673 if(data.ToNumber()) {
674 result.f_type = data.f_type;
675 if(data.f_type == NODE_INT64) {
676 result.f_int.Set(~data.f_int.Get());
677 }
678 else {
679 // ECMAScript version 4 says we can do this with floats!
680 result.f_float.Set(~((int64_t) data.f_float.Get() & 0x0FFFFFFFF));
681 }
682 }
683 else {
684 // We assume that the expression was already
685 // compiled and thus identifiers which were
686 // constants have been replaced already.
687 return;
688 }
689
690 // we don't need our child anymore
691 bitwise_not.DeleteChild(0);
692 }
693
694
LogicalNot(NodePtr & logical_not)695 void IntOptimizer::LogicalNot(NodePtr& logical_not)
696 {
697 if(logical_not.GetChildCount() != 1) {
698 return;
699 }
700 Data& result = logical_not.GetData();
701
702 NodePtr child = logical_not.GetChild(0);
703 Data data = child.GetData();
704 if(data.ToBoolean()) {
705 if(data.f_type == NODE_TRUE) {
706 result.f_type = NODE_FALSE;
707 }
708 else {
709 result.f_type = NODE_TRUE;
710 }
711 }
712 else {
713 if(data.f_type == NODE_LOGICAL_NOT) {
714 // Reduce !!expr to expr
715 // TODO:
716 // we lose the convertion of boolean...
717 // we may want to reconsider this optimization!
718 NodePtr expr = child.GetChild(0);
719 child.DeleteChild(0);
720 logical_not.ReplaceWith(expr);
721 }
722 // We assume that the expression was already
723 // compiled and thus identifiers which were
724 // constants have been replaced already.
725 return;
726 }
727
728 // we don't need our child anymore
729 logical_not.DeleteChild(0);
730 }
731
732
Decrement(NodePtr & decrement)733 void IntOptimizer::Decrement(NodePtr& decrement)
734 {
735 if(decrement.GetChildCount() != 1) {
736 return;
737 }
738 Data& result = decrement.GetData();
739
740 NodePtr child = decrement.GetChild(0);
741 Data data = child.GetData();
742 if(data.ToNumber()) {
743 if(data.f_type == NODE_INT64) {
744 result.f_int.Set(data.f_int.Get() - 1);
745 }
746 else {
747 result.f_float.Set(data.f_float.Get() - 1.0);
748 }
749 }
750 else {
751 // We assume that the expression was already
752 // compiled and thus identifiers which were
753 // constants have been replaced already.
754 return;
755 }
756
757 result.f_type = data.f_type;
758
759 // we don't need our child anymore
760 decrement.DeleteChild(0);
761 }
762
763
Increment(NodePtr & increment)764 void IntOptimizer::Increment(NodePtr& increment)
765 {
766 if(increment.GetChildCount() != 1) {
767 return;
768 }
769 Data& result = increment.GetData();
770
771 NodePtr child = increment.GetChild(0);
772 Data data = child.GetData();
773 if(data.ToNumber()) {
774 if(data.f_type == NODE_INT64) {
775 result.f_int.Set(data.f_int.Get() + 1);
776 }
777 else {
778 result.f_float.Set(data.f_float.Get() + 1.0);
779 }
780 }
781 else {
782 // We assume that the expression was already
783 // compiled and thus identifiers which were
784 // constants have been replaced already.
785 return;
786 }
787
788 result.f_type = data.f_type;
789
790 // we don't need our child anymore
791 increment.DeleteChild(0);
792 }
793
794
Power(NodePtr & power)795 void IntOptimizer::Power(NodePtr& power)
796 {
797 if(power.GetChildCount() != 2) {
798 return;
799 }
800
801 // in case we reduce, we may use this
802 Data& power_data = power.GetData();
803
804 NodePtr lchild = power.GetChild(0);
805 Data left = lchild.GetData();
806
807 NodePtr rchild = power.GetChild(1);
808 Data right = rchild.GetData();
809
810 if(!right.ToNumber()) {
811 // Reduce the following
812 // 0 ** b = 0 (we can't garantee that b <> 0, we can't do it)
813 // 1 ** b = 1
814 if(!left.ToNumber()) {
815 return;
816 }
817 if(left.f_type == NODE_INT64) {
818 if(left.f_int.Get() == 1) {
819 if(rchild.HasSideEffects()) {
820 power.DeleteChild(0);
821 power.DeleteChild(1);
822 power.AddChild(rchild);
823 power.AddChild(lchild);
824 power_data.f_type = NODE_LIST;
825 }
826 else {
827 power.DeleteChild(0);
828 power.ReplaceWith(lchild);
829 }
830 return;
831 }
832 }
833 else {
834 if(left.f_float.Get() == 1.0) {
835 if(rchild.HasSideEffects()) {
836 power.DeleteChild(0);
837 power.DeleteChild(1);
838 power.AddChild(rchild);
839 power.AddChild(lchild);
840 power_data.f_type = NODE_LIST;
841 }
842 else {
843 power.DeleteChild(0);
844 power.ReplaceWith(lchild);
845 }
846 return;
847 }
848 }
849 return;
850 }
851
852 //
853 // Reduce the following if possible
854 // a ** 0 = 1
855 // a ** 1 = a
856 // a ** 2 = a * a (we don't do this one because 'a' can be a
857 // complex expression which we don't want
858 // to duplicate)
859 //
860 if(right.f_type == NODE_INT64) {
861 if(right.f_int.Get() == 0) {
862 Data& right = rchild.GetData();
863 right.f_int.Set(1LL);
864 // the result is always 1
865 if(lchild.HasSideEffects()) {
866 power_data.f_type = NODE_LIST;
867 return;
868 }
869 power.DeleteChild(1);
870 power.ReplaceWith(rchild);
871 return;
872 }
873 else if(right.f_int.Get() == 1) {
874 power.DeleteChild(0);
875 power.ReplaceWith(lchild);
876 return;
877 }
878 }
879 else {
880 if(right.f_float.Get() == 0.0) {
881 Data& right = rchild.GetData();
882 right.f_float.Set(1.0);
883 // the result is always 1
884 if(lchild.HasSideEffects()) {
885 power_data.f_type = NODE_LIST;
886 return;
887 }
888 power.DeleteChild(1);
889 power.ReplaceWith(rchild);
890 return;
891 }
892 else if(right.f_float.Get() == 1.0) {
893 power.DeleteChild(0);
894 power.ReplaceWith(lchild);
895 return;
896 }
897 }
898
899 if(!left.ToNumber()) {
900 return;
901 }
902
903 Data& result = power.GetData();
904
905 if(left.f_type == NODE_INT64) {
906 if(right.f_type == NODE_INT64) {
907 result.f_type = NODE_INT64;
908 result.f_int.Set((int64_t) pow((double) left.f_int.Get(), (double) right.f_int.Get()));
909 }
910 else {
911 result.f_type = NODE_FLOAT64;
912 result.f_float.Set(pow((double) left.f_int.Get(), right.f_float.Get()));
913 }
914 }
915 else {
916 result.f_type = NODE_FLOAT64;
917 if(right.f_type == NODE_INT64) {
918 result.f_float.Set(pow(left.f_float.Get(), (double) right.f_int.Get()));
919 }
920 else {
921 result.f_float.Set(pow(left.f_float.Get(), right.f_float.Get()));
922 }
923 }
924
925 // we don't need any of these children anymore
926 power.DeleteChild(1);
927 power.DeleteChild(0);
928 }
929
930
931
Multiply(NodePtr & multiply)932 void IntOptimizer::Multiply(NodePtr& multiply)
933 {
934 int64_t itotal;
935 double ftotal;
936 node_t type;
937 int idx, max;
938 bool constant;
939 NodePtr zero;
940
941 // Reduce
942 // a * 0 = 0
943 // a * 1 = a
944
945 // NOTE: we should also be able to optimize -1 to a simple
946 // negate; this is not very useful for Flash though
947 // since it doesn't even have a negate (we need to
948 // use 0 - expr anyway)
949
950 constant = true;
951 max = multiply.GetChildCount();
952 for(idx = 0; idx < max && max > 1; ++idx) {
953 NodePtr& child = multiply.GetChild(idx);
954 Data data = child.GetData();
955 if(data.ToNumber()) {
956 if(data.f_type == NODE_INT64) {
957 if(data.f_int.Get() == 0) {
958 // anything else won't matter
959 // (except function calls with
960 // side effects)
961 if(!zero.HasNode()) {
962 zero = child;
963 }
964 }
965 else if(data.f_int.Get() == 1) {
966 // ignore this child
967 multiply.DeleteChild(idx);
968 --idx;
969 --max;
970 }
971 }
972 else {
973 if(data.f_float.Get() == 0.0) {
974 // anything else won't matter
975 // (except function calls with
976 // side effects)
977 zero = child;
978 }
979 else if(data.f_float.Get() == 1.0) {
980 // ignore this child
981 multiply.DeleteChild(idx);
982 --idx;
983 --max;
984 }
985 }
986 }
987 else {
988 constant = false;
989 }
990 }
991
992 if(zero.HasNode() && max > 1) {
993 max = multiply.GetChildCount();
994 for(idx = 0; idx < max; ++idx) {
995 NodePtr& child = multiply.GetChild(idx);
996 if(!child.HasSideEffects()
997 && !child.SameAs(zero)) {
998 multiply.DeleteChild(idx);
999 --idx;
1000 --max;
1001 }
1002 }
1003 }
1004
1005 if(max == 1) {
1006 // Ha! We deleted many 1's or everything but one
1007 // zero; remove the multiplication and just leave
1008 // the other member or the zero
1009 NodePtr expr = multiply.GetChild(0);
1010 multiply.DeleteChild(0);
1011 multiply.ReplaceWith(expr);
1012 return;
1013 }
1014
1015 if(!constant) {
1016 return;
1017 }
1018
1019 type = NODE_INT64;
1020 itotal = 1;
1021 ftotal = 1.0;
1022 for(idx = 0; idx < max; ++idx) {
1023 NodePtr child = multiply.GetChild(idx);
1024 Data data = child.GetData();
1025 if(data.ToNumber()) {
1026 if(data.f_type == NODE_INT64) {
1027 if(type == NODE_FLOAT64) {
1028 ftotal *= data.f_int.Get();
1029 }
1030 else {
1031 itotal *= data.f_int.Get();
1032 }
1033 }
1034 else {
1035 if(type == NODE_INT64) {
1036 type = NODE_FLOAT64;
1037 ftotal = itotal * data.f_float.Get();
1038 }
1039 else {
1040 ftotal *= data.f_float.Get();
1041 }
1042 }
1043 }
1044 else {
1045 // we should not come here!
1046 AS_ASSERT(0);
1047 // We assume that the expression was already
1048 // compiled and thus identifiers which were
1049 // constants have been replaced already.
1050 return;
1051 }
1052 }
1053
1054 // if we reach here, we can change the node type
1055 // to NODE_INT64 or NODE_FLOAT64
1056 Data& data = multiply.GetData();
1057 data.f_type = type;
1058 if(type == NODE_INT64) {
1059 data.f_int.Set(itotal);
1060 }
1061 else {
1062 data.f_float.Set(ftotal);
1063 }
1064
1065 // we don't need any of these children anymore
1066 while(max > 0) {
1067 --max;
1068 multiply.DeleteChild(max);
1069 }
1070 }
1071
1072
Divide(NodePtr & divide)1073 void IntOptimizer::Divide(NodePtr& divide)
1074 {
1075 int64_t itotal, idiv;
1076 double ftotal, fdiv;
1077 node_t type;
1078 int idx, max;
1079 bool div0, constant;
1080
1081 // Reduce
1082 // a / 1 = a
1083 // Error
1084 // a / 0
1085
1086 type = NODE_UNKNOWN;
1087 itotal = 0;
1088 ftotal = 0.0;
1089 constant = true;
1090 max = divide.GetChildCount();
1091 for(idx = 0; idx < max; ++idx) {
1092 div0 = false;
1093 NodePtr& child = divide.GetChild(idx);
1094 Data data = child.GetData();
1095 if(data.ToNumber()) {
1096 if(data.f_type == NODE_INT64) {
1097 idiv = data.f_int.Get();
1098 if(idx > 0 && idiv == 1) {
1099 divide.DeleteChild(idx);
1100 --idx;
1101 --max;
1102 }
1103 else if(type == NODE_UNKNOWN) {
1104 type = NODE_INT64;
1105 itotal = idiv;
1106 }
1107 else {
1108 div0 = idiv == 0;
1109 if(!div0) {
1110 if(type == NODE_FLOAT64) {
1111 ftotal /= idiv;
1112 }
1113 else {
1114 itotal /= idiv;
1115 }
1116 }
1117 }
1118 }
1119 else {
1120 fdiv = data.f_float.Get();
1121 if(idx > 0 && fdiv == 1.0) {
1122 divide.DeleteChild(idx);
1123 --idx;
1124 --max;
1125 }
1126 else if(type == NODE_UNKNOWN) {
1127 type = NODE_FLOAT64;
1128 ftotal = fdiv;
1129 }
1130 else {
1131 div0 = fdiv == 0.0;
1132 if(!div0) {
1133 if(type == NODE_INT64) {
1134 type = NODE_FLOAT64;
1135 ftotal = itotal / fdiv;
1136 }
1137 else {
1138 ftotal /= fdiv;
1139 }
1140 }
1141 }
1142 }
1143 }
1144 else {
1145 // We assume that the expression was already
1146 // compiled and thus identifiers which were
1147 // constants have been replaced already.
1148 constant = false;
1149 }
1150 if(div0) {
1151 f_error_stream->ErrMsg(AS_ERR_DIVIDE_BY_ZERO, divide, "dividing by zero is illegal");
1152 f_errcnt++;
1153 }
1154 }
1155
1156 if(max == 1) {
1157 NodePtr expr = divide.GetChild(0);
1158 divide.DeleteChild(0);
1159 divide.ReplaceWith(expr);
1160 return;
1161 }
1162
1163 if(!constant) {
1164 return;
1165 }
1166
1167 // if we reach here, we can change the node type
1168 // to NODE_INT64 or NODE_FLOAT64
1169 Data& data = divide.GetData();
1170 data.f_type = type;
1171 if(type == NODE_INT64) {
1172 data.f_int.Set(itotal);
1173 }
1174 else {
1175 data.f_float.Set(ftotal);
1176 }
1177
1178 // we don't need any of these children anymore
1179 while(max > 0) {
1180 --max;
1181 divide.DeleteChild(max);
1182 }
1183 }
1184
1185
Modulo(NodePtr & modulo)1186 void IntOptimizer::Modulo(NodePtr& modulo)
1187 {
1188 int64_t itotal, idiv;
1189 double ftotal, fdiv;
1190 node_t type;
1191 int idx, max;
1192 bool div0, constant;
1193
1194 // Error
1195 // a % 0
1196
1197 type = NODE_UNKNOWN;
1198 itotal = 0;
1199 ftotal = 0.0;
1200 constant = true;
1201 max = modulo.GetChildCount();
1202 for(idx = 0; idx < max; ++idx) {
1203 div0 = false;
1204 NodePtr& child = modulo.GetChild(idx);
1205 Data data = child.GetData();
1206 if(data.ToNumber()) {
1207 if(data.f_type == NODE_INT64) {
1208 idiv = data.f_int.Get();
1209 if(type == NODE_UNKNOWN) {
1210 type = NODE_INT64;
1211 itotal = idiv;
1212 }
1213 else {
1214 div0 = idiv == 0;
1215 if(!div0) {
1216 if(type == NODE_FLOAT64) {
1217 ftotal = fmod(ftotal, idiv);
1218 }
1219 else {
1220 itotal %= idiv;
1221 }
1222 }
1223 }
1224 }
1225 else {
1226 fdiv = data.f_float.Get();
1227 if(type == NODE_UNKNOWN) {
1228 type = NODE_FLOAT64;
1229 ftotal = fdiv;
1230 }
1231 else {
1232 div0 = fdiv != 0;
1233 if(!div0) {
1234 if(type == NODE_INT64) {
1235 type = NODE_FLOAT64;
1236 ftotal = fmod(itotal, fdiv);
1237 }
1238 else {
1239 ftotal = fmod(ftotal, fdiv);
1240 }
1241 }
1242 }
1243 }
1244 }
1245 else {
1246 // We assume that the expression was already
1247 // compiled and thus identifiers which were
1248 // constants have been replaced already.
1249 constant = false;
1250 }
1251 if(div0) {
1252 f_error_stream->ErrMsg(AS_ERR_DIVIDE_BY_ZERO, modulo, "dividing by zero is illegal");
1253 f_errcnt++;
1254 }
1255 }
1256
1257 if(!constant) {
1258 return;
1259 }
1260
1261 // if we reach here, we can change the node type
1262 // to NODE_INT64 or NODE_FLOAT64
1263 Data& data = modulo.GetData();
1264 data.f_type = type;
1265 if(type == NODE_INT64) {
1266 data.f_int.Set(itotal);
1267 }
1268 else {
1269 data.f_float.Set(ftotal);
1270 }
1271
1272 // we don't need any of these children anymore
1273 while(max > 0) {
1274 --max;
1275 modulo.DeleteChild(max);
1276 }
1277 }
1278
1279
Add(NodePtr & add)1280 void IntOptimizer::Add(NodePtr& add)
1281 {
1282 int64_t itotal;
1283 double ftotal;
1284 node_t type;
1285 int idx, max;
1286 bool constant;
1287
1288 // Reduce:
1289 // a + 0 = a
1290 // 0 + a = a
1291
1292 constant = true;
1293 type = NODE_INT64;
1294 itotal = 0;
1295 ftotal = 0.0;
1296 max = add.GetChildCount();
1297 for(idx = 0; idx < max; ++idx) {
1298 NodePtr child = add.GetChild(idx);
1299 Data data = child.GetData();
1300 if(data.ToNumber()) {
1301 if(data.f_type == NODE_INT64) {
1302 if(data.f_int.Get() == 0) {
1303 add.DeleteChild(idx);
1304 --idx;
1305 --max;
1306 }
1307 else if(type == NODE_FLOAT64) {
1308 ftotal += data.f_int.Get();
1309 }
1310 else {
1311 itotal += data.f_int.Get();
1312 }
1313 }
1314 else {
1315 // special case where we still want
1316 // to force the value to a floating
1317 // point value! (1 + 0.0 -> 1.0)
1318 if(type == NODE_INT64) {
1319 type = NODE_FLOAT64;
1320 ftotal = itotal + data.f_float.Get();
1321 }
1322 else {
1323 ftotal += data.f_float.Get();
1324 }
1325 if(data.f_float.Get() == 0.0) {
1326 add.DeleteChild(idx);
1327 --idx;
1328 --max;
1329 }
1330 }
1331 }
1332 else {
1333 // We assume that the expression was already
1334 // compiled and thus identifiers which were
1335 // constants have been replaced already.
1336 constant = false;
1337 }
1338 }
1339
1340 // max is 1 when the user used positive or added zero
1341 if(max == 1) {
1342 NodePtr expr = add.GetChild(0);
1343 add.DeleteChild(0);
1344 add.ReplaceWith(expr);
1345 return;
1346 }
1347
1348 if(!constant) {
1349 return;
1350 }
1351
1352 // if we reach here, we can change the node type
1353 // to NODE_INT64 or NODE_FLOAT64
1354 Data& data = add.GetData();
1355 data.f_type = type;
1356 if(type == NODE_INT64) {
1357 data.f_int.Set(itotal);
1358 }
1359 else {
1360 data.f_float.Set(ftotal);
1361 }
1362
1363 // we don't need any of these children anymore
1364 while(max > 0) {
1365 --max;
1366 add.DeleteChild(max);
1367 }
1368 }
1369
1370
Subtract(NodePtr & subtract)1371 void IntOptimizer::Subtract(NodePtr& subtract)
1372 {
1373 int64_t itotal;
1374 double ftotal;
1375 node_t type;
1376 int idx, max, start_max;
1377 bool constant;
1378
1379 // Reduce:
1380 // a - 0 = a
1381
1382 type = NODE_UNKNOWN;
1383 itotal = 0;
1384 ftotal = 0.0;
1385 constant = true;
1386 start_max = max = subtract.GetChildCount();
1387 for(idx = 0; idx < max; ++idx) {
1388 NodePtr& child = subtract.GetChild(idx);
1389 Data data = child.GetData();
1390 if(data.ToNumber()) {
1391 if(data.f_type == NODE_INT64) {
1392 if(idx != 0 && data.f_int.Get() == 0) {
1393 subtract.DeleteChild(idx);
1394 --idx;
1395 --max;
1396 }
1397 else if(type == NODE_UNKNOWN) {
1398 type = NODE_INT64;
1399 itotal = data.f_int.Get();
1400 }
1401 else if(type == NODE_FLOAT64) {
1402 ftotal -= data.f_int.Get();
1403 }
1404 else {
1405 itotal -= data.f_int.Get();
1406 }
1407 }
1408 else {
1409 if(idx != 0 && data.f_int.Get() == 0) {
1410 subtract.DeleteChild(idx);
1411 --idx;
1412 --max;
1413 }
1414 else if(type == NODE_UNKNOWN) {
1415 type = NODE_FLOAT64;
1416 ftotal = data.f_float.Get();
1417 }
1418 else if(type == NODE_INT64) {
1419 type = NODE_FLOAT64;
1420 ftotal = itotal - data.f_float.Get();
1421 }
1422 else {
1423 ftotal -= data.f_float.Get();
1424 }
1425 }
1426 }
1427 else {
1428 // We assume that the expression was already
1429 // compiled and thus identifiers which were
1430 // constants have been replaced already.
1431 constant = false;
1432 }
1433 }
1434
1435 // cancellation of the operation? (i.e. a - 0)
1436 if(start_max > 1 && max == 1) {
1437 NodePtr expr = subtract.GetChild(0);
1438 subtract.DeleteChild(0);
1439 subtract.ReplaceWith(expr);
1440 return;
1441 }
1442
1443 if(!constant) {
1444 return;
1445 }
1446
1447 // subtraction or negation?
1448 if(max == 1) {
1449 if(type == NODE_INT64) {
1450 itotal = -itotal;
1451 }
1452 else {
1453 ftotal = -ftotal;
1454 }
1455 }
1456
1457 // if we reach here, we can change the node type
1458 // to NODE_INT64 or NODE_FLOAT64
1459 Data& data = subtract.GetData();
1460 data.f_type = type;
1461 if(type == NODE_INT64) {
1462 data.f_int.Set(itotal);
1463 }
1464 else {
1465 data.f_float.Set(ftotal);
1466 }
1467
1468 // we don't need any of these children anymore
1469 while(max > 0) {
1470 --max;
1471 subtract.DeleteChild(max);
1472 }
1473 }
1474
1475
1476
ShiftLeft(NodePtr & shift_left)1477 void IntOptimizer::ShiftLeft(NodePtr& shift_left)
1478 {
1479 int64_t itotal;
1480 node_t type;
1481 int idx, max;
1482
1483 type = NODE_UNKNOWN;
1484 itotal = 0;
1485 max = shift_left.GetChildCount();
1486 for(idx = 0; idx < max; ++idx) {
1487 NodePtr child = shift_left.GetChild(idx);
1488 Data data = child.GetData();
1489 if(data.ToNumber()) {
1490 if(data.f_type == NODE_INT64) {
1491 if(type == NODE_UNKNOWN) {
1492 itotal = data.f_int.Get();
1493 }
1494 else {
1495 itotal <<= data.f_int.Get() & 0x3F;
1496 }
1497 type = NODE_INT64;
1498 }
1499 else {
1500 if(type == NODE_UNKNOWN) {
1501 itotal = (int32_t) data.f_float.Get();
1502 }
1503 else {
1504 itotal <<= (int32_t) data.f_float.Get() & 0x1F;
1505 }
1506 type = NODE_FLOAT64;
1507 }
1508 }
1509 else {
1510 // We assume that the expression was already
1511 // compiled and thus identifiers which were
1512 // constants have been replaced already.
1513 return;
1514 }
1515 }
1516
1517 // if we reach here, we can change the node type
1518 // to NODE_INT64 or NODE_FLOAT64
1519 Data& data = shift_left.GetData();
1520 data.f_type = type;
1521 if(type == NODE_INT64) {
1522 data.f_int.Set(itotal);
1523 }
1524 else {
1525 data.f_float.Set(itotal);
1526 }
1527
1528 // we don't need any of these children anymore
1529 while(max > 0) {
1530 --max;
1531 shift_left.DeleteChild(max);
1532 }
1533 }
1534
1535
ShiftRight(NodePtr & shift_right)1536 void IntOptimizer::ShiftRight(NodePtr& shift_right)
1537 {
1538 int64_t itotal;
1539 node_t type;
1540 int idx, max;
1541
1542 type = NODE_UNKNOWN;
1543 itotal = 0;
1544 max = shift_right.GetChildCount();
1545 for(idx = 0; idx < max; ++idx) {
1546 NodePtr child = shift_right.GetChild(idx);
1547 Data data = child.GetData();
1548 if(data.ToNumber()) {
1549 if(data.f_type == NODE_INT64) {
1550 if(type == NODE_UNKNOWN) {
1551 itotal = data.f_int.Get();
1552 }
1553 else {
1554 itotal >>= data.f_int.Get() & 0x3F;
1555 }
1556 type = NODE_INT64;
1557 }
1558 else {
1559 if(type == NODE_UNKNOWN) {
1560 itotal = (int32_t) data.f_float.Get();
1561 }
1562 else {
1563 itotal >>= (int32_t) data.f_float.Get() & 0x1F;
1564 }
1565 type = NODE_FLOAT64;
1566 }
1567 }
1568 else {
1569 // We assume that the expression was already
1570 // compiled and thus identifiers which were
1571 // constants have been replaced already.
1572 return;
1573 }
1574 }
1575
1576 // if we reach here, we can change the node type
1577 // to NODE_INT64 or NODE_FLOAT64
1578 Data& data = shift_right.GetData();
1579 data.f_type = type;
1580 if(type == NODE_INT64) {
1581 data.f_int.Set(itotal);
1582 }
1583 else {
1584 data.f_float.Set(itotal);
1585 }
1586
1587 // we don't need any of these children anymore
1588 while(max > 0) {
1589 --max;
1590 shift_right.DeleteChild(max);
1591 }
1592 }
1593
1594
1595
ShiftRightUnsigned(NodePtr & shift_right_unsigned)1596 void IntOptimizer::ShiftRightUnsigned(NodePtr& shift_right_unsigned)
1597 {
1598 uint64_t itotal;
1599 node_t type;
1600 int idx, max;
1601
1602 type = NODE_UNKNOWN;
1603 itotal = 0;
1604 max = shift_right_unsigned.GetChildCount();
1605 for(idx = 0; idx < max; ++idx) {
1606 NodePtr child = shift_right_unsigned.GetChild(idx);
1607 Data data = child.GetData();
1608 if(data.ToNumber()) {
1609 if(data.f_type == NODE_INT64) {
1610 if(type == NODE_UNKNOWN) {
1611 itotal = data.f_int.Get();
1612 }
1613 else {
1614 itotal >>= data.f_int.Get() & 0x3F;
1615 }
1616 type = NODE_INT64;
1617 }
1618 else {
1619 if(type == NODE_UNKNOWN) {
1620 itotal = (int32_t) data.f_float.Get();
1621 }
1622 else {
1623 itotal >>= (int32_t) data.f_float.Get() & 0x1F;
1624 }
1625 type = NODE_FLOAT64;
1626 }
1627 }
1628 else {
1629 // We assume that the expression was already
1630 // compiled and thus identifiers which were
1631 // constants have been replaced already.
1632 return;
1633 }
1634 }
1635
1636 // if we reach here, we can change the node type
1637 // to NODE_INT64 or NODE_FLOAT64
1638 Data& data = shift_right_unsigned.GetData();
1639 data.f_type = type;
1640 if(type == NODE_INT64) {
1641 data.f_int.Set(itotal);
1642 }
1643 else {
1644 data.f_float.Set(itotal);
1645 }
1646
1647 // we don't need any of these children anymore
1648 while(max > 0) {
1649 --max;
1650 shift_right_unsigned.DeleteChild(max);
1651 }
1652 }
1653
1654
RotateLeft(NodePtr & rotate_left)1655 void IntOptimizer::RotateLeft(NodePtr& rotate_left)
1656 {
1657 uint64_t itotal;
1658 node_t type;
1659 int idx, max, count;
1660
1661 type = NODE_UNKNOWN;
1662 itotal = 0;
1663 max = rotate_left.GetChildCount();
1664 for(idx = 0; idx < max; ++idx) {
1665 NodePtr child = rotate_left.GetChild(idx);
1666 Data data = child.GetData();
1667 if(data.ToNumber()) {
1668 if(data.f_type == NODE_INT64) {
1669 if(type == NODE_UNKNOWN) {
1670 itotal = data.f_int.Get();
1671 }
1672 else {
1673 count = data.f_int.Get() & 0x3F;
1674 if(count != 0) {
1675 itotal = (itotal << count) | (itotal >> (64 - count));
1676 }
1677 }
1678 type = NODE_INT64;
1679 }
1680 else {
1681 if(type == NODE_UNKNOWN) {
1682 itotal = (int32_t) data.f_float.Get();
1683 }
1684 else {
1685 count = (int32_t) data.f_float.Get() & 0x1F;
1686 if(count != 0) {
1687 itotal = ((itotal << count) | (itotal >> (64 - count)));
1688 }
1689 }
1690 type = NODE_FLOAT64;
1691 }
1692 }
1693 else {
1694 // We assume that the expression was already
1695 // compiled and thus identifiers which were
1696 // constants have been replaced already.
1697 return;
1698 }
1699 }
1700
1701 // if we reach here, we can change the node type
1702 // to NODE_INT64 or NODE_FLOAT64
1703 Data& data = rotate_left.GetData();
1704 data.f_type = type;
1705 if(type == NODE_INT64) {
1706 data.f_int.Set(itotal);
1707 }
1708 else {
1709 data.f_float.Set(itotal);
1710 }
1711
1712 // we don't need any of these children anymore
1713 while(max > 0) {
1714 --max;
1715 rotate_left.DeleteChild(max);
1716 }
1717 }
1718
1719
1720
RotateRight(NodePtr & rotate_right)1721 void IntOptimizer::RotateRight(NodePtr& rotate_right)
1722 {
1723 uint64_t itotal;
1724 node_t type;
1725 int idx, max, count;
1726
1727 type = NODE_UNKNOWN;
1728 itotal = 0;
1729 max = rotate_right.GetChildCount();
1730 for(idx = 0; idx < max; ++idx) {
1731 NodePtr child = rotate_right.GetChild(idx);
1732 Data data = child.GetData();
1733 if(data.ToNumber()) {
1734 if(data.f_type == NODE_INT64) {
1735 if(type == NODE_UNKNOWN) {
1736 itotal = data.f_int.Get();
1737 }
1738 else {
1739 count = data.f_int.Get() & 0x3F;
1740 if(count != 0) {
1741 itotal = (itotal >> count) | (itotal << (64 - count));
1742 }
1743 }
1744 type = NODE_INT64;
1745 }
1746 else {
1747 if(type == NODE_UNKNOWN) {
1748 itotal = (int32_t) data.f_float.Get();
1749 }
1750 else {
1751 count = (int32_t) data.f_float.Get() & 0x1F;
1752 if(count != 0) {
1753 itotal = ((itotal >> count) | (itotal << (64 - count)));
1754 }
1755 }
1756 type = NODE_FLOAT64;
1757 }
1758 }
1759 else {
1760 // We assume that the expression was already
1761 // compiled and thus identifiers which were
1762 // constants have been replaced already.
1763 return;
1764 }
1765 }
1766
1767 // if we reach here, we can change the node type
1768 // to NODE_INT64 or NODE_FLOAT64
1769 Data& data = rotate_right.GetData();
1770 data.f_type = type;
1771 if(type == NODE_INT64) {
1772 data.f_int.Set(itotal);
1773 }
1774 else {
1775 data.f_float.Set(itotal);
1776 }
1777
1778 // we don't need any of these children anymore
1779 while(max > 0) {
1780 --max;
1781 rotate_right.DeleteChild(max);
1782 }
1783 }
1784
1785
1786
1787 // returns:
1788 // 0 - equal
1789 // -1 - left < right
1790 // 1 - left > right
1791 // 2 - unordered (left or right is a NaN)
1792 // -2 - error (can't compare)
Compare(NodePtr & relational)1793 int IntOptimizer::Compare(NodePtr& relational)
1794 {
1795 if(relational.GetChildCount() != 2) {
1796 return -2;
1797 }
1798
1799 NodePtr child = relational.GetChild(0);
1800 Data left = child.GetData();
1801
1802 child = relational.GetChild(1);
1803 Data right = child.GetData();
1804
1805 if(left.f_type == NODE_STRING
1806 && right.f_type == NODE_STRING) {
1807 return left.f_str.Compare(right.f_str);
1808 }
1809
1810 if(!left.ToNumber()) {
1811 return -2;
1812 }
1813 if(!right.ToNumber()) {
1814 return -2;
1815 }
1816
1817 if(left.f_type == NODE_INT64) {
1818 if(right.f_type == NODE_INT64) {
1819 int64_t r = left.f_int.Get() - right.f_int.Get();
1820 if(r == 0) {
1821 return 0;
1822 }
1823 return r < 0 ? -1 : 1;
1824 }
1825 else {
1826 if(isnan(right.f_float.Get())) {
1827 return 2;
1828 }
1829 int inf = isinf(right.f_float.Get());
1830 if(inf != 0) {
1831 return -inf;
1832 }
1833 double r = left.f_int.Get() - right.f_float.Get();
1834 if(r == 0.0) {
1835 return 0;
1836 }
1837 return r < 0.0 ? -1 : 1;
1838 }
1839 }
1840 else {
1841 if(isnan(left.f_float.Get())) {
1842 return 2;
1843 }
1844 if(right.f_type == NODE_INT64) {
1845 int inf = isinf(left.f_float.Get());
1846 if(inf != 0) {
1847 return inf;
1848 }
1849 double r = left.f_float.Get() - right.f_int.Get();
1850 if(r == 0.0) {
1851 return 0;
1852 }
1853 return r < 0.0 ? -1 : 1;
1854 }
1855 else {
1856 if(isnan(right.f_float.Get())) {
1857 return 2;
1858 }
1859 int linf = isinf(left.f_float.Get());
1860 int rinf = isinf(right.f_float.Get());
1861 if(linf != 0 || rinf != 0) {
1862 if(linf == rinf) {
1863 return 0;
1864 }
1865 return linf < rinf ? -1 : 1;
1866 }
1867 double r = left.f_float.Get() - right.f_float.Get();
1868 if(r == 0.0) {
1869 return 0;
1870 }
1871 return r < 0.0 ? -1 : 1;
1872 }
1873 }
1874 }
1875
1876
1877
Less(NodePtr & less)1878 void IntOptimizer::Less(NodePtr& less)
1879 {
1880 long r = Compare(less);
1881 if(r == -2) {
1882 return;
1883 }
1884
1885 if(r == 2) {
1886 // ???
1887 return;
1888 }
1889
1890 Data& result = less.GetData();
1891 result.f_type = r < 0 ? NODE_TRUE : NODE_FALSE;
1892
1893 less.DeleteChild(1);
1894 less.DeleteChild(0);
1895 }
1896
1897
LessEqual(NodePtr & less_equal)1898 void IntOptimizer::LessEqual(NodePtr& less_equal)
1899 {
1900 long r = Compare(less_equal);
1901 if(r == -2) {
1902 return;
1903 }
1904
1905 if(r == 2) {
1906 // ???
1907 return;
1908 }
1909
1910 Data& result = less_equal.GetData();
1911 result.f_type = r <= 0 ? NODE_TRUE : NODE_FALSE;
1912
1913 less_equal.DeleteChild(1);
1914 less_equal.DeleteChild(0);
1915 }
1916
1917
Greater(NodePtr & greater)1918 void IntOptimizer::Greater(NodePtr& greater)
1919 {
1920 long r = Compare(greater);
1921 if(r == -2) {
1922 return;
1923 }
1924
1925 if(r == 2) {
1926 // ???
1927 return;
1928 }
1929
1930 Data& result = greater.GetData();
1931 result.f_type = r > 0 ? NODE_TRUE : NODE_FALSE;
1932
1933 greater.DeleteChild(1);
1934 greater.DeleteChild(0);
1935 }
1936
1937
GreaterEqual(NodePtr & greater_equal)1938 void IntOptimizer::GreaterEqual(NodePtr& greater_equal)
1939 {
1940 long r = Compare(greater_equal);
1941 if(r == -2) {
1942 return;
1943 }
1944
1945 if(r == 2) {
1946 // ???
1947 return;
1948 }
1949
1950 Data& result = greater_equal.GetData();
1951 result.f_type = r >= 0 ? NODE_TRUE : NODE_FALSE;
1952
1953 greater_equal.DeleteChild(1);
1954 greater_equal.DeleteChild(0);
1955 }
1956
1957
Equality(NodePtr & equality,bool strict,bool logical_not)1958 void IntOptimizer::Equality(NodePtr& equality, bool strict, bool logical_not)
1959 {
1960 if(equality.GetChildCount() != 2) {
1961 return;
1962 }
1963
1964 bool result = false;
1965
1966 NodePtr child = equality.GetChild(0);
1967 Data left = child.GetData();
1968
1969 child = equality.GetChild(1);
1970 Data right = child.GetData();
1971
1972 if(strict) { // ===
1973 if((left.f_type == NODE_TRUE || left.f_type == NODE_FALSE)
1974 && (right.f_type == NODE_TRUE || right.f_type == NODE_FALSE)) {
1975 result = left.f_type == right.f_type;
1976 }
1977 else if(left.f_type == NODE_INT64 && right.f_type == NODE_INT64) {
1978 result = left.f_int.Get() == right.f_int.Get();
1979 }
1980 else if(left.f_type == NODE_FLOAT64 && right.f_type == NODE_FLOAT64) {
1981 result = left.f_float.Get() == right.f_float.Get();
1982 }
1983 else if(left.f_type == NODE_INT64 && right.f_type == NODE_FLOAT64) {
1984 result = left.f_int.Get() == right.f_float.Get();
1985 }
1986 else if(left.f_type == NODE_FLOAT64 && right.f_type == NODE_INT64) {
1987 result = left.f_float.Get() == right.f_int.Get();
1988 }
1989 else if(left.f_type == NODE_STRING && right.f_type == NODE_STRING) {
1990 result = left.f_str == right.f_str;
1991 }
1992 else if((left.f_type == NODE_UNDEFINED && right.f_type == NODE_UNDEFINED)
1993 || (left.f_type == NODE_NULL && right.f_type == NODE_NULL)) {
1994 result = true;
1995 }
1996 else if((left.f_type == NODE_NULL && right.f_type == NODE_UNDEFINED)
1997 || (left.f_type == NODE_UNDEFINED && right.f_type == NODE_NULL)) {
1998 result = false;
1999 }
2000 else if((left.f_type == NODE_IDENTIFIER || left.f_type == NODE_VIDENTIFIER)
2001 && (right.f_type == NODE_IDENTIFIER || right.f_type == NODE_VIDENTIFIER)) {
2002 // special case of a === a
2003 if(left.f_str != right.f_str) {
2004 // If not the same, we can't know what the result
2005 // is at compile time.
2006 return;
2007 }
2008 result = true;
2009 }
2010 else {
2011 switch(left.f_type) {
2012 case NODE_INT64:
2013 case NODE_FLOAT64:
2014 case NODE_STRING:
2015 case NODE_NULL:
2016 case NODE_UNDEFINED:
2017 case NODE_TRUE:
2018 case NODE_FALSE:
2019 break;
2020
2021 default:
2022 // undefined at compile time
2023 return;
2024
2025 }
2026 switch(right.f_type) {
2027 case NODE_INT64:
2028 case NODE_FLOAT64:
2029 case NODE_STRING:
2030 case NODE_NULL:
2031 case NODE_UNDEFINED:
2032 case NODE_TRUE:
2033 case NODE_FALSE:
2034 break;
2035
2036 default:
2037 // undefined at compile time
2038 return;
2039
2040 }
2041 // any one of these mix is always false in strict mode
2042 result = false;
2043 }
2044 }
2045 else { // ==
2046 switch(left.f_type) {
2047 case NODE_UNDEFINED:
2048 case NODE_NULL:
2049 switch(right.f_type) {
2050 case NODE_UNDEFINED:
2051 case NODE_NULL:
2052 result = true;
2053 break;
2054
2055 case NODE_INT64:
2056 case NODE_FLOAT64:
2057 case NODE_STRING:
2058 case NODE_TRUE:
2059 case NODE_FALSE:
2060 result = false;
2061 break;
2062
2063 default:
2064 // undefined at compile time
2065 return;
2066
2067 }
2068 break;
2069
2070 case NODE_TRUE:
2071 switch(right.f_type) {
2072 case NODE_TRUE:
2073 result = true;
2074 break;
2075
2076 case NODE_FALSE:
2077 case NODE_STRING:
2078 case NODE_NULL:
2079 case NODE_UNDEFINED:
2080 result = false;
2081 break;
2082
2083 default:
2084 if(!right.ToNumber()) {
2085 // undefined at compile time
2086 return;
2087 }
2088 if(right.f_type == NODE_INT64) {
2089 result = right.f_int.Get() == 1;
2090 }
2091 else {
2092 result = right.f_float.Get() == 1.0;
2093 }
2094 break;
2095
2096 }
2097 break;
2098
2099 case NODE_FALSE:
2100 switch(right.f_type) {
2101 case NODE_TRUE:
2102 case NODE_STRING:
2103 case NODE_NULL:
2104 case NODE_UNDEFINED:
2105 result = false;
2106 break;
2107
2108 case NODE_FALSE:
2109 result = true;
2110 break;
2111
2112 default:
2113 if(!right.ToNumber()) {
2114 // undefined at compile time
2115 return;
2116 }
2117 if(right.f_type == NODE_INT64) {
2118 result = right.f_int.Get() == 0;
2119 }
2120 else {
2121 result = right.f_float.Get() == 0.0;
2122 }
2123 break;
2124
2125 }
2126 break;
2127
2128 case NODE_INT64:
2129 switch(right.f_type) {
2130 case NODE_INT64:
2131 result = left.f_int.Get() == right.f_int.Get();
2132 break;
2133
2134 case NODE_FLOAT64:
2135 result = left.f_int.Get() == right.f_float.Get();
2136 break;
2137
2138 case NODE_TRUE:
2139 result = left.f_int.Get() == 1;
2140 break;
2141
2142 case NODE_FALSE:
2143 result = left.f_int.Get() == 0;
2144 break;
2145
2146 //case NODE_STRING: ...
2147
2148 case NODE_NULL:
2149 case NODE_UNDEFINED:
2150 result = false;
2151 break;
2152
2153 default:
2154 return;
2155
2156 }
2157 break;
2158
2159 case NODE_FLOAT64:
2160 switch(right.f_type) {
2161 case NODE_FLOAT64:
2162 result = left.f_float.Get() == right.f_float.Get();
2163 break;
2164
2165 case NODE_INT64:
2166 result = left.f_float.Get() == right.f_int.Get();
2167 break;
2168
2169 case NODE_TRUE:
2170 result = left.f_float.Get() == 1.0;
2171 break;
2172
2173 case NODE_FALSE:
2174 result = left.f_float.Get() == 0.0;
2175 break;
2176
2177 //case NODE_STRING: ...
2178
2179 case NODE_NULL:
2180 case NODE_UNDEFINED:
2181 result = false;
2182 break;
2183
2184 default:
2185 return;
2186
2187 }
2188 break;
2189
2190 case NODE_STRING:
2191 switch(right.f_type) {
2192 case NODE_STRING:
2193 result = left.f_str == right.f_str;
2194 break;
2195
2196 case NODE_NULL:
2197 case NODE_UNDEFINED:
2198 result = false;
2199 break;
2200
2201 //case NODE_INT64: ...
2202 //case NODE_FLOAT64: ...
2203
2204 default:
2205 return;
2206
2207 }
2208 break;
2209
2210 case NODE_IDENTIFIER:
2211 case NODE_VIDENTIFIER:
2212 if((right.f_type != NODE_IDENTIFIER && right.f_type != NODE_VIDENTIFIER)
2213 || left.f_str != right.f_str) {
2214 return;
2215 }
2216 // special case of a == a
2217 result = true;
2218 break;
2219
2220 default:
2221 // undefined at compile time
2222 return;
2223
2224 }
2225 }
2226
2227 // if we reach here, we can change the node type
2228 // to NODE_INT64 or NODE_FLOAT64
2229 Data& data = equality.GetData();
2230 data.f_type = result ^ logical_not ? NODE_TRUE : NODE_FALSE;
2231
2232 // we don't need any of these children anymore
2233 equality.DeleteChild(1);
2234 equality.DeleteChild(0);
2235 }
2236
2237
2238
BitwiseAnd(NodePtr & bitwise_and)2239 void IntOptimizer::BitwiseAnd(NodePtr& bitwise_and)
2240 {
2241 int64_t itotal;
2242 double ftotal;
2243 node_t type;
2244 int idx, max;
2245 String result;
2246
2247 type = NODE_INT64;
2248 itotal = -1;
2249 ftotal = -1.0;
2250 max = bitwise_and.GetChildCount();
2251 for(idx = 0; idx < max; ++idx) {
2252 NodePtr child = bitwise_and.GetChild(idx);
2253 Data data = child.GetData();
2254 if(data.f_type == NODE_STRING || type == NODE_STRING) {
2255 if(type != NODE_STRING && idx != 0) {
2256 Data value;
2257 value.f_type = type;
2258 if(type == NODE_INT64) {
2259 value.f_int.Set(itotal);
2260 }
2261 else {
2262 value.f_float.Set(ftotal);
2263 }
2264 value.ToString();
2265 result = value.f_str;
2266 }
2267 if(!data.ToString()) {
2268 return;
2269 }
2270 type = NODE_STRING;
2271 result += data.f_str;
2272 }
2273 else if(data.ToNumber()) {
2274 if(data.f_type == NODE_INT64) {
2275 if(type == NODE_INT64) {
2276 itotal &= data.f_int.Get();
2277 }
2278 else {
2279 ftotal = (int32_t) ftotal & (int32_t) data.f_int.Get();
2280 type = NODE_FLOAT64;
2281 }
2282 }
2283 else {
2284 if(type == NODE_INT64) {
2285 type = NODE_FLOAT64;
2286 ftotal = (int32_t) itotal & (int32_t) data.f_float.Get();
2287 }
2288 else {
2289 ftotal = (int32_t) ftotal & (int32_t) data.f_float.Get();
2290 }
2291 }
2292 }
2293 else {
2294 // We assume that the expression was already
2295 // compiled and thus identifiers which were
2296 // constants have been replaced already.
2297 return;
2298 }
2299 }
2300
2301 // if we reach here, we can change the node type
2302 // to NODE_INT64 or NODE_FLOAT64
2303 Data& data = bitwise_and.GetData();
2304 data.f_type = type;
2305 if(type == NODE_STRING) {
2306 data.f_str = result;
2307 }
2308 else if(type == NODE_INT64) {
2309 data.f_int.Set(itotal);
2310 }
2311 else {
2312 data.f_float.Set(ftotal);
2313 }
2314
2315 // we don't need any of these children anymore
2316 while(max > 0) {
2317 --max;
2318 bitwise_and.DeleteChild(max);
2319 }
2320 }
2321
2322
2323
BitwiseXOr(NodePtr & bitwise_xor)2324 void IntOptimizer::BitwiseXOr(NodePtr& bitwise_xor)
2325 {
2326 int64_t itotal;
2327 double ftotal;
2328 node_t type;
2329 int idx, max;
2330
2331 type = NODE_INT64;
2332 itotal = 0;
2333 ftotal = 0.0;
2334 max = bitwise_xor.GetChildCount();
2335 for(idx = 0; idx < max; ++idx) {
2336 NodePtr child = bitwise_xor.GetChild(idx);
2337 Data data = child.GetData();
2338 if(data.ToNumber()) {
2339 if(data.f_type == NODE_INT64) {
2340 if(type == NODE_INT64) {
2341 itotal ^= data.f_int.Get();
2342 }
2343 else {
2344 ftotal = (int32_t) ftotal ^ (int32_t) data.f_int.Get();
2345 }
2346 }
2347 else {
2348 if(type == NODE_INT64) {
2349 ftotal = (int32_t) itotal ^ (int32_t) data.f_float.Get();
2350 }
2351 else {
2352 ftotal = (int32_t) ftotal ^ (int32_t) data.f_float.Get();
2353 }
2354 }
2355 }
2356 else {
2357 // We assume that the expression was already
2358 // compiled and thus identifiers which were
2359 // constants have been replaced already.
2360 return;
2361 }
2362 }
2363
2364 // if we reach here, we can change the node type
2365 // to NODE_INT64 or NODE_FLOAT64
2366 Data& data = bitwise_xor.GetData();
2367 data.f_type = type;
2368 if(type == NODE_INT64) {
2369 data.f_int.Set(itotal);
2370 }
2371 else {
2372 data.f_float.Set(ftotal);
2373 }
2374
2375 // we don't need any of these children anymore
2376 while(max > 0) {
2377 --max;
2378 bitwise_xor.DeleteChild(max);
2379 }
2380 }
2381
2382
2383
BitwiseOr(NodePtr & bitwise_or)2384 void IntOptimizer::BitwiseOr(NodePtr& bitwise_or)
2385 {
2386 int64_t itotal;
2387 double ftotal;
2388 node_t type;
2389 int idx, max;
2390
2391 type = NODE_INT64;
2392 itotal = 0;
2393 ftotal = 0.0;
2394 max = bitwise_or.GetChildCount();
2395 for(idx = 0; idx < max; ++idx) {
2396 NodePtr child = bitwise_or.GetChild(idx);
2397 Data data = child.GetData();
2398 if(data.ToNumber()) {
2399 if(data.f_type == NODE_INT64) {
2400 if(type == NODE_INT64) {
2401 itotal |= data.f_int.Get();
2402 }
2403 else {
2404 ftotal = (int32_t) ftotal | (int32_t) data.f_int.Get();
2405 }
2406 }
2407 else {
2408 if(type == NODE_INT64) {
2409 ftotal = (int32_t) itotal | (int32_t) data.f_float.Get();
2410 }
2411 else {
2412 ftotal = (int32_t) ftotal | (int32_t) data.f_float.Get();
2413 }
2414 }
2415 }
2416 else {
2417 // We assume that the expression was already
2418 // compiled and thus identifiers which were
2419 // constants have been replaced already.
2420 return;
2421 }
2422 }
2423
2424 // if we reach here, we can change the node type
2425 // to NODE_INT64 or NODE_FLOAT64
2426 Data& data = bitwise_or.GetData();
2427 data.f_type = type;
2428 if(type == NODE_INT64) {
2429 data.f_int.Set(itotal);
2430 }
2431 else {
2432 data.f_float.Set(ftotal);
2433 }
2434
2435 // we don't need any of these children anymore
2436 while(max > 0) {
2437 --max;
2438 bitwise_or.DeleteChild(max);
2439 }
2440 }
2441
2442
2443
LogicalAnd(NodePtr & logical_and)2444 void IntOptimizer::LogicalAnd(NodePtr& logical_and)
2445 {
2446 node_t type;
2447 int idx, max;
2448
2449 type = NODE_TRUE;
2450 max = logical_and.GetChildCount();
2451 for(idx = 0; idx < max; ++idx) {
2452 NodePtr child = logical_and.GetChild(idx);
2453 Data data = child.GetData();
2454 if(data.ToBoolean()) {
2455 if(data.f_type == NODE_FALSE) {
2456 // stop testing as soon as it is known to be false
2457 type = NODE_FALSE;
2458 break;
2459 }
2460 }
2461 else {
2462 // We assume that the expression was already
2463 // compiled and thus identifiers which were
2464 // constants have been replaced already.
2465 return;
2466 }
2467 }
2468
2469 // if we reach here, we can change the node type
2470 // to NODE_INT64 or NODE_FLOAT64
2471 Data& data = logical_and.GetData();
2472 data.f_type = type;
2473
2474 // we don't need any of these children anymore
2475 while(max > 0) {
2476 --max;
2477 logical_and.DeleteChild(max);
2478 }
2479 }
2480
2481
2482
LogicalXOr(NodePtr & logical_xor)2483 void IntOptimizer::LogicalXOr(NodePtr& logical_xor)
2484 {
2485 node_t type;
2486 int idx, max;
2487
2488 type = NODE_FALSE;
2489 max = logical_xor.GetChildCount();
2490 for(idx = 0; idx < max; ++idx) {
2491 NodePtr child = logical_xor.GetChild(idx);
2492 Data data = child.GetData();
2493 if(data.ToBoolean()) {
2494 if(data.f_type == NODE_TRUE) {
2495 type = type == NODE_TRUE ? NODE_FALSE : NODE_TRUE;
2496 }
2497 }
2498 else {
2499 // We assume that the expression was already
2500 // compiled and thus identifiers which were
2501 // constants have been replaced already.
2502 return;
2503 }
2504 }
2505
2506 // if we reach here, we can change the node type
2507 // to NODE_INT64 or NODE_FLOAT64
2508 Data& data = logical_xor.GetData();
2509 data.f_type = type;
2510
2511 // we don't need any of these children anymore
2512 while(max > 0) {
2513 --max;
2514 logical_xor.DeleteChild(max);
2515 }
2516 }
2517
2518
2519
LogicalOr(NodePtr & logical_or)2520 void IntOptimizer::LogicalOr(NodePtr& logical_or)
2521 {
2522 node_t type;
2523 int idx, max;
2524
2525 type = NODE_FALSE;
2526 max = logical_or.GetChildCount();
2527 for(idx = 0; idx < max; ++idx) {
2528 NodePtr child = logical_or.GetChild(idx);
2529 Data data = child.GetData();
2530 if(data.ToBoolean()) {
2531 if(data.f_type == NODE_TRUE) {
2532 type = NODE_TRUE;
2533 break;
2534 }
2535 }
2536 else {
2537 // We assume that the expression was already
2538 // compiled and thus identifiers which were
2539 // constants have been replaced already.
2540 return;
2541 }
2542 }
2543
2544 // if we reach here, we can change the node type
2545 // to NODE_INT64 or NODE_FLOAT64
2546 Data& data = logical_or.GetData();
2547 data.f_type = type;
2548
2549 // we don't need any of these children anymore
2550 while(max > 0) {
2551 --max;
2552 logical_or.DeleteChild(max);
2553 }
2554 }
2555
2556
2557
Minimum(NodePtr & minimum)2558 void IntOptimizer::Minimum(NodePtr& minimum)
2559 {
2560 int r = Compare(minimum);
2561 if(r == -2 || r == 2) {
2562 return;
2563 }
2564
2565 if(r <= 0) {
2566 // in this case we want to keep the left node
2567 minimum = minimum.GetChild(0);
2568 }
2569 else {
2570 minimum = minimum.GetChild(1);
2571 }
2572 }
2573
2574
2575
Maximum(NodePtr & maximum)2576 void IntOptimizer::Maximum(NodePtr& maximum)
2577 {
2578 int r = Compare(maximum);
2579 if(r == -2 || r == 2) {
2580 return;
2581 }
2582
2583 if(r >= 0) {
2584 // in this case we want to keep the left node
2585 maximum = maximum.GetChild(0);
2586 }
2587 else {
2588 maximum = maximum.GetChild(1);
2589 }
2590 }
2591
2592
2593
Conditional(NodePtr & conditional)2594 void IntOptimizer::Conditional(NodePtr& conditional)
2595 {
2596 if(conditional.GetChildCount() != 3) {
2597 return;
2598 }
2599
2600 NodePtr child = conditional.GetChild(0);
2601 Data data = child.GetData();
2602 if(!data.ToBoolean()) {
2603 return;
2604 }
2605
2606 if(data.f_type == NODE_TRUE) {
2607 NodePtr expr = conditional.GetChild(1);
2608 conditional.DeleteChild(1);
2609 conditional.ReplaceWith(expr);
2610 }
2611 else {
2612 NodePtr expr = conditional.GetChild(2);
2613 conditional.DeleteChild(2);
2614 conditional.ReplaceWith(expr);
2615 }
2616 }
2617
2618
2619
2620
2621
2622 }; // namespace as
2623 }; // namespace sswf
2624