Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build-scripts/config_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ message (
" \"Sign-extension Operators\"\n"
" \"WebAssembly C and C++ API\"\n"
" \"Branch Hinting\"\n"
" \"Compilation Hints\"\n"
" Configurable. 0 is OFF. 1 is ON:\n"
" \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n"
" \"Bulk-memory-opt\" via WAMR_BUILD_BULK_MEMORY_OPT: ${WAMR_BUILD_BULK_MEMORY_OPT}\n"
Expand Down
4 changes: 4 additions & 0 deletions core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,10 @@ unless used elsewhere */
#define WASM_ENABLE_BRANCH_HINTS 0
#endif

#ifndef WASM_ENABLE_COMPILATION_HINTS
#define WASM_ENABLE_COMPILATION_HINTS 0
#endif

#ifndef WASM_ENABLE_GC
#define WASM_ENABLE_GC 0
#endif
Expand Down
4 changes: 2 additions & 2 deletions core/iwasm/compilation/aot.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ aot_create_funcs(const WASMModule *module, uint32 pointer_size)
aot_func->local_types_wp = func->local_types;
aot_func->code = func->code;
aot_func->code_size = func->code_size;
#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
aot_func->code_body_begin = func->code_body_begin;
#endif

Expand Down Expand Up @@ -875,7 +875,7 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
comp_data->name_section_buf_end = module->name_section_buf_end;
#endif

#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
comp_data->function_hints = module->function_hints;
#endif

Expand Down
4 changes: 2 additions & 2 deletions core/iwasm/compilation/aot.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ typedef struct AOTFunc {
/* offset of each local, including function parameters
and local variables */
uint16 *local_offsets;
#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
uint8 *code_body_begin;
#endif
} AOTFunc;
Expand Down Expand Up @@ -300,7 +300,7 @@ typedef struct AOTCompData {
dwarf_extractor_handle_t extractor;
#endif

#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
struct WASMCompilationHint **function_hints;
#endif
} AOTCompData;
Expand Down
16 changes: 14 additions & 2 deletions core/iwasm/compilation/aot_compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,12 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)

case WASM_OP_CALL_INDIRECT:
{
#if WASM_ENABLE_COMPILATION_HINTS != 0
const uint32 instr_offset =
(frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
#else
const uint32 instr_offset = 0;
#endif
uint32 tbl_idx;

read_leb_uint32(frame_ip, frame_ip_end, type_idx);
Expand All @@ -1246,7 +1252,7 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
}

if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx,
tbl_idx))
tbl_idx, instr_offset))
return false;
break;
}
Expand All @@ -1269,6 +1275,12 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)

case WASM_OP_RETURN_CALL_INDIRECT:
{
#if WASM_ENABLE_COMPILATION_HINTS != 0
const uint32 instr_offset =
(frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
#else
const uint32 instr_offset = 0;
#endif
uint32 tbl_idx;

if (!comp_ctx->enable_tail_call) {
Expand All @@ -1286,7 +1298,7 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
}

if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx,
tbl_idx))
tbl_idx, instr_offset))
return false;
if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip))
return false;
Expand Down
12 changes: 6 additions & 6 deletions core/iwasm/compilation/aot_emit_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,14 @@ aot_emit_branch_hint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
{
struct WASMCompilationHint *hint = func_ctx->function_hints;
while (hint != NULL) {
if (hint->type == WASM_COMPILATION_BRANCH_HINT
&& ((struct WASMCompilationHintBranchHint *)hint)->offset
== offset) {
if (hint->type == WASM_COMPILATION_HINT_BRANCH
&& hint->offset == offset) {
break;
}
hint = hint->next;
}
if (hint != NULL) {
((struct WASMCompilationHintBranchHint *)hint)->used = true;
Comment thread
Lukasdoe marked this conversation as resolved.
Outdated
// same weight llvm MDBuilder::createLikelyBranchWeights assigns
const uint32_t likely_weight = (1U << 20) - 1;
const uint32_t unlikely_weight = 1;
Expand Down Expand Up @@ -1094,11 +1094,11 @@ aot_compile_conditional_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint64 size;

// ip is advanced by one byte for the opcode
#if WASM_ENABLE_BRANCH_HINTS != 0
uint32 instr_offset =
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
const uint32 instr_offset =
(*p_frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
#else
uint32 instr_offset = 0;
const uint32 instr_offset = 0;
#endif
uint64 br_depth;
if (!read_leb(p_frame_ip, *p_frame_ip + 5, 32, false, &br_depth, NULL, 0))
Expand Down
71 changes: 67 additions & 4 deletions core/iwasm/compilation/aot_emit_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,65 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
return true;
}

#if WASM_ENABLE_COMPILATION_HINTS != 0
static void
aot_emit_call_target_hint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 offset, LLVMValueRef call_instr)
{
struct WASMCompilationHint *hint = func_ctx->function_hints;
while (hint != NULL) {
if (hint->type == WASM_COMPILATION_HINT_CALL_TARGETS
&& ((struct WASMCompilationHintCallTargets *)hint)->offset
== offset) {
break;
}
hint = hint->next;
}
if (hint != NULL) {
hint->used = true;
struct WASMCompilationHintCallTargets *ct_hint =
(struct WASMCompilationHintCallTargets *)hint;

const unsigned md_node_cnt = ct_hint->target_count * 2 + 3;
LLVMMetadataRef *md_nodes =
wasm_runtime_malloc(md_node_cnt * sizeof(LLVMMetadataRef));
if (!md_nodes) {
aot_set_last_error("allocate memory failed.");
return;
}

md_nodes[0] =
LLVMMDStringInContext2(comp_ctx->context, "VP", strlen("VP"));
md_nodes[1] = LLVMValueAsMetadata(I32_CONST(0));
// since wasm encodes a call frequency in full percent, we forward this
// to llvm as 100 calls to match the percentages
// (could be enhanced with the instruction frequency hints)
md_nodes[2] = LLVMValueAsMetadata(I64_CONST(100));

for (size_t i = 0; i < ct_hint->target_count; ++i) {
struct WASMCompilationHintCallTargetsHint *target =
&ct_hint->hints[i];
char target_func_name[48];
snprintf(target_func_name, sizeof(target_func_name), "%s%d",
AOT_FUNC_PREFIX,
target->func_idx - comp_ctx->comp_data->import_func_count);
const uint64_t func_name_hash =
aot_func_name_hash(target_func_name);
md_nodes[i * 2 + 3] =
LLVMValueAsMetadata(I64_CONST(func_name_hash));
md_nodes[i * 2 + 3 + 1] =
LLVMValueAsMetadata(I64_CONST(target->call_frequency));
}
LLVMMetadataRef meta_data =
LLVMMDNodeInContext2(comp_ctx->context, md_nodes, md_node_cnt);
LLVMValueRef meta_data_as_value =
LLVMMetadataAsValue(comp_ctx->context, meta_data);
LLVMSetMetadata(call_instr, 2, meta_data_as_value);
wasm_runtime_free(md_nodes);
}
}
#endif

/* Check whether there was exception thrown, if yes, return directly */
static bool
check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
Expand Down Expand Up @@ -1929,7 +1988,7 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef *param_values, uint32 param_count,
uint32 param_cell_num, uint32 result_count,
uint8 *wasm_ret_types, LLVMValueRef *value_rets,
LLVMValueRef *p_res)
LLVMValueRef *p_res, uint32 instr_offset)
{
LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
LLVMTypeRef ret_type, ret_ptr_type, elem_ptr_type;
Expand Down Expand Up @@ -2074,14 +2133,14 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
cell_num += wasm_value_type_cell_num_internal(wasm_ret_types[i],
comp_ctx->pointer_size);
}

*p_res = res;
return true;
}

bool
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 type_idx, uint32 tbl_idx)
uint32 type_idx, uint32 tbl_idx,
uint32 instr_offset)
{
AOTFuncType *func_type;
LLVMValueRef tbl_idx_value, elem_idx, func_idx;
Expand Down Expand Up @@ -2620,7 +2679,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
if (!call_aot_call_indirect_func(
comp_ctx, func_ctx, func_type, ftype_idx, tbl_idx_value, elem_idx,
param_types + 1, param_values + 1, func_param_count, param_cell_num,
func_result_count, wasm_ret_types, value_rets, &res))
func_result_count, wasm_ret_types, value_rets, &res, instr_offset))
goto fail;

/* Check whether exception was thrown when executing the function */
Expand Down Expand Up @@ -2681,6 +2740,10 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}

#if WASM_ENABLE_COMPILATION_HINTS != 0
aot_emit_call_target_hint(comp_ctx, func_ctx, instr_offset, value_ret);
#endif

/* Check whether exception was thrown when executing the function */
if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
&& !check_exception_thrown(comp_ctx, func_ctx))
Expand Down
3 changes: 2 additions & 1 deletion core/iwasm/compilation/aot_emit_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,

bool
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 type_idx, uint32 tbl_idx);
uint32 type_idx, uint32 tbl_idx,
uint32 instr_offset);

bool
aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
Expand Down
2 changes: 1 addition & 1 deletion core/iwasm/compilation/aot_llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1963,7 +1963,7 @@ aot_create_func_context(const AOTCompData *comp_data, AOTCompContext *comp_ctx,
goto fail;
}

#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
func_ctx->function_hints =
comp_ctx->comp_data->function_hints
? comp_ctx->comp_data->function_hints[func_index]
Expand Down
5 changes: 4 additions & 1 deletion core/iwasm/compilation/aot_llvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ typedef struct AOTFuncContext {
#if WASM_ENABLE_DEBUG_AOT != 0
LLVMMetadataRef debug_func;
#endif
#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
struct WASMCompilationHint *function_hints;
#endif

Expand Down Expand Up @@ -674,6 +674,9 @@ unsigned int
aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx,
const AOTFuncType *callee_func_type);

uint64_t
aot_func_name_hash(const char *name);

#ifdef __cplusplus
} /* end of extern "C" */
#endif
Expand Down
6 changes: 6 additions & 0 deletions core/iwasm/compilation/aot_llvm_extra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,9 @@ aot_compress_aot_func_names(AOTCompContext *comp_ctx, uint32 *p_size)
*p_size = compressed_str_len;
return compressed_str;
}

uint64_t
aot_func_name_hash(const char *name)
{
return MD5Hash(StringRef(name));
Comment thread
Lukasdoe marked this conversation as resolved.
}
28 changes: 24 additions & 4 deletions core/iwasm/interpreter/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ struct WASMFunction {
#endif
#endif

#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
uint8 *code_body_begin;
#endif
};
Expand All @@ -765,21 +765,41 @@ struct WASMTag {
};
#endif

#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
enum WASMCompilationHintType {
DUMMY = 0,
WASM_COMPILATION_BRANCH_HINT = 0,
WASM_COMPILATION_HINT_BRANCH = 1,
WASM_COMPILATION_HINT_CALL_TARGETS = 2,
};
struct WASMCompilationHint {
struct WASMCompilationHint *next;
enum WASMCompilationHintType type;
uint32 offset;
bool used;
Comment thread
lum1n0us marked this conversation as resolved.
};
struct WASMCompilationHintBranchHint {
struct WASMCompilationHint *next;
enum WASMCompilationHintType type;
uint32 offset;
bool used;
Comment thread
Lukasdoe marked this conversation as resolved.
Outdated

// custom field
bool is_likely;
};
struct WASMCompilationHintCallTargetsHint {
uint32 func_idx;
uint32 call_frequency;
};
struct WASMCompilationHintCallTargets {
struct WASMCompilationHint *next;
enum WASMCompilationHintType type;
uint32 offset;
bool used;

// custom fields
size_t target_count;
struct WASMCompilationHintCallTargetsHint *hints;
};
#endif

struct WASMGlobal {
Expand Down Expand Up @@ -1070,7 +1090,7 @@ struct WASMModule {
const uint8 *name_section_buf_end;
#endif

#if WASM_ENABLE_BRANCH_HINTS != 0
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
struct WASMCompilationHint **function_hints;
#endif

Expand Down
Loading
Loading