Keep more data around about ir instructions. Implement a half-baked type
inference routine to propagate information about floats up the tree, so we know whether to put floats into special registers as early as possible.
This commit is contained in:
parent
416b13fd76
commit
cc176e5183
|
@ -103,9 +103,15 @@ struct ir* ir_find(struct ir* ir, int opcode)
|
||||||
|
|
||||||
static void print_expr(char k, const struct ir* ir)
|
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)
|
if (ir->size)
|
||||||
tracef(k, "%d", 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, "(");
|
tracef(k, "(");
|
||||||
|
|
||||||
switch (ir->opcode)
|
switch (ir->opcode)
|
||||||
|
|
|
@ -3,27 +3,12 @@
|
||||||
|
|
||||||
#include "ircodes.h"
|
#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
|
struct ir
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
enum ir_opcode opcode;
|
enum ir_opcode opcode;
|
||||||
int size;
|
int size;
|
||||||
|
enum ir_type type;
|
||||||
struct ir* left;
|
struct ir* left;
|
||||||
struct ir* right;
|
struct ir* right;
|
||||||
union
|
union
|
||||||
|
|
|
@ -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_remove_dead_blocks(struct procedure* proc);
|
||||||
extern void pass_eliminate_trivial_blocks(struct procedure* proc);
|
extern void pass_eliminate_trivial_blocks(struct procedure* proc);
|
||||||
extern void pass_instruction_selector(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);
|
extern void procedure_compile(struct procedure* proc);
|
||||||
|
|
||||||
|
|
63
mach/proto/mcg/pass_typeinference.c
Normal file
63
mach/proto/mcg/pass_typeinference.c
Normal file
|
@ -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 : */
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ void procedure_compile(struct procedure* proc)
|
||||||
pass_eliminate_trivial_blocks(proc);
|
pass_eliminate_trivial_blocks(proc);
|
||||||
pass_remove_dead_blocks(proc);
|
pass_remove_dead_blocks(proc);
|
||||||
pass_convert_stack_ops(proc);
|
pass_convert_stack_ops(proc);
|
||||||
|
pass_type_inference(proc);
|
||||||
|
|
||||||
print_blocks('2', proc);
|
print_blocks('2', proc);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ yacc {
|
||||||
|
|
||||||
normalrule {
|
normalrule {
|
||||||
name = "ircodes",
|
name = "ircodes",
|
||||||
outleaves = { "ircodes.h", "ircodes.c" },
|
outleaves = { "ircodes-dyn.h", "ircodes.c" },
|
||||||
ins = {
|
ins = {
|
||||||
"./ircodes.sh",
|
"./ircodes.sh",
|
||||||
"./ir.dat"
|
"./ir.dat"
|
||||||
|
@ -25,10 +25,15 @@ normalrule {
|
||||||
clibrary {
|
clibrary {
|
||||||
name = "lib",
|
name = "lib",
|
||||||
srcs = {
|
srcs = {
|
||||||
matching(filenamesof("+ircodes"), "%.c$")
|
matching(filenamesof("+ircodes"), "%.c$"),
|
||||||
|
},
|
||||||
|
deps = {
|
||||||
|
"+ircodes",
|
||||||
|
"./ircodes.h"
|
||||||
},
|
},
|
||||||
hdrs = {
|
hdrs = {
|
||||||
matching(filenamesof("+ircodes"), "%.h$"),
|
matching(filenamesof("+ircodes"), "%.h$"),
|
||||||
|
"./ircodes.h",
|
||||||
"./mcgg.h"
|
"./mcgg.h"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,9 +176,9 @@ char* stringf(char* fmt, ...)
|
||||||
return p;
|
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);
|
int esn = ir_to_esn(iropcode, size);
|
||||||
|
|
||||||
term(s, esn);
|
term(s, esn);
|
||||||
|
@ -190,15 +190,15 @@ static void registerterminals(void)
|
||||||
|
|
||||||
for (i=0; i<IR__COUNT; i++)
|
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_data[i], i, 1);
|
||||||
registerterminal(ir_names[i], i, 2);
|
registerterminal(&ir_data[i], i, 2);
|
||||||
registerterminal(ir_names[i], i, 4);
|
registerterminal(&ir_data[i], i, 4);
|
||||||
registerterminal(ir_names[i], i, 8);
|
registerterminal(&ir_data[i], i, 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
registerterminal(ir_names[i], i, 0);
|
registerterminal(&ir_data[i], i, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
134
util/mcgg/ir.dat
134
util/mcgg/ir.dat
|
@ -1,76 +1,92 @@
|
||||||
# Flags:
|
# Flags:
|
||||||
# S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
|
# S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
|
||||||
# V: has no size (use in JUMP, CJUMP, RET 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
|
# Simple terminals
|
||||||
S CONST
|
SA.. CONST
|
||||||
S REG
|
SF.. CONSTF
|
||||||
S LABEL
|
SA.. REG
|
||||||
S BLOCK
|
SF.. REGF
|
||||||
V PAIR
|
SI.. LABEL
|
||||||
S ANY
|
SI.. BLOCK
|
||||||
S LOCAL
|
V... PAIR
|
||||||
S PHI
|
SA.. ANY
|
||||||
|
SF.. ANYF
|
||||||
|
S... LOCAL
|
||||||
|
S... PHI
|
||||||
|
|
||||||
# Magic stack operations
|
# Magic stack operations
|
||||||
S PUSH
|
S.A. PUSH
|
||||||
S POP
|
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
|
# Arithemetic operations
|
||||||
S ADD
|
SIII ADD
|
||||||
S SUB
|
SIII SUB
|
||||||
S MUL
|
SIII MUL
|
||||||
S DIV
|
SIII DIV
|
||||||
S MOD
|
SIII MOD
|
||||||
S NEG
|
SIII NEG
|
||||||
|
|
||||||
S ADDF
|
SFFF ADDF
|
||||||
S SUBF
|
SFFF SUBF
|
||||||
S MULF
|
SFFF MULF
|
||||||
S DIVF
|
SFFF DIVF
|
||||||
S NEGF
|
SFFF NEGF
|
||||||
|
|
||||||
S AND
|
SIII AND
|
||||||
S OR
|
SIII OR
|
||||||
S EOR
|
SIII EOR
|
||||||
S NOT
|
SIII NOT
|
||||||
|
|
||||||
# Conversions
|
# Conversions
|
||||||
S CII1
|
SIII CII1
|
||||||
S CII2
|
SIII CII2
|
||||||
S CII4
|
SIII CII4
|
||||||
S CII8
|
SIII CII8
|
||||||
|
|
||||||
S CIU1
|
SIII CIU1
|
||||||
S CIU2
|
SIII CIU2
|
||||||
S CIU4
|
SIII CIU4
|
||||||
S CIU8
|
SIII CIU8
|
||||||
|
|
||||||
# Tristate comparisons
|
# Tristate comparisons
|
||||||
S COMPARES
|
SIII COMPARES
|
||||||
S COMPAREU
|
SIII COMPAREU
|
||||||
|
|
||||||
# Boolean comparisons
|
# Boolean comparisons
|
||||||
S IFEQ
|
SIII IFEQ
|
||||||
S IFLT
|
SIII IFLT
|
||||||
S IFLE
|
SIII IFLE
|
||||||
|
|
||||||
# Procedures
|
# Procedures
|
||||||
V CALL
|
VI.. CALL
|
||||||
|
|
||||||
# Flow control --- these never return
|
# Flow control --- these never return
|
||||||
V JUMP
|
V.I. JUMP
|
||||||
V CJUMPEQ
|
VIII CJUMPEQ
|
||||||
V CJUMPLT
|
VIII CJUMPLT
|
||||||
V CJUMPLE
|
VIII CJUMPLE
|
||||||
V RET
|
V... RET
|
||||||
|
|
||||||
# Special
|
# Special
|
||||||
S STACKADJUST
|
SI.. STACKADJUST
|
||||||
S GETRET
|
SA.. GETRET
|
||||||
S SETRET
|
SF.. GETRETF
|
||||||
|
S.A. SETRET
|
||||||
|
S.F. SETRETF
|
||||||
|
|
||||||
|
|
33
util/mcgg/ircodes.h
Normal file
33
util/mcgg/ircodes.h
Normal file
|
@ -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 : */
|
||||||
|
|
|
@ -16,42 +16,34 @@ awk -f - $in >$header << "EOF"
|
||||||
END {
|
END {
|
||||||
print "\tIR__COUNT"
|
print "\tIR__COUNT"
|
||||||
print "};"
|
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
|
EOF
|
||||||
|
|
||||||
awk -f - $in >$source << "EOF"
|
awk -f - $in >$source << "EOF"
|
||||||
BEGIN {
|
BEGIN {
|
||||||
print "#include \"ircodes.h\""
|
print "#include \"ircodes.h\""
|
||||||
print "const char* ir_names[IR__COUNT] = {"
|
print "const struct ir_data ir_data[IR__COUNT] = {"
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
function char_to_flags(c) {
|
||||||
|
if (c == "S") return "IRF_SIZED"
|
||||||
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
/^ *[^# ]+/ {
|
/^ *[^# ]+/ {
|
||||||
printf("\t\"%s\",\n", $2)
|
printf("\t{ \"%s\", ", $2)
|
||||||
}
|
printf("%s, ", char_to_flags(substr($1, 1, 1)))
|
||||||
|
printf("%s, ", char_to_type(substr($1, 2, 1)))
|
||||||
END {
|
printf("%s, ", char_to_type(substr($1, 3, 1)))
|
||||||
print "};"
|
printf("%s", char_to_type(substr($1, 4, 1)))
|
||||||
}
|
printf(" },\n")
|
||||||
EOF
|
|
||||||
|
|
||||||
awk -f - $in >>$source << "EOF"
|
|
||||||
BEGIN {
|
|
||||||
print ""
|
|
||||||
print "const char ir_flags[IR__COUNT] = {"
|
|
||||||
}
|
|
||||||
|
|
||||||
/^ *[^# ]+/ {
|
|
||||||
if ($1 == "S")
|
|
||||||
print("\tIRF_SIZED,")
|
|
||||||
else
|
|
||||||
print("\t0,")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
END {
|
END {
|
||||||
|
|
Loading…
Reference in a new issue