Introduced even more aggressive optimizations.

This commit is contained in:
Mphatso Raymond Mataka
2025-02-27 01:03:19 -08:00
parent 01712c9443
commit 24d5f92b76
9 changed files with 8276 additions and 7767 deletions
@@ -0,0 +1,24 @@
#include "aarch64_assembler.h"
#include <string.h>
#define ONE_MB 1 * 1024 * 1024
#define X(reg) rarma_context::X(reg)
#define SP rarma_context::SP()
#define WSP rarma_context::SP()
void assemble_aarch64_abi_caller_code(void* result_code, uint64_t* result_code_size, abi abi_information)
{
rarma_context c;
rarma_context::create(&c, ONE_MB);
rarma_context::sub_imm12(&c, SP, SP, 8);
rarma_context::add_imm12(&c, SP, SP, 8);
*result_code_size = c.memory_location;
memcpy(result_code, c.memory_block, *result_code_size);
rarma_context::destroy(&c);
}
+7
View File
@@ -1,4 +1,11 @@
#include <inttypes.h>
#include "abi_information.h"
#ifndef AARCH64_ASSEMBLER_H
#define AARCH64_ASSEMBLER_H
#include "rarma.h"
void assemble_aarch64_abi_caller_code(void* result_code, uint64_t* result_code_size, abi abi_information);
#endif
+322
View File
@@ -0,0 +1,322 @@
#ifndef RARMA_H
#define RARMA_H
#include <string>
#include <inttypes.h>
#include <iostream>
#include <assert.h>
struct rarma_context
{
void* memory_block;
uint64_t memory_block_size;
uint64_t memory_location;
enum operand_type
{
zr,
sp,
gp,
vec
};
enum shift_type
{
lsl,
lsr,
ror,
asr
};
struct operand
{
int operand_size;
int operand_register_index;
operand_type type;
};
static uint64_t get_code_size(rarma_context* context)
{
return context->memory_location;
}
static operand gp_size(int index, int size, operand_type type)
{
operand result;
result.operand_size = size;
result.operand_register_index = index;
result.type = type;
assert_in_mask(index, 5);
switch (type)
{
case sp:
case zr:
{
assert(index == 31);
assert(size >= 2 && size <= 3);
}; break;
}
return result;
}
static operand X(int index)
{
return gp_size(index, 3, operand_type::gp);
}
static operand SP()
{
return gp_size(31, 3, operand_type::sp);
}
static operand W(int index)
{
return gp_size(index, 2, operand_type::gp);
}
static operand WSP()
{
return gp_size(31, 2, operand_type::sp);
}
static operand H(int index)
{
return gp_size(index, 1, operand_type::gp);
}
static operand B(int index)
{
return gp_size(index, 0, operand_type::gp);
}
static void assert_is_gp_sp(operand test)
{
if (test.operand_register_index == 31)
{
assert(test.type == sp);
}
else
{
assert(test.type == gp);
}
}
static void assert_is_gp_zr(operand test)
{
if (test.operand_register_index == 31)
{
assert(test.type == zr);
}
else
{
assert(test.type == gp);
}
}
static void assert_same_size(operand left, operand right)
{
assert(left.operand_size == right.operand_size);
}
static bool is_vector(operand test)
{
return test.operand_size == 4;
}
static void assert_not_vector(operand test)
{
assert(!is_vector(test));
}
static void assert_w_or_x(operand test)
{
assert(test.operand_size == 2 || test.operand_size == 3);
}
static void assert_in_mask(int imm, int bit_count)
{
assert((imm & ~create_mask(bit_count)) == 0);
}
static void create(rarma_context* result, uint64_t memory_block_size = 1024)
{
result->memory_block = malloc(memory_block_size);
result->memory_location = 0;
result->memory_block_size = memory_block_size;
}
static void destroy(rarma_context* to_destroy)
{
free(to_destroy->memory_block);
}
static uint32_t write_instruction(rarma_context* context,uint32_t instruction)
{
if (context->memory_location >= context->memory_block_size)
{
std::cout << "RARM OUT OF SPACE" << std::endl;
throw 0;
}
*(uint32_t*)((uint64_t)context->memory_block + context->memory_location) = instruction;
context->memory_location += 4;
return instruction;
}
static int create_mask(int size)
{
return (1 << size) - 1;
}
static uint32_t add_subtract_shifted(rarma_context* context, bool is_add, bool set_flags, operand d, operand n, operand m, shift_type shift, int imm6)
{
int sf = d.operand_size == 3;
int op = !is_add;
int S = set_flags;
assert_in_mask(imm6, 6);
assert_in_mask(shift, 2);
assert_is_gp_zr(d);
assert_is_gp_zr(n);
assert_is_gp_zr(m);
uint32_t result = 0b01011 << 24;
result |= sf << 31;
result |= op << 30;
result |= S << 28;
result |= shift << 22;
result |= m.operand_register_index << 16;
result |= imm6 << 10;
result |= n.operand_register_index << 5;
result |= d.operand_register_index;
write_instruction(context, result);
return result;
}
static uint32_t add_subtract_imm12(rarma_context* context, bool is_add, bool set_flags, operand d, operand n, int imm12)
{
int sf = d.operand_size == 3;
int op = !is_add;
int S = set_flags;
int sh;
if (imm12 == 0)
{
sh = 0;
}
else if (imm12 & create_mask(12))
{
assert_in_mask(imm12, 12);
sh = 0;
}
else if (imm12 >> 12)
{
imm12 >>= 12;
assert((imm12 & ~create_mask(12)) == 0);
sh = 1;
}
uint32_t result = 0b100010 << 23;
assert_same_size(d, n);
assert_not_vector(d);
assert_w_or_x(d);
assert_is_gp_sp(n);
if (set_flags)
{
assert_is_gp_zr(d);
}
else
{
assert_is_gp_sp(d);
}
result |= (sf << 31);
result |= (op << 30);
result |= (S << 29);
result |= (sh << 22);
result |= d.operand_register_index;
result |= n.operand_register_index << 5;
result |= imm12 << 10;
write_instruction(context, result);
return result;
}
static uint32_t add_imm12(rarma_context* context, operand d, operand n, int imm12)
{
return add_subtract_imm12(context, true, false, d, n, imm12);
}
static uint32_t sub_imm12(rarma_context* context, operand d, operand n, int imm12)
{
return add_subtract_imm12(context, false, false, d, n, imm12);
}
static uint32_t adds_imm12(rarma_context* context, operand d, operand n, int imm12)
{
return add_subtract_imm12(context, true, true, d, n, imm12);
}
static uint32_t subs_imm12(rarma_context* context, operand d, operand n, int imm12)
{
return add_subtract_imm12(context, false, true, d, n, imm12);
}
static uint32_t add_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
{
return add_subtract_shifted(context, true, false, d, n, m, shift, imm6);
}
static uint32_t sub_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
{
return add_subtract_shifted(context, false, false, d, n, m, shift, imm6);
}
static uint32_t adds_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
{
return add_subtract_shifted(context, true, true, d, n, m, shift, imm6);
}
static uint32_t subs_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
{
return add_subtract_shifted(context, false, true, d, n, m, shift, imm6);
}
static uint32_t ret(rarma_context* context, operand n)
{
uint32_t result = 0b1101011001011111000000 << 10;
assert_is_gp_zr(n);
result |= n.operand_register_index << 5;
write_instruction(context, result);
return result;
}
};
#endif
+9
View File
@@ -233,6 +233,15 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
case ir_jump_if_equal:
case ir_jump_if_not_equal:
case ir_jump_if_greater_equal_signed:
case ir_jump_if_greater_equal_unsigned:
case ir_jump_if_greater_signed:
case ir_jump_if_greater_unsigned:
case ir_jump_if_less_equal_signed:
case ir_jump_if_less_equal_unsigned:
case ir_jump_if_less_signed:
case ir_jump_if_less_unsigned:
{
ir_operand label_operand = working_operation.sources[0];
ir_operand left = working_operation.sources[1];
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+194 -60
View File
@@ -29,6 +29,7 @@ struct ssa_node
std::unordered_set<uint64_t> declared_in_block;
std::unordered_map<int, std::unordered_map<uint64_t, uint64_t>> declaration_time_map;
std::unordered_map<uint64_t, int> last_declared;
std::unordered_map<uint64_t, global_usage_location*> cached_global_declarations;
std::vector<ssa_node*> inlets;
std::vector<ssa_node*> outlets;
@@ -196,6 +197,13 @@ static void find_same_register_pools(ssa_node* node)
continue;
}
if (in_map(&node->cached_global_declarations, current_source->value))
{
connect_global_usages(this_global_usage,node->cached_global_declarations[current_source->value]);
continue;
}
this_global_usage->is_global = true;
for (auto inlet : node->inlets)
@@ -204,6 +212,8 @@ static void find_same_register_pools(ssa_node* node)
find_register_in_parents(inlet, current_source->value, this_global_usage, &visited);
}
node->cached_global_declarations[current_source->value] = this_global_usage;
}
time++;
@@ -544,6 +554,7 @@ static bool optimize_math(ssa_node* working_node)
}; break;
case ir_bitwise_or:
case x86_orps:
{
if (check_constant(src[0], 0))
{
@@ -571,6 +582,12 @@ static bool optimize_math(ssa_node* working_node)
convert_to_move(working_operation, ir_operand::create_con(value, des[0].meta_data));
is_done = false;
}
else if (ir_operand::are_equal(src[0], src[1]))
{
convert_to_move(working_operation, src[0]);
is_done = false;
}
}; break;
@@ -595,6 +612,12 @@ static bool optimize_math(ssa_node* working_node)
convert_to_move(working_operation, ir_operand::create_con(value, des[0].meta_data));
is_done = false;
}
else if (ir_operand::are_equal(src[0], src[1]))
{
convert_to_move(working_operation, ir_operand::create_con(0));
is_done = false;
}
}; break;
@@ -620,6 +643,14 @@ static bool optimize_math(ssa_node* working_node)
is_done = false;
}
else if (ir_operand::are_equal(src[0], src[1]))
{
src[1] = ir_operand::create_con(1, src[1].meta_data);
working_operation->instruction = ir_shift_left;
is_done = false;
}
else if (check_constant(src[0]) && check_constant(src[1]))
{
uint64_t value = src[0].value + src[1].value;
@@ -628,6 +659,7 @@ static bool optimize_math(ssa_node* working_node)
is_done = false;
}
}; break;
case ir_subtract:
@@ -654,6 +686,12 @@ static bool optimize_math(ssa_node* working_node)
is_done = false;
}
else if (ir_operand::are_equal(src[0], src[1]))
{
convert_to_move(working_operation, ir_operand::create_con(0));
is_done = false;
}
else if (check_constant(src[0]) && check_constant(src[1]))
{
uint64_t value = src[0].value - src[1].value;
@@ -836,7 +874,7 @@ static void loop_through_operands_find_usage_count(ir_operand* operands, int cou
}
}
static bool check_for_register_in_instruction(ir_operand* operands,int count, uint64_t to_check)
static bool check_for_register_in_collection(ir_operand* operands,int count, uint64_t to_check)
{
for (int i = 0; i < count; ++i)
{
@@ -854,7 +892,7 @@ static bool check_for_register_in_instruction(ir_operand* operands,int count, ui
static bool check_for_register_in_instruction(ir_operation* operation, uint64_t to_check)
{
return check_for_register_in_instruction(operation->destinations.data, operation->destinations.count, to_check) | check_for_register_in_instruction(operation->sources.data, operation->sources.count, to_check);
return check_for_register_in_collection(operation->destinations.data, operation->destinations.count, to_check) | check_for_register_in_collection(operation->sources.data, operation->sources.count, to_check);
}
void copy_operands(ir_operand* destination,ir_operand* source, int count)
@@ -898,10 +936,10 @@ static bool optimize_multiple_instructions(ssa_node* working_node)
loop_through_operands_find_usage_count(working_operation->sources.data, working_operation->sources.count, &usage_count);
if (working_operation->destinations.count != 1)
continue;
declaration_location[working_operation->destinations[0].value] = working_operation;
for (int r = 0; r < working_operation->destinations.count; ++r)
{
declaration_location[working_operation->destinations[r].value] = working_operation;
}
}
time = 0;
@@ -1081,9 +1119,28 @@ static bool optimize_multiple_instructions(ssa_node* working_node)
is_done = false;
}; break;
case ir_compare_greater_equal_unsigned:
{
replace_jump_with_condition(ir, label, working_operation, condition_source, ir_jump_if_greater_equal_unsigned);
is_done = false;
}; break;
case ir_compare_greater_equal_signed:
{
replace_jump_with_condition(ir, label, working_operation, condition_source, ir_jump_if_greater_equal_signed);
is_done = false;
}; break;
default:
break;
{
if (ir_operation_block::is_compare(condition_source))
{
std::cout << instruction_names[condition_source->instruction] << std::endl;
}
}; break;
}
}; break;
@@ -1096,70 +1153,143 @@ static bool optimize_multiple_instructions(ssa_node* working_node)
if (ir_operand::is_constant(&source_operand))
continue;
if (!is_global(context, destination_operand))
continue;
if (is_global(context, source_operand))
continue;
ir_operation* local_declared_operation = declaration_location[source_operand.value];
if (local_declared_operation == nullptr)
continue;
if (usage_count[source_operand.value] > 1)
continue;
if (local_declared_operation->destinations.count == 0)
continue;
bool is_valid = true;
for (auto b = i->prev; b != raw_node->entry_instruction->prev; b = b->prev)
if (is_global(context, destination_operand) && !is_global(context, source_operand))
{
ir_operation* check_operation = &b->data;
ir_operation* local_declared_operation = declaration_location[source_operand.value];
if (check_operation == local_declared_operation)
break;
if (check_for_register_in_instruction(check_operation, destination_operand.value))
if (local_declared_operation == nullptr)
continue;
if (usage_count[source_operand.value] > 1)
continue;
if (local_declared_operation->destinations.count == 0)
continue;
bool is_valid = true;
for (auto b = i->prev; b != raw_node->entry_instruction->prev; b = b->prev)
{
is_valid = false;
break;
}
}
if (!is_valid)
continue;
for (int o = 0; o < local_declared_operation->destinations.count; ++o)
{
ir_operand* replace_candidate = &local_declared_operation->destinations.data[o];
if (replace_candidate->value == source_operand.value)
{
if (replace_candidate->meta_data != source_operand.meta_data)
ir_operation* check_operation = &b->data;
if (check_operation == local_declared_operation)
break;
if (check_for_register_in_instruction(check_operation, destination_operand.value))
{
//is_valid = false;
is_valid = false;
break;
}
}
if (!is_valid)
continue;
for (int o = 0; o < local_declared_operation->destinations.count; ++o)
{
ir_operand* replace_candidate = &local_declared_operation->destinations.data[o];
if (replace_candidate->value == source_operand.value)
{
if (replace_candidate->meta_data != source_operand.meta_data)
{
//is_valid = false;
//IN A LOT OF CACES, THIS CAN BE IGNORED
//TODO, FIND THOSE CASES
//break;
}
replace_candidate->value = destination_operand.value;
}
}
if (!is_valid)
continue;
nop_operation(working_operation);
is_done = false;
}
else if (!is_global(context,destination_operand) && is_global(context, source_operand))
{
bool is_zero_extend = false;
bool ignore = false;
//IN A LOT OF CACES, THIS CAN BE IGNORED
//TODO, FIND THOSE CASES
std::vector<ir_operand*> to_replace;
intrusive_linked_list_element<ir_operation>* look_next = nullptr;
//break;
for (auto check = i->next; check != raw_node->final_instruction->next; check = check->next)
{
ir_operation* check_operation = &check->data;
if (check_if_zero_extend(&check->data,destination_operand))
{
is_zero_extend = true;
break;
}
replace_candidate->value = destination_operand.value;
for (int o = 0; o < check_operation->sources.count; ++o)
{
ir_operand* to_replace_candidate = &check_operation->sources[o];
if (ir_operand::is_constant(to_replace_candidate))
continue;
if (to_replace_candidate->value != destination_operand.value)
continue;
to_replace.push_back(to_replace_candidate);
}
if (check_for_register_in_collection(check_operation->destinations.data, check_operation->destinations.count, source_operand.value))
{
look_next = check->next;
break;
}
}
if (look_next != nullptr)
{
for (auto check = look_next; check != raw_node->final_instruction->next; check = check->next)
{
ir_operation* check_operation = &check->data;
if (!check_for_register_in_collection(check_operation->sources.data, check_operation->sources.count, destination_operand.value))
continue;
ignore = true;
break;
}
}
if (ignore)
{
continue;
}
if (is_zero_extend)
{
i->data.instruction = ir_zero_extend;
continue;
}
for (auto i : to_replace)
{
i->value = source_operand.value;
}
nop_operation(working_operation);
is_done = false;
}
if (!is_valid)
continue;
nop_operation(working_operation);
is_done = false;
}; break;
default:
@@ -1269,6 +1399,10 @@ void convert_to_ssa(ir_operation_block* ir, bool optimize)
}
}
//ir_operation_block::log(ssa.ir);
//std::cin.get();
linier_scan_register_allocator_pass(ssa.cfg);
destroy_ssa_context(&ssa);
+4 -2
View File
@@ -49,9 +49,11 @@ static void unmark_memory_executable(void* memory, uint64_t size)
static uint64_t align_64_kb(uint64_t source)
{
uint64_t mask = ~63ULL;
uint64_t page_size = 64 * 1024;
return (source & mask) + 64;
uint64_t mask = page_size - 1;
return (source & ~mask) + page_size;
}
bool jit_memory::create(jit_memory** result, uint64_t allocation_size, abi host_abi)
+11
View File
@@ -0,0 +1,11 @@
{
"folders": [
{
"path": "../../../rem_tester_arm"
},
{
"path": "../.."
}
],
"settings": {}
}