diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 277bc6cf4..ddd33aecf 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -124,6 +124,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_promote_float_ops(struct procedure* proc); extern void procedure_compile(struct procedure* proc); diff --git a/mach/proto/mcg/pass_promotefloatops.c b/mach/proto/mcg/pass_promotefloatops.c new file mode 100644 index 000000000..478143b38 --- /dev/null +++ b/mach/proto/mcg/pass_promotefloatops.c @@ -0,0 +1,100 @@ +#include "mcg.h" + +static ARRAYOF(struct ir) pending; +static ARRAYOF(struct ir) promotable; + +static void addall(struct ir* ir) +{ + if (array_appendu(&pending, ir)) + return; + + if (ir->left) + addall(ir->left); + if (ir->right) + addall(ir->right); +} + +static void collect_irs(struct procedure* proc) +{ + int i; + + pending.count = 0; + promotable.count = 0; + for (i=0; iblocks.count; i++) + { + struct basicblock* bb = proc->blocks.item[i]; + int j; + + for (j=0; jirs.count; j++) + addall(bb->irs.item[j]); + } +} + +static void promote(struct ir* ir) +{ + switch (ir->opcode) + { + case IR_CONST: + case IR_POP: + case IR_LOAD: + array_appendu(&promotable, ir); + break; + + case IR_PHI: + if (!array_appendu(&promotable, ir)) + { + if (ir->left) + promote(ir->left); + if (ir->right) + promote(ir->right); + } + break; + } +} + +static void search_for_promotable_irs(void) +{ + int i; + + for (i=0; iopcode) + { + case IR_ADDF: + case IR_SUBF: + case IR_MULF: + case IR_DIVF: + case IR_NEGF: + if (ir->left) + promote(ir->left); + if (ir->right) + promote(ir->right); + break; + } + } +} + +static void modify_promotable_irs(void) +{ + int i; + + for (i=0; iopcode != IR_PHI) + ir->opcode++; + } +} + +void pass_promote_float_ops(struct procedure* proc) +{ + collect_irs(proc); + search_for_promotable_irs(); + modify_promotable_irs(); +} + +/* vim: set sw=4 ts=4 expandtab : */ + diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index a27aeedf7..300882eb9 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -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_promote_float_ops(proc); print_blocks('2', proc); diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index c88c68fcb..59272c4dd 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -190,7 +190,7 @@ PATTERNS emit "ldr %int, address-containing-$value" cost 8; - float = value:CONST4 + float = value:CONSTF4 emit "vldr %float, address-containing-$value" cost 8; diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 3dd785b5c..b12cf8934 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -3,7 +3,8 @@ # V: has no size (use in JUMP, CJUMP, RET forms) # Simple terminals -S CONST +S CONST # must be followed by float form +S CONSTF S REG S LABEL S BLOCK @@ -14,10 +15,12 @@ S PHI # Magic stack operations S PUSH -S POP +S POP # must be followed by float form +S POPF #... Memory operations -S LOAD +S LOAD # must be followed by float form +S LOADF S STORE # Arithemetic operations