287 lines
10 KiB
C
Raw Normal View History

2025-12-02 06:54:32 +01:00
#include "superinst.h"
2025-12-04 06:14:22 +01:00
#include "fastframe.h"
2025-12-02 06:54:32 +01:00
#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;
}
}
}
2025-12-04 06:14:22 +01:00
static int is_power_of_two(int64_t n) {
return n > 0 && (n & (n - 1)) == 0;
}
static int log2_int(int64_t n) {
int result = 0;
while (n > 1) {
n >>= 1;
result++;
}
return result;
}
static void optimize_strength_reduction(RavaInstruction_t *instrs, size_t count) {
for (size_t i = 0; i + 2 < count; i++) {
if (instrs[i+1].opcode == RAVA_OP_LOAD_CONST) {
int64_t const_val = instrs[i+1].operand.int_value;
if (instrs[i+2].opcode == RAVA_OP_MUL && is_power_of_two(const_val)) {
int shift_amount = log2_int(const_val);
instrs[i+1].operand.int_value = shift_amount;
instrs[i+2].opcode = RAVA_OP_SHL;
}
else if (instrs[i+2].opcode == RAVA_OP_DIV && is_power_of_two(const_val)) {
int shift_amount = log2_int(const_val);
instrs[i+1].operand.int_value = shift_amount;
instrs[i+2].opcode = RAVA_OP_SHR;
}
else if (instrs[i+2].opcode == RAVA_OP_MOD && const_val == 2) {
instrs[i+1].operand.int_value = 1;
instrs[i+2].opcode = RAVA_OP_AND;
}
}
}
}
static void optimize_constant_folding(RavaInstruction_t *instrs, size_t count) {
for (size_t i = 0; i + 2 < count; i++) {
if (instrs[i].opcode == RAVA_OP_LOAD_CONST &&
instrs[i+1].opcode == RAVA_OP_LOAD_CONST) {
int64_t val1 = instrs[i].operand.int_value;
int64_t val2 = instrs[i+1].operand.int_value;
int64_t result = 0;
int can_fold = 1;
switch (instrs[i+2].opcode) {
case RAVA_OP_ADD:
result = val1 + val2;
break;
case RAVA_OP_SUB:
result = val1 - val2;
break;
case RAVA_OP_MUL:
result = val1 * val2;
break;
case RAVA_OP_DIV:
if (val2 != 0) {
result = val1 / val2;
} else {
can_fold = 0;
}
break;
case RAVA_OP_MOD:
if (val2 != 0) {
result = val1 % val2;
} else {
can_fold = 0;
}
break;
case RAVA_OP_AND:
result = val1 & val2;
break;
case RAVA_OP_OR:
result = val1 | val2;
break;
case RAVA_OP_XOR:
result = val1 ^ val2;
break;
case RAVA_OP_SHL:
result = val1 << val2;
break;
case RAVA_OP_SHR:
result = val1 >> val2;
break;
case RAVA_OP_EQ:
result = val1 == val2;
break;
case RAVA_OP_NE:
result = val1 != val2;
break;
case RAVA_OP_LT:
result = val1 < val2;
break;
case RAVA_OP_LE:
result = val1 <= val2;
break;
case RAVA_OP_GT:
result = val1 > val2;
break;
case RAVA_OP_GE:
result = val1 >= val2;
break;
default:
can_fold = 0;
break;
}
if (can_fold) {
instrs[i].operand.int_value = result;
instrs[i+1].opcode = RAVA_OP_NOP;
instrs[i+2].opcode = RAVA_OP_NOP;
}
}
}
}
static void optimize_inline_calls(RavaInstruction_t *instrs, size_t count) {
for (size_t i = 0; i < count; i++) {
if (instrs[i].opcode == RAVA_OP_CALL_STATIC ||
instrs[i].opcode == RAVA_OP_CALL_RECURSIVE) {
RavaMethod_t *target = (RavaMethod_t*)instrs[i].operand.call.cached_method;
if (target && target->is_simple && target->is_leaf &&
target->local_count <= RAVA_INLINE_FRAME_LOCALS &&
target->max_stack <= RAVA_INLINE_FRAME_STACK) {
instrs[i].opcode = RAVA_OP_CALL_INLINE;
}
}
}
}
2025-12-02 06:54:32 +01:00
void rava_optimize_superinstructions(RavaMethod_t* method) {
if (!method || !method->instructions) return;
RavaInstruction_t *instrs = method->instructions->instructions;
size_t count = method->instructions->count;
2025-12-04 06:14:22 +01:00
optimize_constant_folding(instrs, count);
optimize_inline_calls(instrs, count);
optimize_strength_reduction(instrs, count);
2025-12-02 06:54:32 +01:00
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);
}