From 0684f41d0fb874c121e0ca3bccf9bf87c224dc55 Mon Sep 17 00:00:00 2001 From: Yu-En Hsiao Date: Sun, 24 Nov 2024 09:43:34 +0800 Subject: [PATCH] Enhance code reusability for the compiler backends After observing ARM and RISC-V backends, the instruction sequences of load and global load operations are very similar, and both of them just use a different register for two instructions. A similar situation occurs for store and global store operations. Therefore, this commit improves the compiler backends to reuse the same code more efficiently. --- src/arm-codegen.c | 39 ++++++++++++++------------------------- src/riscv-codegen.c | 39 ++++++++++++++------------------------- 2 files changed, 28 insertions(+), 50 deletions(-) diff --git a/src/arm-codegen.c b/src/arm-codegen.c index fa036778..808eb6e8 100644 --- a/src/arm-codegen.c +++ b/src/arm-codegen.c @@ -194,9 +194,11 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) int ofs; /* Prepare this variable to reuse the same code for - * the instruction sequence of division and modulo. + * the instruction sequence of + * 1. division and modulo. + * 2. load and store operations. */ - arm_reg soft_div_rd = __r8; + arm_reg interm; switch (ph2_ir->op) { case OP_define: @@ -236,40 +238,26 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) emit(__mov_r(__AL, rd, rn)); return; case OP_load: - if (ph2_ir->src0 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src0)); - emit(__movt(__AL, __r8, ph2_ir->src0)); - emit(__add_r(__AL, __r8, __sp, __r8)); - emit(__lw(__AL, rd, __r8, 0)); - } else - emit(__lw(__AL, rd, __sp, ph2_ir->src0)); - return; - case OP_store: - if (ph2_ir->src1 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src1)); - emit(__movt(__AL, __r8, ph2_ir->src1)); - emit(__add_r(__AL, __r8, __sp, __r8)); - emit(__sw(__AL, rn, __r8, 0)); - } else - emit(__sw(__AL, rn, __sp, ph2_ir->src1)); - return; case OP_global_load: + interm = ph2_ir->op == OP_load ? __sp : __r12; if (ph2_ir->src0 > 4095) { emit(__movw(__AL, __r8, ph2_ir->src0)); emit(__movt(__AL, __r8, ph2_ir->src0)); - emit(__add_r(__AL, __r8, __r12, __r8)); + emit(__add_r(__AL, __r8, interm, __r8)); emit(__lw(__AL, rd, __r8, 0)); } else - emit(__lw(__AL, rd, __r12, ph2_ir->src0)); + emit(__lw(__AL, rd, interm, ph2_ir->src0)); return; + case OP_store: case OP_global_store: + interm = ph2_ir->op == OP_store ? __sp : __r12; if (ph2_ir->src1 > 4095) { emit(__movw(__AL, __r8, ph2_ir->src1)); emit(__movt(__AL, __r8, ph2_ir->src1)); - emit(__add_r(__AL, __r8, __r12, __r8)); + emit(__add_r(__AL, __r8, interm, __r8)); emit(__sw(__AL, rn, __r8, 0)); } else - emit(__sw(__AL, rn, __r12, ph2_ir->src1)); + emit(__sw(__AL, rn, interm, ph2_ir->src1)); return; case OP_read: if (ph2_ir->src1 == 1) @@ -351,6 +339,7 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) } return; } + interm = __r8; /* div/mod emulation */ /* Preserve the values of the dividend and divisor */ emit(__stmdb(__AL, 1, __sp, (1 << rn) | (1 << rm))); @@ -368,7 +357,7 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) * in __r9. The sign of the divisor is irrelevant for determining * the result's sign. */ - soft_div_rd = __r9; + interm = __r9; emit(__mov_r(__AL, __r10, __r8)); } /* Unsigned integer division */ @@ -399,7 +388,7 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) */ emit(__mov_r(__AL, __r9, rn)); emit(__ldm(__AL, 1, __sp, (1 << rn) | (1 << rm))); - emit(__mov_r(__AL, rd, soft_div_rd)); + emit(__mov_r(__AL, rd, interm)); /* Handle the correct sign for the quotient or remainder */ emit(__cmp_i(__AL, __r10, 0)); emit(__rsb_i(__NE, rd, 0, rd)); diff --git a/src/riscv-codegen.c b/src/riscv-codegen.c index 33dca886..ad3db9f4 100644 --- a/src/riscv-codegen.c +++ b/src/riscv-codegen.c @@ -158,9 +158,11 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) int ofs; /* Prepare the variables to reuse the same code for - * the instruction sequence of division and modulo. + * the instruction sequence of + * 1. division and modulo. + * 2. load and store operations. */ - rv_reg soft_div_rd = __t0, divisor_mask = __t1; + rv_reg interm, divisor_mask = __t1; switch (ph2_ir->op) { case OP_define: @@ -197,40 +199,26 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) emit(__addi(rd, rs1, 0)); return; case OP_load: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src0))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); - emit(__add(__t0, __sp, __t0)); - emit(__lw(rd, __t0, 0)); - } else - emit(__lw(rd, __sp, ph2_ir->src0)); - return; - case OP_store: - if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src1))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); - emit(__add(__t0, __sp, __t0)); - emit(__sw(rs1, __t0, 0)); - } else - emit(__sw(rs1, __sp, ph2_ir->src1)); - return; case OP_global_load: + interm = ph2_ir->op == OP_load ? __sp : __gp; if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { emit(__lui(__t0, rv_hi(ph2_ir->src0))); emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); - emit(__add(__t0, __gp, __t0)); + emit(__add(__t0, interm, __t0)); emit(__lw(rd, __t0, 0)); } else - emit(__lw(rd, __gp, ph2_ir->src0)); + emit(__lw(rd, interm, ph2_ir->src0)); return; + case OP_store: case OP_global_store: + interm = ph2_ir->op == OP_store ? __sp : __gp; if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { emit(__lui(__t0, rv_hi(ph2_ir->src1))); emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); - emit(__add(__t0, __gp, __t0)); + emit(__add(__t0, interm, __t0)); emit(__sw(rs1, __t0, 0)); } else - emit(__sw(rs1, __gp, ph2_ir->src1)); + emit(__sw(rs1, interm, ph2_ir->src1)); return; case OP_read: if (ph2_ir->src1 == 1) @@ -325,13 +313,14 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) emit(__mod(rd, rs1, rs2)); return; } + interm = __t0; /* div/mod emulation */ if (ph2_ir->op == OP_mod) { /* If the requested operation is modulo, the result will be stored * in __t2. The sign of the divisor is irrelevant for determining * the result's sign. */ - soft_div_rd = __t2; + interm = __t2; divisor_mask = __zero; } /* Obtain absolute values of the dividend and divisor */ @@ -359,7 +348,7 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir) emit(__srli(__t1, __t1, 1)); emit(__srli(__t3, __t3, 1)); emit(__bne(__t1, __zero, -20)); - emit(__addi(rd, soft_div_rd, 0)); + emit(__addi(rd, interm, 0)); /* Handle the correct sign for the quotient or remainder */ emit(__beq(__t5, __zero, 8)); emit(__sub(rd, __zero, rd));