cvsuser     03/02/17 05:56:38

  Modified:    languages/imcc imc.c imc.h imcc.l imcc.y instructions.c
                        main.c optimizer.c parser_util.c pbc.c symreg.c
               languages/imcc/t/imcpasm opt1.t
  Log:
  imcc-opt: J.Boemmels patch #21033; much more optimizations
  
  Revision  Changes    Path
  1.33      +11 -0     parrot/languages/imcc/imc.c
  
  Index: imc.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imc.c,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -w -r1.32 -r1.33
  --- imc.c     8 Feb 2003 17:16:16 -0000       1.32
  +++ imc.c     17 Feb 2003 13:56:36 -0000      1.33
  @@ -23,6 +23,17 @@
   
   static IMCStack nodeStack;
   
  +/* return the index of a PMC class */
  +int get_pmc_num(struct Parrot_Interp *interp, char *pmc_type)
  +{
  +    STRING * s = string_make(interp, pmc_type,
  +            (UINTVAL) strlen(pmc_type), NULL, 0, NULL);
  +    PMC * key = key_new_string(interp, s);
  +    PMC * cnames = interp->Parrot_base_classname_hash;
  +
  +    return cnames->vtable->get_integer_keyed(interp, cnames, key);
  +}
  +
   /* allocate is the main loop of the allocation algorithm */
   void allocate(struct Parrot_Interp *interpreter) {
       int to_spill;
  
  
  
  1.26      +1 -0      parrot/languages/imcc/imc.h
  
  Index: imc.h
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imc.h,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -w -r1.25 -r1.26
  --- imc.h     8 Feb 2003 14:41:28 -0000       1.25
  +++ imc.h     17 Feb 2003 13:56:36 -0000      1.26
  @@ -54,6 +54,7 @@
   void restore_interference_graph(void);
   void free_reglist(void);
   int neighbours(int node);
  +int get_pmc_num(struct Parrot_Interp *interp, char *pmc_type);
   
   
   int check_op(struct Parrot_Interp *, char * fullname, char *op, SymReg *r[]);
  
  
  
  1.27      +459 -61   parrot/languages/imcc/imcc.l
  
  Index: imcc.l
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imcc.l,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -w -r1.26 -r1.27
  --- imcc.l    11 Feb 2003 11:34:36 -0000      1.26
  +++ imcc.l    17 Feb 2003 13:56:36 -0000      1.27
  @@ -16,10 +16,56 @@
   #include "imc.h"
   #include "parser.h"
   
  -#define YY_NO_UNPUT
  +#define MAX_PARAM 16
  +
  +struct params_t {
  +    char *name[MAX_PARAM];
  +    int num_param;
  +};
  +
  +struct macro_t {
  +    char *name;
  +    struct params_t params;
  +    char *expansion;
  +};
  +
  +/* XXX: boe: rework this hack to use a hash */
  +struct macro_t macros[256];
  +int num_macros = 0;
  +
  +char temp_buffer[4096];
  +
  +struct macro_frame_t {
  +    struct macro_frame_t *next;
  +    YY_BUFFER_STATE buffer;
  +    struct params_t *params;
  +    struct params_t expansion;
  +    int label;
  +};
  +
  +struct macro_frame_t *frames = NULL;
  +
  +/* static function declariations */
  +static struct macro_frame_t *new_frame (void);
  +/*static void add_param_to_frame (const char *param, const char *expansion); */
  +static void scan_string (struct macro_frame_t *frame, const char *expansion);
  +static void scan_file (struct macro_frame_t *frame, FILE *);
  +static void destroy_frame (struct macro_frame_t *frame);
  +static int yylex_skip (YYSTYPE *valp, void *interp, const char *skip);
  +
  +static int read_macro (YYSTYPE *valp, void *interp);
  +static int expand_macro (YYSTYPE *valp, void *interp, const char *name);
  +static void include_file (const char *file_name);
  +
   #define YY_DECL int yylex(YYSTYPE *valp, struct Parrot_Interp *interp)
   
  -int state;
  +#define YYCHOP() (yytext[--yyleng] = '\0')
  +#define DUP_AND_RET(valp, token)             \
  +  do {                                       \
  +      if (valp) (valp)->s = str_dup(yytext); \
  +      return token;                          \
  +  } while (0)
  +
   %}
   
   %option outfile="imclexer.c"
  @@ -32,19 +78,23 @@
   SIGN            [-+]
   FLOATNUM        {SIGN}?{DIGIT}+{DOT}{DIGIT}*([eE]{SIGN}?{DIGIT}+)?
   LETTERDIGIT     [a-zA-Z0-9_]
  +ID              {LETTER}{LETTERDIGIT}*
   STRINGCONSTANT  \"(\\\"|[^"\n]*)*\"
   CHARCONSTANT    \'[^'\n]*\'
   RANKSPEC        \[[,]*\]
   EOL          \r?\n
  +WS              [\t\f\r ]
   
   %x emit
  +%x macro
  +
   %%
  -        /* for emacs: ' */
  +        /* for emacs "*/
           if (expect_pasm == 1) {
            expect_pasm = 2;
               BEGIN(emit);
        }
  -     if (pasm_file && YYSTATE != emit) {
  +        if (pasm_file && YYSTATE == INITIAL) {
            if (pasm_file == 1) {
                BEGIN(emit);
                return EMIT;
  @@ -56,7 +106,7 @@
           if (expect_pasm == 2)
          BEGIN(INITIAL);
           expect_pasm = 0;
  -        line++;
  +        if (frames) line++;
           return '\n';
       }
   
  @@ -128,17 +178,68 @@
   "!="            return(RELOP_NE);
   "**"            return(POW);
   
  -<emit,INITIAL>","             return(COMMA);
  +<emit>".macro" {
  +        return read_macro(valp, interp);
  +    }
   
  -<emit,INITIAL>{LETTER}{LETTERDIGIT}*":" {
  -     yytext[yyleng-1] = 0;  /* trim last ':' */
  -        valp->s = str_dup(yytext);
  -        return(LABEL);
  +<emit>".include" {
  +        int c;
  +
  +     c = yylex(valp, interp);
  +     if (c != STRINGC) return c;
  +
  +     YYCHOP();
  +     include_file(str_dup(yytext + 1));
       }
   
  -<emit>{DOT}{LETTER}{LETTERDIGIT}* {
  -        valp->s = str_dup(yytext+1);
  -        return(MACRO);
  +<emit>{ID}"$:" {
  +        char *label;
  +
  +     if (valp) {
  +         YYCHOP(); YYCHOP();
  +
  +         label = mem_sys_allocate(yyleng+10);
  +         sprintf(label, "%s%d", yytext, frames->label);
  +
  +         valp->s = label;
  +     }
  +
  +        return LABEL;
  +    }
  +
  +<emit>{ID}"$" {
  +        char *label;
  +
  +     if (valp) {
  +         YYCHOP();
  +
  +         label = mem_sys_allocate(yyleng+10);
  +         sprintf(label, "%s%d", yytext, frames->label);
  +
  +         valp->s = label;
  +     }
  +
  +     return IDENTIFIER;
  +    }
  +
  +<emit,INITIAL>","             return(COMMA);
  +
  +<emit,INITIAL>{ID}":" {
  +     YYCHOP();  /* trim last ':' */
  +     DUP_AND_RET(valp,LABEL);
  +    }
  +
  +<emit,INITIAL>{DOT}{LETTER}{LETTERDIGIT}* {
  +        int type = get_pmc_num(interp, yytext+1);
  +
  +        if (type) {
  +            char *buf = malloc(16);
  +         sprintf(buf, "%d", type);
  +         valp->s = buf;
  +         return INTC;
  +     }
  +     if (!expand_macro(valp, interp, yytext+1))
  +            fataly(1, "", line, "unknown macro '%s'\n", yytext);
       }
   
   <emit,INITIAL>{LETTER}{LETTERDIGIT}* {
  @@ -153,53 +254,28 @@
           return(is_op(interp, valp->s) ? PARROT_OP : IDENTIFIER);
       }
   
  -<emit,INITIAL>{FLOATNUM} {
  -        valp->s = str_dup(yytext);
  -        return(FLOATC);
  -    }
  +<*>{FLOATNUM}         DUP_AND_RET(valp, FLOATC);
  +<*>{SIGN}?{DIGIT}+    DUP_AND_RET(valp, INTC);
  +<*>{HEX}              DUP_AND_RET(valp, INTC);
  +<*>{BIN}              DUP_AND_RET(valp, INTC);
   
  -<emit,INITIAL>{SIGN}?{DIGIT}+ {
  +<*>{STRINGCONSTANT} {
           valp->s = str_dup(yytext);
  -        return(INTC);
  +        return(STRINGC); /* XXX delete quotes, -> emit, pbc */
       }
  -<emit,INITIAL>{HEX} {
  -        valp->s = str_dup(yytext);
  -        return(INTC);
  -    }
  -<emit,INITIAL>{BIN} {
  -        valp->s = str_dup(yytext);
  -        return(INTC);
  -    }
  -<emit,INITIAL>{STRINGCONSTANT} {
  +
  +<*>{CHARCONSTANT} {
           valp->s = str_dup(yytext); /* XXX delete quotes, -> emit, pbc */
           return(STRINGC);
       }
  -<emit,INITIAL>{CHARCONSTANT} {
  -        valp->s = str_dup(yytext);
  -        return(STRINGC);
  -    }
   
  -<emit,INITIAL>\$I[0-9]+ {
  -        valp->s = str_dup(yytext);
  -        return(IREG);
  -    }
  +<*>\$I[0-9]+          DUP_AND_RET(valp, IREG);
  +<*>\$N[0-9]+          DUP_AND_RET(valp, NREG);
  +<*>\$S[0-9]+          DUP_AND_RET(valp, SREG);
  +<*>\$P[0-9]+          DUP_AND_RET(valp, PREG);
   
  -<emit,INITIAL>\$N[0-9]+ {
  -        valp->s = str_dup(yytext);
  -        return(NREG);
  -    }
  -
  -<emit,INITIAL>\$S[0-9]+ {
  -        valp->s = str_dup(yytext);
  -        return(SREG);
  -    }
  +<emit,INITIAL>{WS}+ /* skip */;
   
  -<emit,INITIAL>\$P[0-9]+ {
  -        valp->s = str_dup(yytext);
  -        return(PREG);
  -    }
  -
  -<emit,INITIAL>[\t\f\r ]+        ;
   <emit,INITIAL>.     {
          return yytext[0];
       }
  @@ -213,7 +289,55 @@
           return 0;
       }
   
  -<<EOF>> yyterminate();
  +<INITIAL><<EOF>> yyterminate();
  +
  +<macro>".endm"         DUP_AND_RET(valp, ENDM);
  +
  +<macro>{WS}*{EOL} {
  +        line++;
  +        DUP_AND_RET(valp, '\n');
  +    }
  +
  +<macro>"$"{ID}":"  return LABEL;
  +<macro>".local"{WS}+ {
  +        char *label;
  +     char *name = macros[num_macros].name;
  +
  +     if (yylex(valp, interp) != LABEL) yyerror("LABEL expected");
  +
  +     if (valp) {
  +         YYCHOP();
  +
  +         label = mem_sys_allocate(strlen(name) + yyleng + 15);
  +         sprintf(label, "local__%s__%s__$:", name, yytext+1);
  +
  +         valp->s = label;
  +     }
  +
  +     return LABEL;
  +    }
  +
  +<macro>".$"{ID} {
  +        char *label;
  +     char *name = macros[num_macros].name;
  +
  +     if (valp) {
  +         label = mem_sys_allocate(strlen(name) + yyleng + 15);
  +         sprintf(label, "local__%s__%s__$", name, yytext+2);
  +
  +         valp->s = label;
  +     }
  +
  +     return IDENTIFIER;
  +    }
  +
  +<macro>^{WS}+                       /* skip leading ws */;
  +<macro>{WS}+                        DUP_AND_RET(valp, ' ');
  +<macro>{ID}                         DUP_AND_RET(valp, IDENTIFIER);
  +<macro>{DOT}{ID}                    DUP_AND_RET(valp, MACRO);
  +<macro>.                            DUP_AND_RET(valp, yytext[0]);
  +<macro><<EOF>>                      yyterminate();
  +
   %%
   
   #ifdef yywrap
  @@ -225,6 +349,280 @@
          yywrap returns 0 if scanning is to continue
       */
       yy_delete_buffer(YY_CURRENT_BUFFER);
  +
  +    /* pop old frames */
  +    if (frames) {
  +     struct macro_frame_t *tmp;
  +     tmp = frames;
  +     frames = frames->next;
  +     destroy_frame(tmp);
  +     return 0;
  +    }
  +
  +    return 1;
  +}
  +
  +static struct macro_frame_t *
  +new_frame (void)
  +{
  +    static int label = 0;
  +    struct macro_frame_t *tmp;
  +
  +    tmp = mem_sys_allocate_zeroed(sizeof(struct macro_frame_t));
  +    tmp->label = ++label;
  +
  +    return tmp;
  +}
  +
  +static void
  +scan_string (struct macro_frame_t *frame, const char *expansion)
  +{
  +    frame->buffer = YY_CURRENT_BUFFER;
  +    frame->next = frames;
  +    frames = frame;
  +
  +    yy_scan_string(expansion);
  +}
  +
  +static void
  +destroy_frame (struct macro_frame_t *frame)
  +{
  +    YY_BUFFER_STATE buffer;
  +    int i;
  +
  +    buffer = frame->buffer;
  +
  +    for (i = 0; i < frame->expansion.num_param; i++) {
  +     free(frame->expansion.name[i]);
  +    }
  +
  +    mem_sys_free(frame);
  +
  +    yy_switch_to_buffer(buffer);
  +}
  +
  +static int
  +yylex_skip (YYSTYPE *valp, void *interp, const char *skip)
  +{
  +    int c;
  +    const char *p;
  +
  +    do {
  +        c = yylex(NULL, interp);
  +        p = skip;
  +     while (*p && c != *p) p++;
  +    } while (*p != '\0');
  +
  +    DUP_AND_RET(valp, c);
  +}
  +
  +static int
  +read_params (YYSTYPE *valp, void *interp, struct params_t *params,
  +          int need_id)
  +{
  +    int c;
  +    YYSTYPE val;
  +    char *current = strdup("");
  +    int len = 0;
  +
  +    params->num_param = 0;
  +    c = yylex_skip(&val, interp, " \n");
  +
  +    while(c != ')') {
  +     if (c == 0) yyerror ("Unexpected end of file");
  +     else if (c == ',') {
  +         params->name[params->num_param++] = current;
  +         current = strdup("");
  +         len = 0;
  +         c = yylex_skip(&val, interp, " \n");
  +     }
  +     else if (need_id && (*current || c != IDENTIFIER) && c != ' ') {
  +         yyerror("macro parameter error");
  +     }
  +     else {
  +         if (!need_id || c != ' ') {
  +             len += strlen(val.s);
  +             current = realloc(current, len + 1);
  +             strcat(current,val.s);
  +         }
  +         free(val.s);
  +         c = yylex(&val,interp);
  +     }
  +    }
  +    params->name[params->num_param++] = current;
  +
  +    if (valp) *valp = val;
  +    else free(val.s);
  +
  +    return c;
  +}
  +
  +static int
  +read_macro (YYSTYPE *valp, void *interp)
  +{
  +    int c;
  +    struct macro_t *m = macros + num_macros;
  +    int start_cond;
  +
  +    temp_buffer[0]='\0';
  +
  +    start_cond = YY_START;
  +    BEGIN(macro);
  +
  +    c = yylex(NULL, interp);
  +    if (c != ' ') yyerror("macro error");
  +
  +    c = yylex(valp, interp);
  +    if (c != IDENTIFIER) yyerror("macro error");
  +
  +    m->name = valp->s;
  +
  +    /* white space is allowed between macro and opening paren) */
  +    c = yylex_skip(valp, interp, " ");
  +
  +    if (c == '(') {
  +     free(valp->s);
  +
  +     c = read_params(NULL, interp, &m->params, 1);
  +     if (c != ')') yyerror("macro parameter: \")\" expected");
  +
  +     c = yylex(valp, interp);
  +    }
  +
  +    while (c != ENDM) {
  +     if (c == 0) yyerror("file ended before macro complete");
  +
  +     strcat(temp_buffer, valp->s);
  +     free(valp->s);
  +
  +        c = yylex(valp, interp);
  +    }
  +    free(valp->s);
  +
  +    BEGIN(start_cond);
  +
  +    macros[num_macros].expansion = str_dup(temp_buffer);
  +
  +    num_macros++;
  +    return MACRO;
  +}
  +
  +static char *
  +find_macro_param (const char *name)
  +{
  +    struct macro_frame_t *f;
  +    int i;
  +
  +    for (f = frames; f; f = f->next) {
  +     if (f->params) {
  +         for (i = 0; i < f->params->num_param; i++) {
  +             if (strcmp(f->params->name[i], name) == 0) {
  +                 return f->expansion.name[i];
  +             }
  +         }
  +     }
  +    }
  +
  +    return NULL;
  +}
  +
  +static struct macro_t *
  +find_macro (const char* name)
  +{
  +    int i;
  +
  +    for (i = 0; i < num_macros; i++) {
  +     if (strcmp(name, macros[i].name) == 0) return macros + i;
  +    }
  +
  +    return NULL;
  +}
  +
  +static int
  +expand_macro (YYSTYPE *valp, void *interp, const char *name)
  +{
  +    int c;
  +    struct macro_frame_t *frame;
  +    struct macro_t *m;
  +    const char *expansion;
  +    int start_cond;
  +
  +    frame = new_frame();
  +
  +    expansion = find_macro_param(name);
  +    if (expansion) {
  +     scan_string(frame, expansion);
  +     return 1;
  +    }
  +
  +    m = find_macro(name);
  +    frame->params = &m->params;
  +    if (m) {
  +     /* whitespace can be savely ignored */
  +     do {
  +         c = input();
  +     } while (c == ' ' || c == '\t');
  +
  +     if (c != '(') {
  +         unput(c);
  +         if (m->params.num_param != 0) yyerror ("Missing macro parameter");
  +         scan_string(frame, m->expansion);
       return 1;
   }
   
  +     start_cond = YY_START;
  +     BEGIN(macro);
  +
  +     read_params (NULL, interp, &frame->expansion, 0);
  +
  +     BEGIN(start_cond);
  +
  +     if (frame->expansion.num_param == 0 && m->params.num_param == 1) {
  +         frame->expansion.name[0] = str_dup("");
  +         frame->expansion.num_param = 1;
  +     }
  +
  +     if (frame->expansion.num_param != m->params.num_param) {
  +         yyerror ("Wrong number of macro arguments");
  +     }
  +
  +     scan_string(frame, m->expansion);
  +     return 1;
  +    }
  +
  +    return 0;
  +}
  +
  +static void
  +include_file (const char *file_name)
  +{
  +    struct macro_frame_t *frame;
  +    FILE *file;
  +
  +    frame = new_frame();
  +
  +    file = fopen(file_name, "r");
  +    if (!file) yyerror ("file not found");
  +
  +    scan_file (frame, file);
  +}
  +
  +static void
  +scan_file (struct macro_frame_t *frame, FILE *file)
  +{
  +    frame->buffer = YY_CURRENT_BUFFER;
  +    frame->next = frames;
  +    frames = frame;
  +
  +    yy_switch_to_buffer(yy_create_buffer(file, YY_BUF_SIZE));
  +}
  +
  +/*
  + * Local variables:
  + * c-indentation-style: bsd
  + * c-basic-offset: 4
  + * indent-tabs-mode: nil
  + * End:
  + *
  + * vim: expandtab shiftwidth=4:
  + */
  
  
  
  1.45      +12 -7     parrot/languages/imcc/imcc.y
  
  Index: imcc.y
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imcc.y,v
  retrieving revision 1.44
  retrieving revision 1.45
  diff -u -w -r1.44 -r1.45
  --- imcc.y    11 Feb 2003 11:34:36 -0000      1.44
  +++ imcc.y    17 Feb 2003 13:56:36 -0000      1.45
  @@ -169,6 +169,7 @@
       return 0;
   }
   
  +#if 0
   /* return the index of a PMC class */
   static int
   get_pmc_num(struct Parrot_Interp *interpreter, char *pmc_type)
  @@ -191,6 +192,7 @@
       r =  mk_const(str_dup(buf), 'I');
       return r;
   }
  +#endif
   
   static Instruction *
   multi_keyed(struct Parrot_Interp *interpreter,char *name,
  @@ -408,14 +410,14 @@
   
   %token <t> CALL GOTO ARG IF UNLESS NEW END SAVEALL RESTOREALL
   %token <t> SUB NAMESPACE ENDNAMESPACE CLASS ENDCLASS SYM LOCAL CONST PARAM
  -%token <t> INC DEC
  +%token <t> CONSTANT INC DEC
   %token <t> SHIFT_LEFT SHIFT_RIGHT INTV FLOATV STRINGV DEFINED LOG_XOR
   %token <t> RELOP_EQ RELOP_NE RELOP_GT RELOP_GTE RELOP_LT RELOP_LTE
   %token <t> GLOBAL ADDR CLONE RESULT RETURN POW SHIFT_RIGHT_U LOG_AND LOG_OR
   %token <t> COMMA ESUB
   %token <s> LABEL
   %token <t> EMIT EOM
  -%token <s> IREG NREG SREG PREG IDENTIFIER STRINGC INTC FLOATC REG MACRO
  +%token <s> IREG NREG SREG PREG IDENTIFIER STRINGC INTC FLOATC REG MACRO ENDM
   %token <s> PARROT_OP
   %type <t> type
   %type <i> program sub sub_start emit
  @@ -425,7 +427,7 @@
   %type <sr> target reg const var rc string
   %type <sr> key keylist _keylist newtype
   %type <sr> vars _vars var_or_i _var_or_i
  -%type <i> pasmcode pasmline pasm_inst
  +%type <i> pasmcode pasmline pasm_inst constant_def
   %type <sr> pasm_args lhs
   %token <sr> VAR
   
  @@ -448,16 +450,21 @@
       ;
   
   pasmline: labels  pasm_inst '\n'  { $$ = 0; }
  +    | MACRO '\n'                  { $$ = 0; }
  +    | constant_def
       ;
  +
   pasm_inst: {clear_state();}
          PARROT_OP pasm_args           { $$ = iANY(interp, $2,0,regs,1); free($2); }
       | /* none */                               { $$ = 0;}
  -
       ;
   pasm_args:
       vars
       ;
   
  +constant_def: CONSTANT IDENTIFIER const { /* printf ("%s\n", $1); */ }
  +    ;
  +
   emit:
         EMIT                              { open_comp_unit(); }
         pasmcode
  @@ -586,8 +593,7 @@
       ;
   
   newtype:
  -     MACRO                             { $$ = macro(interp, $1); free($1); }
  -    | const
  +    const
       ;
   
   if_statement:
  @@ -638,7 +644,6 @@
          IDENTIFIER                    { $$ = mk_address($1, U_add_once); }
       |  PARROT_OP                        { $$ = mk_address($1, U_add_once); }
       |  var
  -    | MACRO                             { $$ = macro(interp, $1); free($1); }
       ;
   
   var:   VAR
  
  
  
  1.25      +6 -1      parrot/languages/imcc/instructions.c
  
  Index: instructions.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/instructions.c,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -w -r1.24 -r1.25
  --- instructions.c    10 Feb 2003 10:04:15 -0000      1.24
  +++ instructions.c    17 Feb 2003 13:56:36 -0000      1.25
  @@ -212,7 +212,10 @@
   
       next = ins->next;
       prev = ins->prev;
  +    if (prev)
       prev->next = next;
  +    else
  +        instructions = next;
       if (next)
           next->prev = prev;
       if (needs_freeing)
  @@ -244,6 +247,8 @@
       Instruction *prev = ins->prev;
       if (prev)
           prev->next = tmp;
  +    else
  +        instructions = tmp;
       tmp->prev = prev;
       tmp->next = ins->next;
       if (ins->next)
  
  
  
  1.16      +1 -2      parrot/languages/imcc/main.c
  
  Index: main.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/main.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -w -r1.15 -r1.16
  --- main.c    10 Feb 2003 10:04:15 -0000      1.15
  +++ main.c    17 Feb 2003 13:56:36 -0000      1.16
  @@ -216,7 +216,6 @@
           }
           ext = strrchr(sourcefile, '.');
           if (ext && strcmp (ext, ".pasm") == 0) {
  -            if (*optimizer_opt == '0')
                   pasm_file = 1;
               if (output)
                   write_pbc = 1;
  
  
  
  1.15      +522 -26   parrot/languages/imcc/optimizer.c
  
  Index: optimizer.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/optimizer.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -w -r1.14 -r1.15
  --- optimizer.c       10 Feb 2003 10:04:15 -0000      1.14
  +++ optimizer.c       17 Feb 2003 13:56:36 -0000      1.15
  @@ -12,35 +12,30 @@
   
   
   /*
  - * current default optimization is -O1 (s. imcc.y)
  - *
  - *
    * pre_optimizer
    * -------------
    *
    * runs before CFG is built
    *
    * if_branch ... converts if/branch/label like so:
  - *
  - *      if x, L1          unless x, L2
  - *      branch L2         ---
  - *    L1:               L2:
  - *    ...
  - *    L2:
  - *
    * unused_label ... deletes them (as L1 above)
  - *
  - * stages currently not needed by ocde from perl6:
  - * jump optimization (jumps to jumps ...)
  - *
  + * branch_branch ... jump optimization (jumps to jumps ...)
  + * strength_reduce ... rewrites e.g add Ix, Ix, y => add Ix, y
  + * subst_constants ... rewrite e.g. add_i_ic_ic
    *
    * optimizer
    * ---------
    *
  - * TODO e.g. constant_propagation
  + * runs with CFG and life info
    *
  + * used_once ... deletes assignments, when LHS is unused
  + * dead_code_remove ... deletes e.g. blocks that are not entered from
  + *                      somewhere or ins after a branch, which aren't
  + *                      reachable
  + * loop_optimization ... pull invariants out of loops
  + * TODO e.g. constant_propagation
    *
  - *  post_optimizer
  + * TODO post_optimizer
    *  ---------------
    *
    *  runs after register alloocation
  @@ -53,6 +48,11 @@
   static void branch_branch(void);
   static void unused_label(void);
   static void strength_reduce(struct Parrot_Interp *interp);
  +static void subst_constants_mix(struct Parrot_Interp *interp);
  +static void subst_constants_umix(struct Parrot_Interp *interp);
  +static void subst_constants(struct Parrot_Interp *interp);
  +static void subst_constants_c(struct Parrot_Interp *interp);
  +static void subst_constants_if(struct Parrot_Interp *interp);
   
   static int used_once(void);
   static int loop_optimization(struct Parrot_Interp *);
  @@ -60,11 +60,16 @@
   
   void pre_optimize(struct Parrot_Interp *interp) {
       if (*optimizer_opt != '0') {      /* XXX */
  +        subst_constants_mix(interp);
  +        subst_constants_umix(interp);
  +        subst_constants(interp);
  +        subst_constants_c(interp);
  +        subst_constants_if(interp);
  +        strength_reduce(interp);
           if_branch(interp);
           branch_branch();
           /* XXX cfg / loop detection breaks e.g. in t/compiler/5_3 */
           unused_label();
  -        strength_reduce(interp);
       }
   }
   
  @@ -123,18 +128,19 @@
       if (!last->next)
           return;
       for (ins = last->next; ins; ) {
  -        if ((last->type & ITBRANCH) &&          /* if ...Lx */
  -                (ins->type & IF_goto) &&        /* branch Ly*/
  +        if ((last->type & ITBRANCH) &&          /* if ...L1 */
  +                (ins->type & IF_goto) &&        /* branch L2*/
                   (reg = get_branch_regno(last)) >= 0) {
               SymReg * br_dest = last->r[reg];
               if (ins->next &&
  -                    (ins->next->type & ITLABEL) &&    /* Lx */
  +                    (ins->next->type & ITLABEL) &&    /* L1 */
                       ins->next->r[0] == br_dest) {
                   const char * neg_op;
                   SymReg * go = get_branch_reg(ins);
                   int args;
   
  -                debug(DEBUG_OPT1,"if_branch %s ... %s\n", last->op, br_dest->name);
  +                debug(DEBUG_OPT1,"if_branch %s ... %s\n",
  +                        last->op, br_dest->name);
                   /* find the negated op (e.g if->unless, ne->eq ... */
                   if ((neg_op = get_neg_op(last->op, &args)) != 0) {
                       Instruction * tmp;
  @@ -232,28 +238,518 @@
       }
   }
   
  +/* these are run after constant simplification, so it is
  + * guaranteed, that one operand is non constant, if opsize == 4
  + */
   static void strength_reduce(struct Parrot_Interp *interp)
   {
       Instruction *ins, *tmp;
       const char *ops[] = { "add", "sub", "mul", "div" };
  -    int i;
  +    int i, found;
  +    SymReg *r;
   
       for (ins = instructions; ins; ins = ins->next) {
           /*
  +         * add Ix, Ix, Iy => add Ix, Iy
            * sub Ix, Ix, Iy => sub Ix, Iy
  +         * ...
            */
  -        for (i = 0; i < 4; i++)
  -            if (!strcmp(ins->op, ops[i]) && ins->opsize == 4 &&
  -                    ins->r[0] == ins->r[1]) {
  +        found = 0;
  +        for (i = 0; i < 4; i++) {
  +            if (ins->opsize == 4 &&
  +                    ins->r[0] == ins->r[1] &&
  +                    !strcmp(ins->op, ops[i])) {
                   debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
                   ins->r[1] = ins->r[2];
                   tmp = INS(interp, ins->op, "", ins->r, 2, 0, 0);
                   debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
                   subst_ins(ins, tmp, 1);
  +                found = 1;
  +                break;
  +            }
  +        }
  +        if (found)
  +            continue;
  +        /*
  +         * mul Ix, Iy, 0 => set Ix, 0
  +         * mul Ix, 0, Iy => set Ix, 0
  +         * mul Ix, 0     => set Ix, 0
  +         */
  +        if ( ( ( ins->opsize >= 3 &&
  +                        ins->r[1]->type == VTCONST &&
  +                        atof(ins->r[1]->name) == 0.0) ||
  +                    (ins->opsize == 4 &&
  +                     ins->r[2]->type == VTCONST &&
  +                     atof(ins->r[2]->name) == 0.0)) &&
  +                !strcmp(ins->op, "mul")) {
  +            debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +            r = mk_const(ins->r[0]->set == 'I' ? str_dup("0") :
  +                    str_dup("0.000000"),
  +                    ins->r[0]->set);
  +            --ins->r[1]->use_count;
  +            if (ins->opsize == 4)
  +                --ins->r[2]->use_count;
  +            ins->r[1] = r;
  +            tmp = INS(interp, "set", "", ins->r, 2, 0, 0);
  +            debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +            subst_ins(ins, tmp, 1);
  +            continue;
  +        }
  +        /*
  +         * mul Ix, Iy, 1 => set Ix, Iy
  +         * mul Ix, 1, Iy => set Ix, Iy
  +         * mul Ix, 1     => delete
  +         */
  +        if ( ( ( ins->opsize >= 3 &&
  +                        ins->r[1]->type == VTCONST &&
  +                        atof(ins->r[1]->name) == 1.0) ||
  +                    (ins->opsize == 4 &&
  +                     ins->r[2]->type == VTCONST &&
  +                     atof(ins->r[2]->name) == 1.0)) &&
  +                !strcmp(ins->op, "mul")) {
  +set_it:
  +            debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +            if (ins->opsize == 3) {
  +                /* mul Ix, 1 */
  +                delete_ins(ins, 1);
  +                debug(DEBUG_OPT1, "deleted\n");
  +                continue;
  +            }
  +            if (ins->r[1]->type == VTCONST) {
  +                --ins->r[1]->use_count;
  +                ins->r[1] = ins->r[2];
  +            }
  +            else {
  +                --ins->r[2]->use_count;
  +            }
  +            tmp = INS(interp, "set", "", ins->r, 2, 0, 0);
  +            debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +            subst_ins(ins, tmp, 1);
  +            continue;
  +        }
  +        /*
  +         * div Ix, Iy, 1 => set Ix, Iy
  +         * div Ix, 1     => delete
  +         */
  +        if ( ( ( ins->opsize == 3 &&
  +                        ins->r[1]->type == VTCONST &&
  +                        atof(ins->r[1]->name) == 1.0) ||
  +                    (ins->opsize == 4 &&
  +                     ins->r[2]->type == VTCONST &&
  +                     atof(ins->r[2]->name) == 1.0)) &&
  +                !strcmp(ins->op, "div")) {
  +            goto set_it;
  +        }
  +    }
  +}
  +
  +/*
  + * rewrite e.g. add_n_nc_ic => add_n_nc_nc
  + */
  +static void
  +subst_constants_mix(struct Parrot_Interp *interp)
  +{
  +    Instruction *ins, *tmp;
  +    const char *ops[] = {
  +        "add", "sub", "mul", "div", "pow", "atan"
  +    };
  +    size_t i;
  +    char b[128];
  +    SymReg *r;
  +
  +    for (ins = instructions; ins; ins = ins->next) {
  +        for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
  +            /* TODO compare ins->opnum with a list of instructions
  +             * containing add_n_nc_ic, ...
  +             */
  +            if (!strcmp(ins->op, ops[i]) && ins->opsize == 4 &&
  +                    ins->r[1]->type == VTCONST &&
  +                    ins->r[1]->set == 'N' &&
  +                    ins->r[2]->type == VTCONST &&
  +                    ins->r[2]->set == 'I') {
  +                debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +                sprintf(b, FLOATVAL_FMT,
  +                        (FLOATVAL)atof(ins->r[2]->name));
  +                r = mk_const(str_dup(b), 'N');
  +                --ins->r[2]->use_count;
  +                ins->r[2] = r;
  +                tmp = INS(interp, ins->op, "", ins->r, 3, 0, 0);
  +                debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +                subst_ins(ins, tmp, 1);
  +            }
  +        }
  +    }
  +}
  +
  +/*
  + * rewrite e.g. add_n_ic => add_n_nc
  + */
  +static void
  +subst_constants_umix(struct Parrot_Interp *interp)
  +{
  +    Instruction *ins, *tmp;
  +    const char *ops[] = {
  +        "add", "div", "mul", "sub", "set"
  +    };
  +    size_t i;
  +    char b[128];
  +    SymReg *r;
  +
  +    for (ins = instructions; ins; ins = ins->next) {
  +        for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
  +            /* TODO compare ins->opnum with a list of instructions
  +             * containing add_n_ic, ...
  +             */
  +            if (ins->opsize == 3 &&
  +                    ins->r[0]->set == 'N' &&
  +                    ins->r[1]->type == VTCONST &&
  +                    ins->r[1]->set == 'I' &&
  +                    !strcmp(ins->op, ops[i])) {
  +                debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +                sprintf(b, FLOATVAL_FMT,
  +                        (FLOATVAL)atof(ins->r[1]->name));
  +                r = mk_const(str_dup(b), 'N');
  +                --ins->r[1]->use_count;
  +                ins->r[1] = r;
  +                tmp = INS(interp, ins->op, "", ins->r, 2, 0, 0);
  +                debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +                subst_ins(ins, tmp, 1);
  +            }
  +        }
  +    }
  +}
  +
  +static void
  +eval_ins(struct Parrot_Interp *interpreter, Instruction *ins, size_t ops)
  +{
  +    opcode_t eval[4];
  +    char op[20];
  +    int opnum;
  +    size_t i;
  +
  +    /*
  +     * find instruction e.g. add_i_ic_ic => add_i_i_i
  +     */
  +    if (ops == 4)
  +        sprintf(op, "%s_%c_%c_%c", ins->op, tolower(ins->r[0]->set),
  +                tolower(ins->r[1]->set), tolower(ins->r[2]->set));
  +    else
  +        sprintf(op, "%s_%c_%c", ins->op, tolower(ins->r[0]->set),
  +                tolower(ins->r[1]->set));
  +    opnum = interpreter->op_lib->op_code(op, 1);
  +    if (opnum < 0)
  +        fatal(1, "eval_ins", "op '%s' not found\n", op);
  +    /* now fill registers */
  +    for (i = 0; i < ops; i++) {
  +        switch (interpreter->op_info_table[opnum].types[i]) {
  +            case PARROT_ARG_OP:
  +                eval[i] = opnum;
  +                break;
  +            case PARROT_ARG_I:
  +            case PARROT_ARG_N:
  +                eval[i] = i - 1;        /* result in I0/N0 */
  +                if (i > 1) {    /* fill source regs */
  +                    switch (ins->r[i-1]->set) {
  +                        case 'I':
  +                            interpreter->ctx.int_reg.registers[i-1] =
  +                                (INTVAL)atoi(ins->r[i-1]->name);
  +                            break;
  +                        case 'N':
  +                            interpreter->ctx.num_reg.registers[i-1] =
  +                                (FLOATVAL)atof(ins->r[i-1]->name);
  +                            break;
  +                    }
  +                }
  +                break;
  +            default:
  +                fatal(1, "eval_ins", "invalid arg #%d for op '%s' not found\n",
  +                        i, op);
  +        }
  +    }
  +
  +    /* eval the opcode */
  +    (interpreter->op_func_table[opnum]) (eval, interpreter);
  +}
  +
  +/*
  + * rewrite e.g. add_n_nc_nc => set_n_nc
  + *          or  abs_i_ic => set_i_ic
  + */
  +static void
  +subst_constants(struct Parrot_Interp *interp)
  +{
  +    Instruction *ins, *tmp;
  +    const char *ops[] = {
  +        "add", "sub", "mul", "div", "cmod", "mod", "pow", "atan"
  +        "shr", "srl", "lsr",
  +        "band", "bor", "bxor",
  +        "and", "or", "xor"
  +    };
  +    const char *ops2[] = {
  +        "abs", "neg", "acos", "asec", "asin",
  +        "atan", "cos", "cosh", "exp", "ln", "log10", "log2", "sec",
  +        "sech", "sin", "sinh", "tan", "tanh", "fact"
  +    };
  +    size_t i;
  +    char b[128];
  +    SymReg *r;
  +    struct Parrot_Context *ctx;
  +    int found;
  +
  +    /* save interpreter ctx */
  +    ctx = mem_sys_allocate(sizeof(struct Parrot_Context));
  +    mem_sys_memcopy(ctx, &interp->ctx, sizeof(struct Parrot_Context));
  +
  +    for (ins = instructions; ins; ins = ins->next) {
  +        found = 0;
  +        for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
  +            /* TODO compare ins->opnum with a list of instructions
  +             * containing add_i_ic_ic, add_n_nc_nc ...
  +             */
  +            if (ins->opsize == 4 &&
  +                    ins->r[1]->type == VTCONST &&
  +                    ins->r[2]->type == VTCONST &&
  +                    !strcmp(ins->op, ops[i])) {
  +                found = 1;
  +                break;
  +            }
  +        }
  +        for (i = 0; !found && i < sizeof(ops2)/sizeof(ops2[0]); i++) {
  +            if (ins->opsize == 3 &&
  +                    ins->r[1]->type == VTCONST &&
  +                    !strcmp(ins->op, ops2[i])) {
  +                found = 1;
  +                break;
  +            }
  +        }
  +        if (!found)
  +            break;
  +        debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +        /* we construct a parrot instruction
  +         * here and let parrot do the calculation in a
  +         * separate context and make a constant
  +         * from the result
  +         */
  +        eval_ins(interp, ins, ins->opsize);
  +        /* result is in I0/N0 */
  +        switch (ins->r[0]->set) {
  +            case 'I':
  +                sprintf(b, INTVAL_FMT, interp->ctx.int_reg.registers[0]);
  +                break;
  +            case 'N':   /* FIXME precision/exponent */
  +                sprintf(b, FLOATVAL_FMT, interp->ctx.num_reg.registers[0]);
  +                break;
  +        }
  +        r = mk_const(str_dup(b), ins->r[0]->set);
  +        --ins->r[1]->use_count;
  +        if (ins->opsize == 4)
  +            --ins->r[2]->use_count;
  +        ins->r[1] = r;
  +        tmp = INS(interp, "set", "", ins->r, 2, 0, 0);
  +        debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +        subst_ins(ins, tmp, 1);
  +    }
  +    mem_sys_memcopy(&interp->ctx, ctx, sizeof(struct Parrot_Context));
  +    mem_sys_free(ctx);
  +}
  +
  +/*
  + * rewrite e.g. eq_ic_ic_ic => branch_ic/nothing
  + */
  +static void
  +subst_constants_c(struct Parrot_Interp *interp)
  +{
  +    Instruction *ins, *tmp;
  +    const char *ops[] = { "eq", "ne", "gt", "ge", "lt", "le" };
  +    size_t i;
  +    int res;
  +
  +    for (ins = instructions; ins; ins = ins->next) {
  +        for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
  +            /* TODO s. above */
  +            if (ins->opsize == 4 &&
  +                    ins->r[0]->type == VTCONST &&
  +                    ins->r[1]->type == VTCONST &&
  +                    !strcmp(ins->op, ops[i])) {
  +                debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +                switch (i) {
  +                    case 0:     /* eq */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = (atoi(ins->r[0]->name) ==
  +                                        atoi(ins->r[1]->name));
  +do_res:
  +                                --ins->r[0]->use_count;
  +                                --ins->r[1]->use_count;
  +                                if (res) {
  +                                    ins->r[0] = ins->r[2];
  +                                    tmp = INS(interp, "branch", "", ins->r,
  +                                            1, 0, 0);
  +                                    debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +                                    subst_ins(ins, tmp, 1);
  +                                }
  +                                else {
  +                                    debug(DEBUG_OPT1, "deleted\n");
  +                                    delete_ins(ins, 1);
  +                                }
  +                                break;
  +                            case 'N':
  +                                res = (atof(ins->r[0]->name) ==
  +                                        atof(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'S':
  +                                res = !strcmp(ins->r[0]->name,
  +                                        ins->r[1]->name);
  +                                goto do_res;
  +                        }
  +                        break;
  +                    case 1:     /* ne */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = (atoi(ins->r[0]->name) !=
  +                                        atoi(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'N':
  +                                res = (atof(ins->r[0]->name) !=
  +                                        atof(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'S':
  +                                res = strcmp(ins->r[0]->name,
  +                                        ins->r[1]->name);
  +                                goto do_res;
  +                        }
  +                        break;
  +                    case 2:     /* gt */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = (atoi(ins->r[0]->name) >
  +                                        atoi(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'N':
  +                                res = (atof(ins->r[0]->name) >
  +                                        atof(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'S':
  +                                res = strcmp(ins->r[0]->name,
  +                                        ins->r[1]->name) > 0;
  +                                goto do_res;
  +                        }
  +                        break;
  +                    case 3:     /* ge */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = (atoi(ins->r[0]->name) >=
  +                                        atoi(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'N':
  +                                res = (atof(ins->r[0]->name) >=
  +                                        atof(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'S':
  +                                res = strcmp(ins->r[0]->name,
  +                                        ins->r[1]->name) >= 0;
  +                                goto do_res;
  +                        }
  +                        break;
  +                    case 4:     /* lt */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = (atoi(ins->r[0]->name) <
  +                                        atoi(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'N':
  +                                res = (atof(ins->r[0]->name) <
  +                                        atof(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'S':
  +                                res = strcmp(ins->r[0]->name,
  +                                        ins->r[1]->name) < 0;
  +                                goto do_res;
  +                        }
  +                        break;
  +                    case 5:     /* le */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = (atoi(ins->r[0]->name) <=
  +                                        atoi(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'N':
  +                                res = (atof(ins->r[0]->name) <=
  +                                        atof(ins->r[1]->name));
  +                                goto do_res;
  +                            case 'S':
  +                                res = strcmp(ins->r[0]->name,
  +                                        ins->r[1]->name) <= 0;
  +                                goto do_res;
  +                        }
  +                        break;
  +                }
  +            }
  +        }
               }
       }
   
  +/*
  + * rewrite e.g. if_ic_ic => branch_ic/nothing
  + */
  +static void
  +subst_constants_if(struct Parrot_Interp *interp)
  +{
  +    Instruction *ins, *tmp;
  +    const char *ops[] = { "if", "unless" };
  +    size_t i;
  +    int res;
  +    char *s;
  +
  +    for (ins = instructions; ins; ins = ins->next) {
  +        for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
  +            /* TODO s. above */
  +            if (ins->opsize == 3 &&
  +                    ins->r[0]->type == VTCONST &&
  +                    !strcmp(ins->op, ops[i])) {
  +                debug(DEBUG_OPT1, "opt1 %s => ", ins_string(ins));
  +                switch (i) {
  +                    case 0:     /* if */
  +                    case 1:     /* unless */
  +                        switch (ins->r[0]->set) {
  +                            case 'I':
  +                                res = atoi(ins->r[0]->name);
  +do_res:
  +                                --ins->r[0]->use_count;
  +                                if (i)
  +                                    res = !res;
  +                                if (res) {
  +                                    ins->r[0] = ins->r[1];
  +                                    tmp = INS(interp, "branch", "", ins->r,
  +                                            1, 0, 0);
  +                                    debug(DEBUG_OPT1, "%s\n", ins_string(tmp));
  +                                    subst_ins(ins, tmp, 1);
  +                                }
  +                                else {
  +                                    debug(DEBUG_OPT1, "deleted\n");
  +                                    delete_ins(ins, 1);
   }
  +                                break;
  +                            case 'N':
  +                                res = atof(ins->r[1]->name) != 0.0;
  +                                goto do_res;
  +                            case 'S':
  +                                break;
  +                                /* TODO strings have quote marks around them,
  +                                 * strip these in lexer
  +                                 */
  +                                s = ins->r[0]->name;
  +                                res = *s && (*s != '0' || s[1]);
  +                                goto do_res;
  +                        }
  +                        break;
  +                }
  +            }
  +        }
  +    }
  +}
  +
  +
   /* optimizations with CFG built */
   int dead_code_remove(void)
   {
  
  
  
  1.9       +5 -2      parrot/languages/imcc/parser_util.c
  
  Index: parser_util.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/parser_util.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -w -r1.8 -r1.9
  --- parser_util.c     31 Jan 2003 10:54:08 -0000      1.8
  +++ parser_util.c     17 Feb 2003 13:56:36 -0000      1.9
  @@ -29,10 +29,13 @@
   iNEW(struct Parrot_Interp *interpreter, SymReg * r0, char * type, int emit)
   {
       char fmt[256];
  -    SymReg *pmc = macro(interpreter, type);
  +    SymReg *pmc;
  +    int pmc_num = get_pmc_num(interpreter, type);
  +    sprintf(fmt, "%d", pmc_num);
  +    pmc = mk_const(str_dup(fmt), 'I');
       /* XXX check, if type exists, but aove keyed search
        * gives 0 for non existing  PMCs */
  -    sprintf(fmt, "%%s, %d\t # .%s", atoi(pmc->name), type);
  +    sprintf(fmt, "%%s, %d\t # .%s", pmc_num, type);
       r0->usage = U_NEW;
       if (!strcmp(type, "PerlArray") || !strcmp(type, "PerlHash"))
           r0->usage |= U_KEYED;
  
  
  
  1.26      +4 -1      parrot/languages/imcc/pbc.c
  
  Index: pbc.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/pbc.c,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -w -r1.25 -r1.26
  --- pbc.c     15 Feb 2003 11:25:33 -0000      1.25
  +++ pbc.c     17 Feb 2003 13:56:36 -0000      1.26
  @@ -610,6 +610,8 @@
   {
       if (r->color >= 0)
           return;
  +    if (r->use_count <= 0)
  +        return;
       switch (r->set) {
           case 'I':
               if (r->name[0] == '0' && r->name[1] == 'x')
  @@ -633,7 +635,8 @@
               break;
       }
       if (r /*&& r->set != 'I' */)
  -        debug(DEBUG_PBC_CONST,"const %s\tcolor %d\n", r->name, r->color);
  +        debug(DEBUG_PBC_CONST,"const %s\tcolor %d use_count %d\n",
  +                r->name, r->color, r->use_count);
   
   }
   /* store a constants idx for later reuse */
  
  
  
  1.15      +5 -2      parrot/languages/imcc/symreg.c
  
  Index: symreg.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/symreg.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -w -r1.14 -r1.15
  --- symreg.c  7 Feb 2003 14:05:51 -0000       1.14
  +++ symreg.c  17 Feb 2003 13:56:36 -0000      1.15
  @@ -127,6 +127,7 @@
   SymReg * _mk_const(SymReg *hsh[], char * name, char t) {
       SymReg * r = _mk_symreg(hsh, name, t);
       r->type = VTCONST;
  +    r->use_count++;
       return r;
   }
   
  @@ -150,9 +151,10 @@
               r->type == VTADDRESS &&
               r->lhs_use_count            /* we use this for labes/subs */
         ) {
  -        if (uniq == U_add_uniq_label)
  +        if (uniq == U_add_uniq_label) {
               fataly(1, "mk_address", line,
                       "Label '%s' already defined\n", name);
  +        }
           else if (uniq == U_add_uniq_sub)
               fataly(1, "mk_address", line,
                       "Subroutine '%s' already defined\n", name);
  @@ -242,6 +244,7 @@
       if (!keychain)
           fatal(1, "link_keys", "Out of mem\n");
       keychain->type = VTCONST;
  +    ++keychain->use_count;
       key = keychain;
       for (i = 0; i < nargs; i++) {
           /* if any component is a variable, we need to track it in
  
  
  
  1.4       +402 -1    parrot/languages/imcc/t/imcpasm/opt1.t
  
  Index: opt1.t
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/t/imcpasm/opt1.t,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -w -r1.3 -r1.4
  --- opt1.t    8 Feb 2003 17:16:21 -0000       1.3
  +++ opt1.t    17 Feb 2003 13:56:38 -0000      1.4
  @@ -1,6 +1,6 @@
   #!perl
   use strict;
  -use TestCompiler tests => 6;
  +use TestCompiler tests => 47;
   use Test::More qw(skip);
   
   # these tests are run with -O1 by TestCompiler and show
  @@ -98,3 +98,404 @@
      end
   OUT
   
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant add");
  +   add I0, 10, 15
  +   add N0, 10.0, 15.0
  +   end
  +CODE
  +   set I0, 25
  +   set N0, 25.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant sub");
  +   sub I0, 10, 15
  +   sub N0, 10.0, 15.0
  +   end
  +CODE
  +   set I0, -5
  +   set N0, -5.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant mul");
  +   mul I0, 10, 15
  +   mul N0, 10.0, 15.0
  +   end
  +CODE
  +   set I0, 150
  +   set N0, 150.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant div");
  +   div I0, 10, 5
  +   div N0, 10.0, 5.0
  +   end
  +CODE
  +   set I0, 2
  +   set N0, 2.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant cmod");
  +   cmod I0, 33, 10
  +   cmod N0, 33.0, 10.0
  +   end
  +CODE
  +   set I0, 3
  +   set N0, 3.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant mod");
  +   mod I0, 33, 10
  +   mod N0, 33.0, 10.0
  +   end
  +CODE
  +   set I0, 3
  +   set N0, 3.000000
  +   end
  +OUT
  +
  +##############################
  +SKIP: {
  +skip("constant concat N/Y", 1);
  +output_is(<<'CODE', <<'OUT', "constant concat");
  +   concat S0, "Parrot ", "rocks"
  +   end
  +CODE
  +   set S0, "Parrot rocks"
  +   end
  +OUT
  +}
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant eq taken");
  +   eq 10, 10, L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant eq not taken");
  +   eq 10, 20, L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant eq taken");
  +   eq 10.0, 10.0, L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant eq not taken");
  +   eq 10.0, 20.0, L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant eq taken");
  +   eq "xy", "xy", L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant eq not taken");
  +   eq "ab", "ba", L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant ne taken");
  +   ne 10, 20, L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant ne not taken");
  +   ne 10, 10, L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant gt taken");
  +   gt "xy", "ap", L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant gt not taken");
  +   gt "ab", "ba", L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant ge taken");
  +   ge "xy", "xy", L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant ge not taken");
  +   gt "ab", "ba", L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant lt taken");
  +   lt "xx", "xy", L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant lt not taken");
  +   lt "ba", "ba", L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant le taken");
  +   le "xy", "xy", L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant le not taken");
  +   le "bb", "ba", L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant if taken");
  +   if 10, L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant if not taken");
  +   if 0, L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant unless taken");
  +   unless 0, L1
  +   set I0, 5
  +L1:end
  +CODE
  +L1:
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant unless not taken");
  +   unless 1, L1
  +   set I0, 5
  +L1:end
  +CODE
  +   set I0, 5
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant mix add");
  +   add N0, 10.0, 15
  +   end
  +CODE
  +   set N0, 25.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant unary abs");
  +   abs I0, -10
  +   end
  +CODE
  +   set I0, 10
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "constant set");
  +   set N0, 5
  +   end
  +CODE
  +   set N0, 5.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul I, 0");
  +   mul I0, 0
  +   end
  +CODE
  +   set I0, 0
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul I, I, 0");
  +   mul I0, I1, 0
  +   end
  +CODE
  +   set I0, 0
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul I, 0, I");
  +   mul I0, 0, I1
  +   end
  +CODE
  +   set I0, 0
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul N, 0, N");
  +   mul N0, 0.0, N1
  +   end
  +CODE
  +   set N0, 0.000000
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul I, 1");
  +   mul I0, 1
  +   end
  +CODE
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul I, I, 1");
  +   mul I0, I1, 1
  +   end
  +CODE
  +   set I0, I1
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul I, 1, I");
  +   mul I0, 1, I1
  +   end
  +CODE
  +   set I0,  I1
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength mul N, 1, N");
  +   mul N0, 1.0, N1
  +   end
  +CODE
  +   set N0, N1
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength div I, 1");
  +   div I0, 1
  +   end
  +CODE
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength div I, I, 1");
  +   div I0, I1, 1
  +   end
  +CODE
  +   set I0, I1
  +   end
  +OUT
  +
  +##############################
  +output_is(<<'CODE', <<'OUT', "strength div N, N, 1");
  +   div N0, N1, 1
  +   end
  +CODE
  +   set N0, N1
  +   end
  +OUT
  
  
  


Reply via email to