yarv-diff:13
From: ko1 atdot.net
Date: 8 Jun 2005 13:33:02 -0000
Subject: [yarv-diff:13] r168 - trunk
Author: ko1
Date: 2005-06-08 22:33:00 +0900 (Wed, 08 Jun 2005)
New Revision: 168
Modified:
trunk/ChangeLog
trunk/compile.c
trunk/test.rb
Log:
* compile.c : add if/unless(L1) jump (L2) :L1 => unless/if(L2)
optimize (condition reversal) and fix typo
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-06-08 03:03:49 UTC (rev 167)
+++ trunk/ChangeLog 2005-06-08 13:33:00 UTC (rev 168)
@@ -4,6 +4,12 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2005-06-08(Wed) 22:30:44 +0900 Koichi Sasada <ko1 atdot.net>
+
+ * compile.c : add if/unless(L1) jump (L2) :L1 => unless/if(L2)
+ optimize (condition reversal) and fix typo
+
+
2005-06-07(Tue) 08:29:41 +0900 Koichi Sasada <ko1 atdot.net>
* yarvcore.c : fix to remove compiler warning
Modified: trunk/compile.c
===================================================================
--- trunk/compile.c 2005-06-08 03:03:49 UTC (rev 167)
+++ trunk/compile.c 2005-06-08 13:33:00 UTC (rev 168)
@@ -264,6 +264,13 @@
}
}
+static void REMOVE_ELEM(struct iseq_link_element *elem){
+ elem->prev->next = elem->next;
+ if(elem->next){
+ elem->next->prev = elem->prev;
+ }
+}
+
/*
#define APPEND_LINKED_LIST(list1, list2) \
{ \
@@ -935,6 +942,30 @@
return list;
}
+static struct iseq_link_element *
+get_next_insn(struct insn_object *iobj){
+ struct iseq_link_element *list = iobj->link.next;
+ while(list){
+ if(list->type == ISEQ_ELEMENT_INSN){
+ return list;
+ }
+ list = list->next;
+ }
+ return 0;
+}
+
+static struct iseq_link_element *
+get_prev_insn(struct insn_object *iobj){
+ struct iseq_link_element *list = iobj->link.prev;
+ while(list){
+ if(list->type == ISEQ_ELEMENT_INSN){
+ return list;
+ }
+ list = list->prev;
+ }
+ return 0;
+}
+
static void iseq_optimize(VALUE self, struct link_anchor *anchor, VALUE ary){
struct iseq_link_element *list;
/*
@@ -951,9 +982,10 @@
list = FIRST_ELEMENT(anchor);
while(list){
if(list->type == ISEQ_ELEMENT_INSN){
- struct insn_object *niobj, *iobj = (struct insn_object *)list;
+ struct insn_object *niobj, *piobj, *iobj = (struct insn_object *)list;
if(iobj->insn_id == BIN(jump)){
niobj = (struct insn_object*)get_destination_insn(iobj);
+
if(niobj->insn_id == BIN(jump)){
OPERAND_OF_RAW(iobj, 0) = OPERAND_OF_RAW(niobj, 0);
continue;
@@ -962,14 +994,36 @@
VALUE endinsn = new_insn(BIN(end), iobj->line_no, niobj->operands);
struct insn_object *eiobj;
GetInsnVal(endinsn, eiobj);
-
+
/* protect for GC */
rb_ary_push(ary, endinsn);
-
+
/* replace */
REPLACE_ELEM((struct iseq_link_element *)iobj,
(struct iseq_link_element *)eiobj);
}
+ /*
+ * if L1
+ * jump L2
+ * L1:
+ * ...
+ * L2:
+ *
+ * ==>
+ * unless L2
+ * L1:
+ * ...
+ * L2:
+ */
+ else if ((piobj = (struct insn_object*)get_prev_insn(iobj)) != 0 &&
+ (piobj->insn_id == BIN(if) ||
+ piobj->insn_id == BIN(unless))){
+ if(get_next_insn(iobj) == get_destination_insn(piobj)){
+ piobj->insn_id = (piobj->insn_id == BIN(if)) ? BIN(unless) : BIN(if);
+ OPERAND_OF_RAW(piobj, 0) = OPERAND_OF_RAW(iobj, 0);
+ REMOVE_ELEM(&iobj->link);
+ }
+ }
}
}
list = list->next;
@@ -1246,27 +1300,27 @@
return iseqobj->local_size;
}
-static VALUE compile_branch_conditon(VALUE self, NODE *cond,
+static VALUE compile_branch_condition(VALUE self, NODE *cond,
VALUE then_label, VALUE else_label){
VALUE ret = NEW_SEQ();
switch(nd_type(cond)){
case NODE_NOT:
- ret = compile_branch_conditon(self, cond->nd_body, else_label, then_label);
+ ret = compile_branch_condition(self, cond->nd_body, else_label, then_label);
break;
case NODE_AND:{
VALUE label = NEW_LABEL(nd_line(cond));
- ADD_SEQ (ret, compile_branch_conditon(self, cond->nd_1st, label, else_label));
+ ADD_SEQ (ret, compile_branch_condition(self, cond->nd_1st, label, else_label));
ADD_LABEL(ret, label);
- ADD_SEQ (ret, compile_branch_conditon(self, cond->nd_2nd, then_label, else_label));
+ ADD_SEQ (ret, compile_branch_condition(self, cond->nd_2nd, then_label, else_label));
break;
}
case NODE_OR:{
VALUE label = NEW_LABEL(nd_line(cond));
- ADD_SEQ (ret, compile_branch_conditon(self, cond->nd_1st, then_label, label));
+ ADD_SEQ (ret, compile_branch_condition(self, cond->nd_1st, then_label, label));
ADD_LABEL(ret, label);
- ADD_SEQ (ret, compile_branch_conditon(self, cond->nd_2nd, then_label, else_label));
+ ADD_SEQ (ret, compile_branch_condition(self, cond->nd_2nd, then_label, else_label));
break;
}
default:
@@ -1548,7 +1602,7 @@
else_label = NEW_LABEL(nd_line(node));
end_label = NEW_LABEL(nd_line(node));
- cond_seq = compile_branch_conditon(self, node->nd_cond, then_label, else_label);
+ cond_seq = compile_branch_condition(self, node->nd_cond, then_label, else_label);
then_seq = COMPILE_("then", node->nd_body, poped);
else_seq = COMPILE_("else", node->nd_else, poped);
@@ -1731,13 +1785,13 @@
ADD_LABEL(ret, next_label); /* next */
if(type == NODE_WHILE){
- ADD_SEQ(ret, compile_branch_conditon(self, node->nd_cond,
- redo_label, end_label));
+ ADD_SEQ(ret, compile_branch_condition(self, node->nd_cond,
+ redo_label, end_label));
}
else{
/* untile */
- ADD_SEQ(ret, compile_branch_conditon(self, node->nd_cond,
- end_label, redo_label));
+ ADD_SEQ(ret, compile_branch_condition(self, node->nd_cond,
+ end_label, redo_label));
}
ADD_LABEL(ret, end_label);
Modified: trunk/test.rb
===================================================================
--- trunk/test.rb 2005-06-08 03:03:49 UTC (rev 167)
+++ trunk/test.rb 2005-06-08 13:33:00 UTC (rev 168)
@@ -9,6 +9,23 @@
###########################################################
$prog =<<'__EOP__'
+def f x, y, z
+ if (x and y) or z
+ 1
+ else
+ 2
+ end
+end
+
+
+__END__
+a = b = c = 0
+if a and b or c
+ p 'hoge'
+end
+
+
+__END__
a = b = 0
while a < 10 and b < 5
a = b = a+1
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml