Use normal i64 arithmetic instead of big-ints for hot path

This commit is contained in:
gingerBill
2026-03-17 13:34:06 +00:00
parent 46936e0e52
commit 153a522228
3 changed files with 66 additions and 14 deletions

View File

@@ -57,6 +57,8 @@ gb_internal void big_int_dealloc(BigInt *dst) {
mp_clear(dst);
}
gb_internal bool big_int_can_be_represented_in_64_bits(BigInt const *x);
gb_internal BigInt big_int_make(BigInt const *b, bool abs=false);
gb_internal BigInt big_int_make_abs(BigInt const *b);
gb_internal BigInt big_int_make_u64(u64 x);
@@ -293,6 +295,11 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success
gb_internal bool big_int_can_be_represented_in_64_bits(BigInt const *x) {
int bits_used = (x->used-1) * MP_DIGIT_BIT;
return bits_used <= 64;
}
gb_internal u64 big_int_to_u64(BigInt const *x) {
GB_ASSERT(x->sign == 0);
return mp_get_u64(x);

View File

@@ -2167,9 +2167,13 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i
BigInt i = v.value_integer;
i64 byte_size = type_size_of(type);
BigInt umax = {};
BigInt imin = {};
BigInt imax = {};
BigInt umax;
BigInt imin;
BigInt imax;
u64 umax_64 = 0;
i64 imin_64 = 0;
i64 imax_64 = 0;
if (c->bit_field_bit_size > 0) {
i64 bit_size = gb_min(cast(i64)(8*byte_size), cast(i64)c->bit_field_bit_size);
@@ -2192,10 +2196,10 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i
big_int_shl_eq(&imax, &bi);
mp_decr(&imax);
} else {
if (byte_size < 16) {
big_int_from_u64(&umax, unsigned_integer_maxs[byte_size]);
big_int_from_i64(&imin, signed_integer_mins[byte_size]);
big_int_from_i64(&imax, signed_integer_maxs[byte_size]);
if (byte_size <= 8) {
umax_64 = unsigned_integer_maxs[byte_size];
imin_64 = signed_integer_mins[byte_size];
imax_64 = signed_integer_maxs[byte_size];
} else {
big_int_from_u64(&umax, 1);
big_int_from_i64(&imin, 1);
@@ -2223,16 +2227,27 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i
case Basic_i16:
case Basic_i32:
case Basic_i64:
case Basic_i128:
case Basic_int:
case Basic_i16le:
case Basic_i32le:
case Basic_i64le:
case Basic_i128le:
case Basic_i16be:
case Basic_i32be:
case Basic_i64be:
{
// return imin <= i && i <= imax;
if (!big_int_can_be_represented_in_64_bits(&i)) {
return false;
}
i64 val64 = big_int_to_i64(&i);
return imin_64 <= val64 && val64 <= imax_64;
}
case Basic_i128le:
case Basic_i128:
case Basic_i128be:
{
// return imin <= i && i <= imax;
@@ -2245,17 +2260,30 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i
case Basic_u16:
case Basic_u32:
case Basic_u64:
case Basic_u128:
case Basic_uint:
case Basic_uintptr:
case Basic_u16le:
case Basic_u32le:
case Basic_u64le:
case Basic_u128le:
case Basic_u16be:
case Basic_u32be:
case Basic_u64be:
{
if (big_int_is_neg(&i)) {
return false;
}
if (!big_int_can_be_represented_in_64_bits(&i)) {
return false;
}
u64 val64 = big_int_to_u64(&i);
return val64 <= umax_64;
}
case Basic_u128:
case Basic_u128le:
case Basic_u128be:
{
// return 0ull <= i && i <= umax;

View File

@@ -2442,6 +2442,9 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res
}
}
Entity *entities_to_use = permanent_alloc_array<Entity>(variable_count);
isize entities_to_use_index = 0;
auto variables = array_make<Entity *>(permanent_allocator(), 0, variable_count);
i32 field_group_index = -1;
for_array(i, results) {
@@ -2480,7 +2483,12 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res
if (field->names.count == 0) {
Token token = ast_token(field->type);
token.string = str_lit("");
Entity *param = alloc_entity_param(scope, token, type, false, false);
// Entity *param = alloc_entity_param(scope, token, type, false, false);
Entity *param = &entities_to_use[entities_to_use_index++];
INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, token, type);
param->state = EntityState_Resolved;
param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Result;
param->Variable.param_value = param_value;
param->Variable.field_group_index = -1;
array_add(&variables, param);
@@ -2503,8 +2511,17 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res
error(name, "Result value cannot be a blank identifer `_`");
}
Entity *param = alloc_entity_param(scope, token, type, false, false);
param->flags |= EntityFlag_Result;
// Entity *param = alloc_entity_param(scope, token, type, false, false);
Entity *param = &entities_to_use[entities_to_use_index++];
INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, token, type);
param->state = EntityState_Resolved;
param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Result;
if (name->kind == Ast_Ident) {
param->interned_name.store(name->Ident.interned);
param->interned_name_hash.store(name->Ident.hash);
}
param->Variable.param_value = param_value;
param->Variable.field_group_index = field_group_index;
array_add(&variables, param);