|
#include "superinst.h"
|
|
#include <string.h>
|
|
|
|
static void optimize_inc_dec_local(RavaInstruction_t *instrs, size_t count) {
|
|
for (size_t i = 0; i + 3 < count; i++) {
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_CONST &&
|
|
instrs[i+1].operand.int_value == 1 &&
|
|
instrs[i+2].opcode == RAVA_OP_ADD &&
|
|
instrs[i+3].opcode == RAVA_OP_STORE_LOCAL &&
|
|
instrs[i].operand.var.index == instrs[i+3].operand.var.index) {
|
|
|
|
instrs[i].opcode = RAVA_OP_INC_LOCAL;
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
instrs[i+2].opcode = RAVA_OP_NOP;
|
|
instrs[i+3].opcode = RAVA_OP_NOP;
|
|
}
|
|
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_CONST &&
|
|
instrs[i+1].operand.int_value == 1 &&
|
|
instrs[i+2].opcode == RAVA_OP_SUB &&
|
|
instrs[i+3].opcode == RAVA_OP_STORE_LOCAL &&
|
|
instrs[i].operand.var.index == instrs[i+3].operand.var.index) {
|
|
|
|
instrs[i].opcode = RAVA_OP_DEC_LOCAL;
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
instrs[i+2].opcode = RAVA_OP_NOP;
|
|
instrs[i+3].opcode = RAVA_OP_NOP;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void optimize_loop_comparison(RavaInstruction_t *instrs, size_t count) {
|
|
for (size_t i = 0; i + 3 < count; i++) {
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_CONST &&
|
|
instrs[i+2].opcode == RAVA_OP_LT &&
|
|
instrs[i+3].opcode == RAVA_OP_JUMP_IF_FALSE) {
|
|
|
|
int local_idx = instrs[i].operand.var.index;
|
|
int64_t const_val = instrs[i+1].operand.int_value;
|
|
int label = instrs[i+3].operand.label_id;
|
|
|
|
instrs[i].opcode = RAVA_OP_LOAD_LOCAL_CONST_LT_JUMPFALSE;
|
|
instrs[i].operand.super.local_index = local_idx;
|
|
instrs[i].operand.super.const_value = const_val;
|
|
instrs[i].operand.super.label_id = label;
|
|
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
instrs[i+2].opcode = RAVA_OP_NOP;
|
|
instrs[i+3].opcode = RAVA_OP_NOP;
|
|
}
|
|
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_CONST &&
|
|
instrs[i+2].opcode == RAVA_OP_LE &&
|
|
instrs[i+3].opcode == RAVA_OP_JUMP_IF_FALSE) {
|
|
|
|
int local_idx = instrs[i].operand.var.index;
|
|
int64_t const_val = instrs[i+1].operand.int_value;
|
|
int label = instrs[i+3].operand.label_id;
|
|
|
|
instrs[i].opcode = RAVA_OP_LOAD_LOCAL_CONST_LE_JUMPFALSE;
|
|
instrs[i].operand.super.local_index = local_idx;
|
|
instrs[i].operand.super.const_value = const_val;
|
|
instrs[i].operand.super.label_id = label;
|
|
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
instrs[i+2].opcode = RAVA_OP_NOP;
|
|
instrs[i+3].opcode = RAVA_OP_NOP;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void optimize_two_locals(RavaInstruction_t *instrs, size_t count) {
|
|
for (size_t i = 0; i + 1 < count; i++) {
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_LOCAL) {
|
|
|
|
int idx1 = instrs[i].operand.var.index;
|
|
int idx2 = instrs[i+1].operand.var.index;
|
|
|
|
instrs[i].opcode = RAVA_OP_LOAD_TWO_LOCALS;
|
|
instrs[i].operand.two_locals.index1 = idx1;
|
|
instrs[i].operand.two_locals.index2 = idx2;
|
|
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void optimize_add_local_to_local(RavaInstruction_t *instrs, size_t count) {
|
|
for (size_t i = 0; i + 3 < count; i++) {
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+2].opcode == RAVA_OP_ADD &&
|
|
instrs[i+3].opcode == RAVA_OP_STORE_LOCAL &&
|
|
instrs[i].operand.var.index == instrs[i+3].operand.var.index) {
|
|
|
|
int dest_idx = instrs[i].operand.var.index;
|
|
int src_idx = instrs[i+1].operand.var.index;
|
|
|
|
instrs[i].opcode = RAVA_OP_ADD_LOCAL_TO_LOCAL;
|
|
instrs[i].operand.add_locals.dest_index = dest_idx;
|
|
instrs[i].operand.add_locals.src_index = src_idx;
|
|
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
instrs[i+2].opcode = RAVA_OP_NOP;
|
|
instrs[i+3].opcode = RAVA_OP_NOP;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void optimize_local_lt_local_jump(RavaInstruction_t *instrs, size_t count) {
|
|
for (size_t i = 0; i + 3 < count; i++) {
|
|
if (instrs[i].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+1].opcode == RAVA_OP_LOAD_LOCAL &&
|
|
instrs[i+2].opcode == RAVA_OP_LT &&
|
|
instrs[i+3].opcode == RAVA_OP_JUMP_IF_FALSE) {
|
|
|
|
int local1 = instrs[i].operand.var.index;
|
|
int local2 = instrs[i+1].operand.var.index;
|
|
int label = instrs[i+3].operand.label_id;
|
|
|
|
instrs[i].opcode = RAVA_OP_LOAD_LOCAL_LT_LOCAL_JUMPFALSE;
|
|
instrs[i].operand.cmp_locals.local1 = local1;
|
|
instrs[i].operand.cmp_locals.local2 = local2;
|
|
instrs[i].operand.cmp_locals.label_id = label;
|
|
|
|
instrs[i+1].opcode = RAVA_OP_NOP;
|
|
instrs[i+2].opcode = RAVA_OP_NOP;
|
|
instrs[i+3].opcode = RAVA_OP_NOP;
|
|
}
|
|
}
|
|
}
|
|
|
|
void rava_optimize_superinstructions(RavaMethod_t* method) {
|
|
if (!method || !method->instructions) return;
|
|
|
|
RavaInstruction_t *instrs = method->instructions->instructions;
|
|
size_t count = method->instructions->count;
|
|
|
|
optimize_add_local_to_local(instrs, count);
|
|
optimize_local_lt_local_jump(instrs, count);
|
|
optimize_inc_dec_local(instrs, count);
|
|
optimize_loop_comparison(instrs, count);
|
|
optimize_two_locals(instrs, count);
|
|
}
|