QCC: de-prioritise bitshift when trying to implement bit shifts - DP's implementation of the builtin is fucked and randomly flips bits (eg: when ReadShort returns negative values), so instead of bitshift(a,[-]b), use floor(a[*|/]pow(2,b)), its slower but harder for engines to fuck up.
Try to optimise a few maths builtins when given constant args, in an attempt to make up for the perf lost... git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5159 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
52f0f117ab
commit
f5b9ca55c9
1 changed files with 64 additions and 15 deletions
|
@ -3865,13 +3865,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
}
|
||||
else
|
||||
{
|
||||
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "bitshift", NULL, false, 0, 0);
|
||||
if (fnc.cast)
|
||||
{
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
|
||||
var_c.cast = *op->type_c;
|
||||
return var_c;
|
||||
}
|
||||
QCC_sref_t fnc;
|
||||
fnc = QCC_PR_GetSRef(NULL, "pow", NULL, false, 0, 0);
|
||||
if (fnc.cast)
|
||||
{ //a<<b === floor(a*pow(2,b))
|
||||
|
@ -3884,6 +3878,13 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
return var_c;
|
||||
}
|
||||
}
|
||||
fnc = QCC_PR_GetSRef(NULL, "bitshift", NULL, false, 0, 0);
|
||||
if (fnc.cast)
|
||||
{ //warning: DP's implementation of bitshift is fucked, hence why we favour the more expensibe floor+pow above.
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
|
||||
var_c.cast = *op->type_c;
|
||||
return var_c;
|
||||
}
|
||||
QCC_PR_ParseError(0, "bitshift function not defined: cannot emulate OP_LSHIFT_F*");
|
||||
break;
|
||||
}
|
||||
|
@ -3896,14 +3897,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
}
|
||||
else
|
||||
{
|
||||
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "bitshift", NULL, false, 0, 0);
|
||||
if (fnc.cast)
|
||||
{
|
||||
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_SUB_F], QCC_MakeFloatConst(0), var_b, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEB:0);
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
|
||||
var_c.cast = *op->type_c;
|
||||
return var_c;
|
||||
}
|
||||
QCC_sref_t fnc;
|
||||
fnc = QCC_PR_GetSRef(NULL, "pow", NULL, false, 0, 0);
|
||||
if (fnc.cast)
|
||||
{ //a<<b === floor(a/pow(2,b))
|
||||
|
@ -3916,6 +3910,14 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
|
|||
return var_c;
|
||||
}
|
||||
}
|
||||
fnc = QCC_PR_GetSRef(NULL, "bitshift", NULL, false, 0, 0);
|
||||
if (fnc.cast)
|
||||
{ //warning: DP's implementation of bitshift is fucked, hence why we favour the more expensibe floor+pow above
|
||||
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_SUB_F], QCC_MakeFloatConst(0), var_b, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEB:0);
|
||||
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
|
||||
var_c.cast = *op->type_c;
|
||||
return var_c;
|
||||
}
|
||||
QCC_PR_ParseError(0, "bitshift function not defined: cannot emulate OP_RSHIFT_F*");
|
||||
break;
|
||||
}
|
||||
|
@ -4959,6 +4961,53 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
|
|||
int firststatement;
|
||||
} args[MAX_PARMS+MAX_EXTRA_PARMS];
|
||||
|
||||
const char *funcname = QCC_GetSRefName(func);
|
||||
if (opt_constantarithmatic && argcount == 1 && arglist[0]->type == REF_GLOBAL)
|
||||
{
|
||||
const QCC_eval_t *a = QCC_SRef_EvalConst(arglist[0]->base);
|
||||
if (a)
|
||||
{
|
||||
// if (!strcmp(funcname, "isnan"))
|
||||
// return QCC_MakeFloatConst(isnan(a->_float));
|
||||
// if (!strcmp(funcname, "isinf"))
|
||||
// return QCC_MakeFloatConst(isinf(a->_float));
|
||||
if (!strcmp(funcname, "floor"))
|
||||
return QCC_MakeFloatConst(floor(a->_float));
|
||||
if (!strcmp(funcname, "ceil"))
|
||||
return QCC_MakeFloatConst(ceil(a->_float));
|
||||
if (!strcmp(funcname, "sin"))
|
||||
return QCC_MakeFloatConst(sin(a->_float));
|
||||
if (!strcmp(funcname, "cos"))
|
||||
return QCC_MakeFloatConst(cos(a->_float));
|
||||
if (!strcmp(funcname, "log"))
|
||||
return QCC_MakeFloatConst(log(a->_float));
|
||||
if (!strcmp(funcname, "sqrt"))
|
||||
return QCC_MakeFloatConst(sqrt(a->_float));
|
||||
// if (!strcmp(funcname, "ftos"))
|
||||
// return QCC_MakeStringConst(ftos(a->_float)); //engines differ too much in their ftos implementation for this to be worthwhile
|
||||
}
|
||||
}
|
||||
else if (opt_constantarithmatic && argcount == 2 && arglist[0]->type == REF_GLOBAL && arglist[1]->type == REF_GLOBAL)
|
||||
{
|
||||
const QCC_eval_t *a = QCC_SRef_EvalConst(arglist[0]->base);
|
||||
const QCC_eval_t *b = QCC_SRef_EvalConst(arglist[1]->base);
|
||||
if (a && b)
|
||||
{
|
||||
if (!strcmp(funcname, "pow"))
|
||||
return QCC_MakeFloatConst(pow(a->_float, b->_float));
|
||||
if (!strcmp(funcname, "mod"))
|
||||
return QCC_MakeFloatConst(fmodf((int)a->_float, (int)b->_float));
|
||||
if (!strcmp(funcname, "bitshift"))
|
||||
{
|
||||
if (b->_float < 0)
|
||||
return QCC_MakeFloatConst((int)a->_float >> (int)-b->_float);
|
||||
else
|
||||
return QCC_MakeFloatConst((int)a->_float << (int)b->_float);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func.sym->timescalled++;
|
||||
|
||||
if (!newself.cast && func.sym->constant && func.sym->allowinline)
|
||||
|
|
Loading…
Reference in a new issue