compiler

Unnamed Compiled Systems Language Project
git clone http://frotz.net/git/compiler.git
Log | Files | Refs

commit d08c090a97f2a9690f15e70fe879f068da5d1b36
parent 47d3a9dea9ae7fda2c7edfcbf2d49786734010bf
Author: Brian Swetland <swetland@frotz.net>
Date:   Tue, 14 Dec 2021 13:22:33 -0800

improve conditional handling in IR and straight r5 codegen

- avoid extraneous branches by avoiding converting comparisons
  into bool values when possible

Diffstat:
Msrc/codegen-ir.c | 29+++++++++++++++++++----------
Msrc/codegen-risc5-simple.c | 43++++++++++++++++++++++++++++---------------
2 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/src/codegen-ir.c b/src/codegen-ir.c @@ -163,6 +163,7 @@ void inst_ret(i32 a) { } u32 rel_op_to_ins_tab[6] = { INS_BEQ, INS_BNE, INS_BLT, INS_BLE, INS_BGT, INS_BGE }; +u32 rel_op_to_inv_ins_tab[6] = { INS_BNE, INS_BEQ, INS_BGE, INS_BGT, INS_BLE, INS_BLT }; u32 add_op_to_ins_tab[4] = { INS_ADD, INS_SUB, INS_OR, INS_XOR }; u32 mul_op_to_ins_tab[6] = { INS_MUL, INS_SDIV, INS_SREM, INS_AND, INS_LSL, INS_ASR }; @@ -313,6 +314,19 @@ i32 gen_relop(Ast node, u32 op) { return inst_phi(rtrue, rfalse); } +i32 gen_branch_if_expr_false(Ast node, i32 label) { + if (ast_kind_is_relop(node->kind)) { + u32 op = rel_op_to_inv_ins_tab[node->kind - AST_EQ]; + i32 left = gen_expr(node->c0); + i32 right = gen_expr(node->c1); + return inst_br_cmp(op, label, left, right); + } else { + i32 r = gen_expr(node); + return inst_br_cmpi(INS_BEQ, label, r, 0); + } +} + + i32 gen_short_circuit_op(Ast node, u32 cc, u32 sc) { #if 0 u32 r = gen_expr(node->c0); @@ -432,15 +446,14 @@ void gen_while(Ast node) { inst_label(loop_continue); - u32 r = gen_expr(node->c0); - - // branch to exit if false - inst_br_cmpi(INS_BEQ, loop_exit, r, 0); + gen_branch_if_expr_false(node->c0, loop_exit); gen_block(node->c1); inst_br(loop_continue); + inst_label(loop_exit); + // restore branch targets loop_continue = old_loop_continue; loop_exit = old_loop_exit; @@ -457,9 +470,7 @@ void gen_if_else(Ast node) { // compute if expr // branch ahead if false; - i32 r = gen_expr(node->c0); - - i32 l0_br_false = inst_br_cmpi(INS_BEQ, label_get(), r, 0); + i32 l0_br_false = gen_branch_if_expr_false(node->c0, label_get()); i32 l_exit = label_get(); @@ -476,9 +487,7 @@ void gen_if_else(Ast node) { if (node->kind == AST_IFELSE) { // ifelse ... gen_trace("gen_ifelse()"); - r = gen_expr(node->c0); - - i32 l0_br_false = inst_br_cmpi(INS_BEQ, label_get(), r, 0); + i32 l0_br_false = gen_branch_if_expr_false(node->c0, label_get()); gen_block(node->c1); node = node->c2; diff --git a/src/codegen-risc5-simple.c b/src/codegen-risc5-simple.c @@ -150,6 +150,7 @@ void emit_bi(u32 op, u32 off) { } u8 rel_op_to_cc_tab[6] = { EQ, NE, LT, LE, GT, GE }; +u8 rel_op_to_inv_cc_tab[6] = { NE, EQ, GE, GT, LE, LT }; u32 add_op_to_ins_tab[4] = { ADD, SUB, IOR, XOR }; u32 mul_op_to_ins_tab[6] = { MUL, DIV, MOD, AND, LSL, ASR }; @@ -411,6 +412,28 @@ u32 gen_relop(Ast node, u32 cc) { return res; } +u32 gen_branch_if_expr_false(Ast node) { + if (ast_kind_is_relop(node->kind)) { + u32 cc = rel_op_to_inv_cc_tab[node->kind - AST_EQ]; + u32 left = gen_expr(node->c0); + u32 right = gen_expr(node->c1); + u32 res = get_reg_tmp(); + emit_op(SUB, left, left, right); + put_reg(left); + put_reg(right); + u32 addr = ctx.pc; + emit_bi(cc, 0); + return addr; + } else { + i32 r = gen_expr(node); + emit_mov(R11, r); // set z flag + put_reg(r); + u32 addr = ctx.pc; + emit_bi(EQ, 0); + return addr; + } +} + u32 gen_short_circuit_op(Ast node, u32 cc, u32 sc) { u32 r = gen_expr(node->c0); emit_mov(R11, r); // set z flag @@ -535,17 +558,15 @@ void gen_while(Ast node) { loop_exit = &list; loop_continue = ctx.pc; - u32 r = gen_expr(node->c0); - emit_mov(R11, r); // set z flag - put_reg(r); - gen_branch_fwd(EQ, &list); + u32 br_false = gen_branch_if_expr_false(node->c0); gen_block(node->c1); gen_branch(AL, loop_continue); - // patch breaks + // patch branches + fixup_branch_fwd(br_false); fixup_branches_fwd(loop_exit->next); // restore branch targets @@ -564,11 +585,7 @@ void gen_if_else(Ast node) { // compute if expr // branch ahead if false; - u32 r = gen_expr(node->c0); - emit_mov(R11, r); // set z flag; - put_reg(r); - u32 l0_br_false = ctx.pc; - emit_bi(EQ, 0); + u32 l0_br_false = gen_branch_if_expr_false(node->c0); // exec then block gen_block(node->c1); @@ -583,11 +600,7 @@ void gen_if_else(Ast node) { if (node->kind == AST_IFELSE) { // ifelse ... gen_trace("gen_ifelse()"); - r = gen_expr(node->c0); - emit_mov(R11, r); // set z flag - put_reg(r); - l0_br_false = ctx.pc; - emit_bi(EQ, 0); + u32 l0_br_false = gen_branch_if_expr_false(node->c0); gen_block(node->c1); node = node->c2; } else { // else ...