From 419fab0fea1863ce32f71f11a44267a7719e783e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Sun, 9 Mar 1997 01:11:13 -0800
Subject: [PATCH] peephole optimizer and code generator bugfixed and improved

Rev: bin/mkpeep.pike:1.3
Rev: src/docode.c:1.13
Rev: src/interpret.c:1.30
Rev: src/language.yacc:1.29
Rev: src/lex.c:1.17
Rev: src/operators.h:1.2
Rev: src/peep.c:1.7
Rev: src/peep.in:1.5
Rev: src/testsuite.in:1.34
---
 bin/mkpeep.pike   |  18 +++++--
 src/docode.c      |  50 ++++++++++++++++++--
 src/interpret.c   |  14 +++++-
 src/language.yacc |   3 +-
 src/lex.c         |   4 +-
 src/operators.h   |   4 ++
 src/peep.c        | 116 ++++++++++++++++++++++++++++++++--------------
 src/peep.in       |   2 +
 src/testsuite.in  |   3 +-
 9 files changed, 169 insertions(+), 45 deletions(-)

diff --git a/bin/mkpeep.pike b/bin/mkpeep.pike
index 181ed1569d..04609cbc65 100755
--- a/bin/mkpeep.pike
+++ b/bin/mkpeep.pike
@@ -312,20 +312,21 @@ void dump2(mixed *data,int ind)
       {
 	if(i+1<sizeof(d[1]) && d[1][i+1][0]=='(')
 	{
-	  write(sprintf("%*ninsert_opcode(%s,arg%d,cl,cf);\n",ind,d[1][i],i));
+	  write(sprintf("%*ninsopt(%s,arg%d,cl,cf);\n",ind,d[1][i],i));
 	  i++;
 	}else{
-	  write(sprintf("%*ninsert_opcode2(%s,cl,cf);\n",ind,d[1][i]));
+	  write(sprintf("%*ninsopt2(%s,cl,cf);\n",ind,d[1][i]));
 	}
 	q++;
       }
       if(sizeof(d[1]))
       {
 	if(q)
-	  write(sprintf("%*nfifo_len+=%d;\n",ind,q+JUMPBACK));
+	  write(sprintf("%*nfifo_len+=%d;\n",ind,q));
 	write(sprintf("%*nfree_string(cf);\n",ind));
 	write(sprintf("%*ndebug();\n",ind));
       }
+      write(sprintf("%*nfifo_len+=%d;\n",ind,q+JUMPBACK));
       write(sprintf("%*ncontinue;\n",ind));
 
       ind-=2;
@@ -373,6 +374,17 @@ int main(int argc, string *argv)
   write("    INT32 current_line;\n");
   write("    struct pike_string *current_file;\n");
   write("\n");
+  write("#ifdef DEBUG\n");
+  write("    if(a_flag>5) {\n");
+  write("      fprintf(stderr,\"#%d,%d:\",eye,fifo_len);\n");
+  write("      fprintf(stderr,\"%s(%d)\",  get_token_name(opcode(-2)),argument(-2));\n");
+  write("      fprintf(stderr,\" %s(%d)\",  get_token_name(opcode(-1)),argument(-1));\n");
+  write("      fprintf(stderr,\" . %s(%d)\",  get_token_name(opcode(0)),argument(0));\n");
+  write("      fprintf(stderr,\" %s(%d)\",  get_token_name(opcode(1)),argument(1));\n");
+  write("      fprintf(stderr,\" %s(%d)\",  get_token_name(opcode(2)),argument(2));\n");
+  write("      fprintf(stderr,\" %s(%d)\\n\",get_token_name(opcode(3)),argument(3));\n");
+  write("    }\n");
+  write("#endif\n\n");
 
   dump2(data,4);
 
diff --git a/src/docode.c b/src/docode.c
index b052a41aa6..12e2c9f2ae 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.12 1997/03/05 05:22:55 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.13 1997/03/09 09:11:10 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -22,6 +22,7 @@ RCSID("$Id: docode.c,v 1.12 1997/03/05 05:22:55 hubbe Exp $");
 #include "builtin_functions.h"
 #include "peep.h"
 #include "docode.h"
+#include "operators.h"
 
 INT32 current_break=-1;
 INT32 current_continue=-1;
@@ -159,6 +160,13 @@ int do_docode(node *n,INT16 flags)
 
 void do_jump_when_zero(node *n,int j);
 
+static int is_efun(node *n, c_fun fun)
+{
+  return n && n->token == F_CONSTANT &&
+     n->u.sval.subtype == FUNCTION_BUILTIN &&
+    n->u.sval.u.efun->function == fun;
+}
+
 void do_jump_when_non_zero(node *n,int j)
 {
   if(!node_is_tossable(n))
@@ -175,10 +183,28 @@ void do_jump_when_non_zero(node *n,int j)
 
   switch(n->token)
   {
+  case F_APPLY:
+    if(is_efun(CAR(n), f_not))
+    {
+      do_jump_when_zero(CDR(n), j);
+      return;
+    }
+    break;
+      
   case F_NOT:
     do_jump_when_zero(CAR(n), j);
     return;
-  case F_OR:
+
+  case F_LAND:
+  {
+    int tmp=alloc_label();
+    do_jump_when_zero(CAR(n), tmp);
+    do_jump_when_non_zero(CDR(n), j);
+    emit(F_LABEL,tmp);
+    return;
+  }
+    
+  case F_LOR:
     do_jump_when_non_zero(CAR(n), j);
     do_jump_when_non_zero(CDR(n), j);
     return;
@@ -205,10 +231,28 @@ void do_jump_when_zero(node *n,int j)
 
   switch(n->token)
   {
+  case F_APPLY:
+    if(is_efun(CAR(n), f_not))
+    {
+      do_jump_when_non_zero(CDR(n), j);
+      return;
+    }
+    break;
+
   case F_NOT:
     do_jump_when_non_zero(CAR(n), j);
     return;
-  case F_AND:
+
+  case F_LOR:
+  {
+    int tmp=alloc_label();
+    do_jump_when_non_zero(CAR(n), tmp);
+    do_jump_when_zero(CDR(n), j);
+    emit(F_LABEL,tmp);
+    return;
+  }
+
+  case F_LAND:
     do_jump_when_zero(CAR(n), j);
     do_jump_when_zero(CDR(n), j);
     return;
diff --git a/src/interpret.c b/src/interpret.c
index 8bb77beff2..81bd795b92 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.29 1997/03/08 12:54:06 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.30 1997/03/09 09:11:11 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -881,6 +881,18 @@ static void eval_instruction(unsigned char *pc)
       }
       break;
 
+      CASE(F_EQ_OR);
+      if(is_eq(sp-2,sp-1))
+      {
+	pop_n_elems(2);
+	pc+=sizeof(INT32);
+      }else{
+	pop_n_elems(2);
+	push_int(1);
+	DOJUMP();
+      }
+      break;
+
       CASE(F_CATCH);
       if(o_catch(pc+sizeof(INT32)))
 	return; /* There was a return inside the evaluated code */
diff --git a/src/language.yacc b/src/language.yacc
index d34d0fc7ea..5122e1f040 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -56,6 +56,7 @@
 %token F_AND F_OR F_XOR
 %token F_LSH F_RSH
 %token F_LAND F_LOR
+%token F_EQ_OR
 
 %token F_SWITCH F_SSCANF F_CATCH
 %token F_CAST
@@ -157,7 +158,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.28 1997/03/05 05:12:07 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.29 1997/03/09 09:11:11 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
diff --git a/src/lex.c b/src/lex.c
index 01e9e894a3..d69d0a1695 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.16 1997/03/08 12:54:06 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.17 1997/03/09 09:11:12 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -272,6 +272,8 @@ struct keyword instr_names[]=
 { "apply and pop",      F_APPLY_AND_POP, 1 },
 { "2 locals",           F_2_LOCALS, 1 },
 { "byte",               F_BYTE, 1 },
+{ "nop",                F_NOP },
+{ "==||",               F_EQ_OR, 1 },
 };
 
 struct instr instrs[F_MAX_INSTR - F_OFFSET];
diff --git a/src/operators.h b/src/operators.h
index e42f381115..4887aa8d49 100644
--- a/src/operators.h
+++ b/src/operators.h
@@ -15,6 +15,7 @@ COMPARISON(f_lt,"`<" , is_lt(sp-2,sp-1))
 COMPARISON(f_le,"`<=",!is_gt(sp-2,sp-1))
 COMPARISON(f_gt,"`>" , is_gt(sp-2,sp-1))
 COMPARISON(f_ge,"`>=",!is_lt(sp-2,sp-1))
+
 void f_add(INT32 args);
 void o_subtract();
 void f_minus(INT32 args);
@@ -40,6 +41,9 @@ void o_compl();
 void f_compl(INT32 args);
 void o_negate();
 void o_range();
+void f_index(INT32 args);
+void f_arrow(INT32 args);
+void f_sizeof(INT32 args);
 void init_operators();
 /* Prototypes end here */
 
diff --git a/src/peep.c b/src/peep.c
index a56921283a..9a3124daff 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -81,6 +81,7 @@ int insert_opcode2(int f,int current_line, struct pike_string *current_file)
   return insert_opcode(f,0,current_line, current_file);
 }
 
+
 void update_arg(int instr,INT32 arg)
 {
   p_instr *p;
@@ -153,6 +154,7 @@ static void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b)
     case F_DEC_NEQ_LOOP: \
     case F_LAND: \
     case F_LOR: \
+    case F_EQ_OR: \
     case F_CATCH: \
     case F_FOREACH
 
@@ -191,20 +193,41 @@ void assemble(void)
 
   for(e=0;e<length;e++)
   {
-    int tmp;
     switch(c[e].opcode)
     {
     case BRANCH_CASES:
     case F_POINTER:
       while(1)
       {
+	int tmp,tmp2;
 	tmp=labels[c[e].arg];
 	
 	while(c[tmp].opcode == F_LABEL ||
 	      c[tmp].opcode == F_NOP) tmp++;
 	
-	if(c[tmp].opcode!=F_BRANCH) break;
-	c[e].arg=c[tmp].arg;
+	if(c[tmp].opcode==F_BRANCH)
+	{
+	  c[e].arg=c[tmp].arg;
+	  continue;
+	}
+
+#define TWOO(X,Y) (((X)<<8)+(Y))
+
+	switch(TWOO(c[e].opcode,c[tmp].opcode))
+	{
+	case TWOO(F_LOR,F_BRANCH_WHEN_NON_ZERO):
+	  c[e].opcode=F_BRANCH_WHEN_NON_ZERO;
+	case TWOO(F_LOR,F_LOR):
+	  c[e].arg=c[tmp].arg;
+	continue;
+	
+	case TWOO(F_LAND,F_BRANCH_WHEN_ZERO):
+	  c[e].opcode=F_BRANCH_WHEN_ZERO;
+	case TWOO(F_LAND,F_LAND):
+	  c[e].arg=c[tmp].arg;
+	continue;
+	}
+	break;
       }
       uses[c[e].arg]++;
     }
@@ -311,6 +334,47 @@ void assemble(void)
 static int fifo_len, eye,len;
 static p_instr *instructions;
 
+int insopt(int f, INT32 b, int cl, struct pike_string *cf)
+{
+  p_instr *p;
+
+#ifdef DEBUG
+  if(!hasarg(f) && b)
+    fatal("hasarg() is wrong!\n");
+#endif
+
+  p=(p_instr *)low_make_buf_space(sizeof(p_instr), &instrbuf);
+
+  if(fifo_len)
+  {
+    MEMMOVE(p-fifo_len+1,p-fifo_len,fifo_len*sizeof(p_instr));
+    p-=fifo_len;
+    fifo_len++;
+  }
+
+#ifdef DEBUG
+  if(!instrbuf.s.len)
+    fatal("Low make buf space failed!!!!!!\n");
+#endif
+
+  p->opcode=f;
+  p->line=current_line;
+  copy_shared_string(p->file, current_file);
+  p->arg=b;
+
+  return p - (p_instr *)instrbuf.s.str;
+}
+
+int insopt2(int f, int cl, struct pike_string *cf)
+{
+#ifdef DEBUG
+  if(hasarg(f))
+    fatal("hasarg() is wrong!\n");
+#endif
+  return insert_opcode(f,0,cl, cf);
+}
+
+
 static void debug()
 {
   if(fifo_len > (long)instrbuf.s.len / (long)sizeof(p_instr))
@@ -336,23 +400,18 @@ static p_instr *instr(int offset)
 
   debug();
 
-  if(offset >= 0)
+  if(offset < fifo_len)
   {
-    if(offset < fifo_len)
-    {
-      p=(p_instr *)low_make_buf_space(0, &instrbuf);
-      p-=fifo_len;
-      p+=offset;
-      return p;
-    }else{
-      offset-=fifo_len;
-      offset+=eye;
-      if(offset >= len) return 0;
-      return instructions+offset;
-    }
+    p=(p_instr *)low_make_buf_space(0, &instrbuf);
+    p-=fifo_len;
+    p+=offset;
+    if(((char *)p)<instrbuf.s.str)  return 0;
+    return p;
   }else{
-    fatal("Can't handle negative offsets in peephole optimizer!\n");
-    return 0; /* Make GCC happy */
+    offset-=fifo_len;
+    offset+=eye;
+    if(offset >= len) return 0;
+    return instructions+offset;
   }
 }
 
@@ -393,37 +452,24 @@ static void pop_n_opcodes(int n)
   {
     p_instr *p;
 
-    d=fifo_len;
-    if(d>n) d=n;
+    d=n;
+    if(d>fifo_len) d=fifo_len;
 #ifdef DEBUG
     if((long)d > (long)instrbuf.s.len / (long)sizeof(p_instr))
       fatal("Popping out of instructions.\n");
 #endif
 
-    low_make_buf_space(-((INT32)sizeof(p_instr))*fifo_len, &instrbuf);
     p=(p_instr *)low_make_buf_space(0, &instrbuf);
+    p-=fifo_len;
     for(e=0;e<d;e++) free_string(p[e].file);
     fifo_len-=d;
     if(fifo_len) MEMMOVE(p,p+d,fifo_len*sizeof(p_instr));
     n-=d;
+    low_make_buf_space(-((INT32)sizeof(p_instr))*d, &instrbuf);
   }
   eye+=n;
 }
 
-static void dofix()
-{
-  p_instr *p,tmp;
-  int e;
-
-  if(fifo_len)
-  {
-    p=(p_instr *)low_make_buf_space(0, &instrbuf);
-    tmp=p[-1];
-    for(e=0;e<fifo_len;e++)
-      p[-1-e]=p[-2-e];
-    p[-1-e]=tmp;
-  }
-}
 
 static void asm_opt(void)
 {
diff --git a/src/peep.in b/src/peep.in
index b100f7ae23..3fab269e3d 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -94,6 +94,8 @@ GT BRANCH_WHEN_ZERO: BRANCH_WHEN_LE ($2a)
 LE BRANCH_WHEN_ZERO: BRANCH_WHEN_GT ($2a)
 GE BRANCH_WHEN_ZERO: BRANCH_WHEN_LT ($2a)
 
+EQ LOR: EQ_OR ($2a)
+
 EQ NOT: NE
 NE NOT: EQ
 LT NOT: GE
diff --git a/src/testsuite.in b/src/testsuite.in
index 7dd2e80402..ccc0366844 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,5 @@
-test_true([["$Id: testsuite.in,v 1.33 1997/03/08 12:54:09 hubbe Exp $"]])
+test_true([["$Id: testsuite.in,v 1.34 1997/03/09 09:11:13 hubbe Exp $"]])
+test_program([[inline string foo(string s){ while(s[0] == ' ' || s[0] == '\t') s = s[1..]; return(s); } string a() { return foo("   bar"); }]])
 test_true([[lambda(function f) {return 1;}(object_program(this_object()));]])
 test_eq([[class { int `()(){ return 4711; } }()(); ]],4711)
 teste_eval_error(mixed foo=({}); sort(@foo); )
-- 
GitLab