Keep more data around about ir instructions. Implement a half-baked type
authorDavid Given <dg@cowlark.com>
Mon, 26 Sep 2016 20:12:46 +0000 (22:12 +0200)
committerDavid Given <dg@cowlark.com>
Mon, 26 Sep 2016 20:12:46 +0000 (22:12 +0200)
inference routine to propagate information about floats up the tree, so we know
whether to put floats into special registers as early as possible.

mach/proto/mcg/ir.c
mach/proto/mcg/ir.h
mach/proto/mcg/mcg.h
mach/proto/mcg/pass_typeinference.c [new file with mode: 0644]
mach/proto/mcg/procedure.c
util/mcgg/build.lua
util/mcgg/iburg.c
util/mcgg/ir.dat
util/mcgg/ircodes.h [new file with mode: 0644]
util/mcgg/ircodes.sh

index f0c495f..9d1dab1 100644 (file)
@@ -103,9 +103,15 @@ struct ir* ir_find(struct ir* ir, int opcode)
 
 static void print_expr(char k, const struct ir* ir)
 {
-    tracef(k, "%s", ir_names[ir->opcode]);
+    tracef(k, "%s", ir_data[ir->opcode].name);
     if (ir->size)
         tracef(k, "%d", ir->size);
+    if (ir->type)
+        tracef(k, ".%s",
+            ((ir->type == IRT_INT) ? "I" :
+             (ir->type == IRT_FLOAT) ? "F" :
+             (ir->type == IRT_ANY) ? "*" :
+             "?"));
     tracef(k, "(");
 
        switch (ir->opcode)
index ac01f16..79dbfdb 100644 (file)
@@ -3,27 +3,12 @@
 
 #include "ircodes.h"
 
-enum
-{
-       IRR_LB = -1,
-       IRR_AB = -2,
-       IRR_SP = -3,
-       IRR_RR = -4,
-};
-
-enum
-{
-       IRS_1,
-       IRS_2,
-       IRS_4,
-       IRS_8
-};
-
 struct ir
 {
        int id;
        enum ir_opcode opcode;
        int size;
+       enum ir_type type;
        struct ir* left;
        struct ir* right;
        union
index 45bb691..e40bbcb 100644 (file)
@@ -123,6 +123,7 @@ extern void pass_convert_stack_ops(struct procedure* proc);
 extern void pass_remove_dead_blocks(struct procedure* proc);
 extern void pass_eliminate_trivial_blocks(struct procedure* proc);
 extern void pass_instruction_selector(struct procedure* proc);
+extern void pass_type_inference(struct procedure* proc);
 
 extern void procedure_compile(struct procedure* proc);
 
diff --git a/mach/proto/mcg/pass_typeinference.c b/mach/proto/mcg/pass_typeinference.c
new file mode 100644 (file)
index 0000000..4d57e32
--- /dev/null
@@ -0,0 +1,63 @@
+#include "mcg.h"
+
+static enum ir_type search_for_type(struct ir* ir, enum ir_type desired)
+{
+       const struct ir_data* data;
+
+       if (ir->type != IRT_UNSET)
+               return ir->type;
+
+       data = &ir_data[ir->opcode];
+       if (ir->left)
+               ir->left->type = search_for_type(ir->left, data->lefttype);
+       if (ir->right)
+               ir->right->type = search_for_type(ir->right, data->righttype);
+       
+    switch (data->returntype)
+    {
+        case IRT_ANY:
+            if (desired == IRT_FLOAT)
+                ir->opcode++;
+            return desired;
+
+        case IRT_UNSET:
+            assert(!((data->lefttype == IRT_ANY) && (data->righttype == IRT_ANY)));
+            if (((data->lefttype == IRT_ANY) && (ir->left->type == IRT_FLOAT)) ||
+                ((data->righttype == IRT_ANY) && (ir->right->type == IRT_FLOAT)))
+            {
+                ir->opcode++;
+                return IRT_FLOAT;
+            }
+            if ((data->lefttype == IRT_ANY) && (ir->left->type == IRT_ANY))
+                ir->left->type = IRT_INT;
+            if ((data->righttype == IRT_ANY) && (ir->right->type == IRT_ANY))
+                ir->right->type = IRT_INT;
+            return IRT_INT;
+
+        default:
+            return data->returntype;
+       }
+}
+
+static void push_types_up(struct basicblock* bb)
+{
+       int i;
+
+       for (i=0; i<bb->irs_count; i++)
+       {
+               struct ir* ir = bb->irs[i];
+               ir->type = search_for_type(ir, ir->type);
+       }
+}
+
+void pass_type_inference(struct procedure* proc)
+{
+    int i;
+    
+       for (i=0; i<proc->blocks_count; i++)
+               push_types_up(proc->blocks[i]);
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
+
index b0bc1a0..78d8f33 100644 (file)
@@ -29,6 +29,7 @@ void procedure_compile(struct procedure* proc)
     pass_eliminate_trivial_blocks(proc);
     pass_remove_dead_blocks(proc);
     pass_convert_stack_ops(proc);
+    pass_type_inference(proc);
 
     print_blocks('2', proc);
 
index b3ffe81..83d800e 100644 (file)
@@ -12,7 +12,7 @@ yacc {
 
 normalrule {
        name = "ircodes",
-       outleaves = { "ircodes.h", "ircodes.c" },
+       outleaves = { "ircodes-dyn.h", "ircodes.c" },
        ins = {
                "./ircodes.sh",
                "./ir.dat"
@@ -25,10 +25,15 @@ normalrule {
 clibrary {
        name = "lib",
        srcs = {
-               matching(filenamesof("+ircodes"), "%.c$")
+               matching(filenamesof("+ircodes"), "%.c$"),
+       },
+       deps = {
+               "+ircodes",
+               "./ircodes.h"
        },
        hdrs = {
                matching(filenamesof("+ircodes"), "%.h$"),
+               "./ircodes.h",
                "./mcgg.h"
        }
 }
index 9ac77ed..f29c859 100644 (file)
@@ -176,9 +176,9 @@ char* stringf(char* fmt, ...)
     return p;
 }
 
-static void registerterminal(const char* name, int iropcode, int size)
+static void registerterminal(const struct ir_data* data, int iropcode, int size)
 {
-       const char* s = (size == 0) ? name : stringf("%s%d", name, size);
+       const char* s = (size == 0) ? data->name : stringf("%s%d", data->name, size);
        int esn = ir_to_esn(iropcode, size);
 
        term(s, esn);
@@ -190,15 +190,15 @@ static void registerterminals(void)
 
        for (i=0; i<IR__COUNT; i++)
        {
-               if (ir_flags[i] & IRF_SIZED)
+               if (ir_data[i].flags & IRF_SIZED)
                {
-                       registerterminal(ir_names[i], i, 1);
-                       registerterminal(ir_names[i], i, 2);
-                       registerterminal(ir_names[i], i, 4);
-                       registerterminal(ir_names[i], i, 8);
+                       registerterminal(&ir_data[i], i, 1);
+                       registerterminal(&ir_data[i], i, 2);
+                       registerterminal(&ir_data[i], i, 4);
+                       registerterminal(&ir_data[i], i, 8);
                }
                else
-                       registerterminal(ir_names[i], i, 0);
+                       registerterminal(&ir_data[i], i, 0);
        }
 }
 
index a7487cd..46be394 100644 (file)
@@ -1,76 +1,92 @@
 # Flags:
 #   S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
 #   V: has no size (use in JUMP, CJUMP, RET forms)
+#
+# Types:
+#   I, F: integer, float
+#   A: any (will be coerced to I or F during IR postprocessing)
+#
+# Any instruction with an A type must be followed by the corresponding F
+# version.
 
 # Simple terminals
-S CONST
-S REG
-S LABEL
-S BLOCK
-V PAIR
-S ANY
-S LOCAL
-S PHI
+SA.. CONST
+SF.. CONSTF
+SA.. REG
+SF.. REGF
+SI.. LABEL
+SI.. BLOCK
+V... PAIR
+SA.. ANY
+SF.. ANYF
+S... LOCAL
+S... PHI
 
 # Magic stack operations
-S PUSH
-S POP
+S.A. PUSH
+S.F. PUSHF
+SA.. POP
+SF.. POPF
+
+#... Memory operations
+SAI. LOAD
+SFI. LOADF
+S.IA STORE
+S.IF STOREF
 
-# Memory operations
-S LOAD
-S STORE
 # Arithemetic operations
-S ADD
-S SUB
-S MUL
-S DIV
-S MOD
-S NEG
-S ADDF
-S SUBF
-S MULF
-S DIVF
-S NEGF
-S AND
-S OR
-S EOR
-S NOT
+SIII ADD
+SIII SUB
+SIII MUL
+SIII DIV
+SIII MOD
+SIII NEG
+
+SFFF ADDF
+SFFF SUBF
+SFFF MULF
+SFFF DIVF
+SFFF NEGF
+
+SIII AND
+SIII OR
+SIII EOR
+SIII NOT
+
 # Conversions
-S CII1
-S CII2
-S CII4
-S CII8
-S CIU1
-S CIU2
-S CIU4
-S CIU8
+SIII CII1
+SIII CII2
+SIII CII4
+SIII CII8
+
+SIII CIU1
+SIII CIU2
+SIII CIU4
+SIII CIU8
+
 # Tristate comparisons
-S COMPARES
-S COMPAREU
+SIII COMPARES
+SIII COMPAREU
+
 # Boolean comparisons
-S IFEQ
-S IFLT
-S IFLE
+SIII IFEQ
+SIII IFLT
+SIII IFLE
+
 # Procedures
-V CALL
+VI.. CALL
+
 # Flow control --- these never return
-V JUMP
-V CJUMPEQ
-V CJUMPLT
-V CJUMPLE
-V RET
+V.I. JUMP
+VIII CJUMPEQ
+VIII CJUMPLT
+VIII CJUMPLE
+V... RET
  
 # Special
-S STACKADJUST
-S GETRET
-S SETRET
+SI.. STACKADJUST
+SA.. GETRET
+SF.. GETRETF
+S.A. SETRET
+S.F. SETRETF
 
diff --git a/util/mcgg/ircodes.h b/util/mcgg/ircodes.h
new file mode 100644 (file)
index 0000000..99dbae7
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef IRCODES_H
+#define IRCODES_H
+
+enum
+{
+       IRF_SIZED = 1,
+};
+
+enum ir_type
+{
+       IRT_UNSET = 0,
+       IRT_INT,
+       IRT_FLOAT,
+       IRT_ANY
+};
+
+struct ir_data
+{
+       const char* name;
+       int flags;
+       enum ir_type returntype;
+       enum ir_type lefttype;
+       enum ir_type righttype;
+};
+
+extern const struct ir_data ir_data[];
+
+#include "ircodes-dyn.h"
+
+#endif
+
+/* vim: set sw=4 ts=4 expandtab : */
+
index 1e382e7..e4d289d 100755 (executable)
@@ -16,42 +16,34 @@ awk -f - $in >$header << "EOF"
        END {
                print "\tIR__COUNT"
                print "};"
-               print ""
-               print "enum {"
-               print "\tIRF_SIZED = 1"
-               print "};"
-               print ""
-               print "extern const char* ir_names[IR__COUNT];"
-               print "extern const char ir_flags[IR__COUNT];"
        }
 EOF
 
 awk -f - $in >$source << "EOF"
        BEGIN {
                print "#include \"ircodes.h\""
-               print "const char* ir_names[IR__COUNT] = {"
-       }
-
-       /^ *[^# ]+/ {
-               printf("\t\"%s\",\n", $2)
+               print "const struct ir_data ir_data[IR__COUNT] = {"
        }
 
-       END {
-               print "};"
+       function char_to_type(c) {
+               if (c == "I") return "IRT_INT"
+               if (c == "F") return "IRT_FLOAT"
+               if (c == "A") return "IRT_ANY"
+               return "IRT_UNSET"
        }
-EOF
 
-awk -f - $in >>$source << "EOF"
-       BEGIN {
-               print ""
-               print "const char ir_flags[IR__COUNT] = {"
+       function char_to_flags(c) {
+               if (c == "S") return "IRF_SIZED"
+               return "0"
        }
 
        /^ *[^# ]+/ {
-               if ($1 == "S")
-                       print("\tIRF_SIZED,")
-               else
-                       print("\t0,")
+               printf("\t{ \"%s\", ", $2)
+               printf("%s, ", char_to_flags(substr($1, 1, 1)))
+               printf("%s, ", char_to_type(substr($1, 2, 1)))
+               printf("%s, ", char_to_type(substr($1, 3, 1)))
+               printf("%s", char_to_type(substr($1, 4, 1)))
+               printf(" },\n")
        }
 
        END {