From 620bd76e76804b1fc1de46daa03724e23339e8bf Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Wed, 14 Nov 2018 08:43:22 -0500 Subject: [PATCH 1/1] fix __builtin_nan and add some missing builtins --- fold.cpp | 63 ++++++++++++++++++++++++++++++++++++++---------------- fold.h | 8 +++++-- intrin.cpp | 6 +++--- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/fold.cpp b/fold.cpp index 7b13db6..a982bf6 100644 --- a/fold.cpp +++ b/fold.cpp @@ -1486,29 +1486,54 @@ ast_expression *fold::intrinsic_pow(ast_value *lhs, ast_value *rhs) { ast_expression *fold::intrinsic_fabs(ast_value *a) { return constgen_float(fabsf(immvalue_float(a)), false); } +ast_expression* fold::intrinsic_nan(void) { + return constgen_float(0.0f / 0.0f, false); +} +ast_expression* fold::intrinsic_epsilon(void) { + static bool calculated = false; + static float eps = 1.0f; + if (!calculated) { + do { + eps /= 2.0f; + } while ((1.0f + (eps / 2.0f)) != 1.0f); + calculated = true; + } + return constgen_float(eps, false); +} -ast_expression *fold::intrinsic(const char *intrinsic, ast_expression **arg) { +ast_expression* fold::intrinsic_inf(void) { + return constgen_float(1.0f / 0.0f, false); +} + +ast_expression *fold::intrinsic(const char *intrinsic, size_t n_args, ast_expression **args) { ast_expression *ret = nullptr; - ast_value *a = (ast_value*)arg[0]; - ast_value *b = (ast_value*)arg[1]; - - if (!strcmp(intrinsic, "isfinite")) ret = intrinsic_isfinite(a); - if (!strcmp(intrinsic, "isinf")) ret = intrinsic_isinf(a); - if (!strcmp(intrinsic, "isnan")) ret = intrinsic_isnan(a); - if (!strcmp(intrinsic, "isnormal")) ret = intrinsic_isnormal(a); - if (!strcmp(intrinsic, "signbit")) ret = intrinsic_signbit(a); - if (!strcmp(intrinsic, "acosh")) ret = intrinsic_acosh(a); - if (!strcmp(intrinsic, "asinh")) ret = intrinsic_asinh(a); - if (!strcmp(intrinsic, "atanh")) ret = intrinsic_atanh(a); - if (!strcmp(intrinsic, "exp")) ret = intrinsic_exp(a); - if (!strcmp(intrinsic, "exp2")) ret = intrinsic_exp2(a); - if (!strcmp(intrinsic, "expm1")) ret = intrinsic_expm1(a); - if (!strcmp(intrinsic, "mod")) ret = intrinsic_mod(a, b); - if (!strcmp(intrinsic, "pow")) ret = intrinsic_pow(a, b); - if (!strcmp(intrinsic, "fabs")) ret = intrinsic_fabs(a); - if (ret) + if (n_args) { + ast_value *a = (ast_value*)args[0]; + ast_value *b = (ast_value*)args[1]; + if (!strcmp(intrinsic, "isfinite")) ret = intrinsic_isfinite(a); + if (!strcmp(intrinsic, "isinf")) ret = intrinsic_isinf(a); + if (!strcmp(intrinsic, "isnan")) ret = intrinsic_isnan(a); + if (!strcmp(intrinsic, "isnormal")) ret = intrinsic_isnormal(a); + if (!strcmp(intrinsic, "signbit")) ret = intrinsic_signbit(a); + if (!strcmp(intrinsic, "acosh")) ret = intrinsic_acosh(a); + if (!strcmp(intrinsic, "asinh")) ret = intrinsic_asinh(a); + if (!strcmp(intrinsic, "atanh")) ret = intrinsic_atanh(a); + if (!strcmp(intrinsic, "exp")) ret = intrinsic_exp(a); + if (!strcmp(intrinsic, "exp2")) ret = intrinsic_exp2(a); + if (!strcmp(intrinsic, "expm1")) ret = intrinsic_expm1(a); + if (!strcmp(intrinsic, "mod")) ret = intrinsic_mod(a, b); + if (!strcmp(intrinsic, "pow")) ret = intrinsic_pow(a, b); + if (!strcmp(intrinsic, "fabs")) ret = intrinsic_fabs(a); + } else { + if (!strcmp(intrinsic, "nan")) ret = intrinsic_nan(); + if (!strcmp(intrinsic, "epsilon")) ret = intrinsic_epsilon(); + if (!strcmp(intrinsic, "inf")) ret = intrinsic_inf(); + } + + if (ret) { ++opts_optimizationcount[OPTIM_CONST_FOLD]; + } return ret; } diff --git a/fold.h b/fold.h index 1d096e8..693231f 100644 --- a/fold.h +++ b/fold.h @@ -21,7 +21,7 @@ struct fold { bool generate(ir_builder *ir); ast_expression *op(const oper_info *info, ast_expression **opexprs); - ast_expression *intrinsic(const char *intrinsic, ast_expression **arg); + ast_expression *intrinsic(const char *intrinsic, size_t n_args, ast_expression **args); static int cond_ternary(ir_value *condval, ast_function *func, ast_ternary *branch); static int cond_ifthen(ir_value *condval, ast_function *func, ast_ifthen *branch); @@ -83,10 +83,14 @@ protected: ast_expression *intrinsic_exp(ast_value *a); ast_expression *intrinsic_exp2(ast_value *a); ast_expression *intrinsic_expm1(ast_value *a); - ast_expression *intrinsic_mod(ast_value *lhs, ast_value *rhs); ast_expression *intrinsic_pow(ast_value *lhs, ast_value *rhs); + ast_expression *intrinsic_mod(ast_value *lhs, ast_value *rhs); ast_expression *intrinsic_fabs(ast_value *a); + ast_expression* intrinsic_nan(void); + ast_expression* intrinsic_epsilon(void); + ast_expression* intrinsic_inf(void); + static qcfloat_t immvalue_float(ir_value *value); static vec3_t immvalue_vector(ir_value *value); diff --git a/intrin.cpp b/intrin.cpp index b37b50f..8053b31 100644 --- a/intrin.cpp +++ b/intrin.cpp @@ -32,8 +32,6 @@ void intrin::reg(ast_value *const value, ast_function *const func) { m_parser->globals.push_back(value); } -#define QC_POW_EPSILON 0.00001f - ast_expression *intrin::nullfunc() { ast_value *val = nullptr; ast_function *func = value(&val, nullptr, TYPE_VOID); @@ -575,6 +573,8 @@ ast_expression *intrin::expm1_() { } ast_expression *intrin::pow_() { + #define QC_POW_EPSILON 0.00001f + /* * * float pow(float base, float exp) { @@ -2005,7 +2005,7 @@ ast_expression *intrin::do_fold(ast_value *val, ast_expression **exprs) { if (val->m_name == it.name) return (vec_size(exprs) != it.args) ? nullptr - : m_fold->intrinsic(val->m_name.c_str() + kPrefixLength, exprs); + : m_fold->intrinsic(val->m_name.c_str() + kPrefixLength, it.args, exprs); } return nullptr; } -- 2.39.2