Skip to content

Commit

Permalink
More refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Thomson committed Jun 12, 2009
1 parent d12840f commit c87324d
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 148 deletions.
309 changes: 161 additions & 148 deletions compiler.cpp
Expand Up @@ -1584,84 +1584,106 @@ RoxorCompiler::compile_symbol_equality_node(SEL sel, VALUE leftRVal, VALUE right
return pn;
}

Value *
RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, std::vector<Value *> &params)
PHINode *
RoxorCompiler::precompile_floating_arith_node(SEL sel, double leftDouble, long rightDouble, int argc, std::vector<Value *> &params)
{
// The not operator (!).
if (sel == selNot) {
return compile_negation_node(argc, params[1]);
GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
bool result_is_fixfloat = true;
double res;
// TODO: put checks in here for NaN, +/- infinity
if (sel == selPLUS) {
res = leftDouble + rightDouble;
}
// Pure arithmetic operations.
else if (sel == selPLUS || sel == selMINUS || sel == selDIV
|| sel == selMULT || sel == selLT || sel == selLE
|| sel == selGT || sel == selGE || sel == selEq
|| sel == selNeq || sel == selEqq) {

if (current_block_func != NULL || argc != 1) {
return NULL;
else if (sel == selMINUS) {
res = leftDouble - rightDouble;
}

GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);

Value *leftVal = params[1]; // self
Value *rightVal = params.back();

VALUE leftRVal = 0, rightRVal = 0;
const bool leftIsConstant = unbox_ruby_constant(leftVal, &leftRVal);
const bool rightIsConst = unbox_ruby_constant(rightVal, &rightRVal);

if (leftIsConstant && rightIsConst && TYPE(leftRVal) == T_SYMBOL && TYPE(rightRVal) == T_SYMBOL) {
// Both operands are symbol constants.
if (sel == selEq || sel == selEqq || sel == selNeq) {
return compile_symbol_equality_node(sel, leftRVal, rightRVal, argc, params);
}
else {
return NULL;
}
else if (sel == selMULT) {
res = leftDouble * rightDouble;
}

const bool leftIsFixnumConstant = FIXNUM_P(leftRVal);
const bool rightIsFixnumConstant = FIXNUM_P(rightRVal);

long leftLong = leftIsFixnumConstant ? FIX2LONG(leftRVal) : 0;
long rightLong = rightIsFixnumConstant ? FIX2LONG(rightRVal) : 0;

bool leftIsFixFloatConstant = FIXFLOAT_P(leftRVal);
bool rightIsFixFloatConstant = FIXFLOAT_P(rightRVal);

double leftDouble = leftIsFixFloatConstant ? FIXFLOAT2DBL(leftRVal) : 0;
double rightDouble = rightIsFixFloatConstant ? FIXFLOAT2DBL(rightRVal) : 0;

if (leftIsFixFloatConstant && rightIsFixnumConstant) {
rightIsFixFloatConstant = true;
rightDouble = (double)rightLong;
else if (sel == selDIV) {
if (rightDouble == 0.0) {
return NULL;
}
res = leftDouble / rightDouble;
} else {
result_is_fixfloat = false;
if (sel == selLT) {
res = leftDouble < rightDouble;
}
else if (sel == selLE) {
res = leftDouble <= rightDouble;
}
else if (sel == selGT) {
res = leftDouble > rightDouble;
}
else if (sel == selGE) {
res = leftDouble >= rightDouble;
}
else if ((sel == selEq) || (sel == selEqq)) {
res = leftDouble == rightDouble;
}
else if (sel == selNeq) {
res = leftDouble != rightDouble;
}
else {
abort();
}
}
else if (leftIsFixnumConstant && rightIsFixFloatConstant) {
leftIsFixFloatConstant = true;
leftDouble = (double)leftLong;
if (!result_is_fixfloat || FIXABLE_DBL(res)) {
Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ,
is_redefined_val, ConstantInt::getFalse(), "", bb);

Function *f = bb->getParent();

BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f);
BasicBlock *elseBB = BasicBlock::Create("op_dispatch", f);
BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);

BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
Value *thenVal = result_is_fixfloat
? ConstantInt::get(RubyObjTy, DBL2FIXFLOAT(res))
: (res == 1 ? trueVal : falseVal);
BranchInst::Create(mergeBB, thenBB);

bb = elseBB;
Value *elseVal = compile_dispatch_call(params);
elseBB = bb;
BranchInst::Create(mergeBB, elseBB);

PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
pn->addIncoming(thenVal, thenBB);
pn->addIncoming(elseVal, elseBB);
bb = mergeBB;

return pn;
}
return NULL; // loss of precision, call the dispatcher.
}

if (leftIsFixnumConstant && rightIsFixnumConstant) {
// Both operands are fixnum constants.
bool result_is_fixnum = true;
long res;

if (sel == selPLUS) {
PHINode *
RoxorCompiler::precompile_integral_arith_node(SEL sel, long leftLong, long rightLong, int argc, std::vector<Value *> &params)
{
GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
bool result_is_fixnum = true;
long res;

if (sel == selPLUS) {
res = leftLong + rightLong;
}
else if (sel == selMINUS) {
}
else if (sel == selMINUS) {
res = leftLong - rightLong;
}
else if (sel == selDIV) {
}
else if (sel == selDIV) {
if (rightLong == 0) {
return NULL;
}
res = leftLong / rightLong;
}
else if (sel == selMULT) {
}
else if (sel == selMULT) {
res = leftLong * rightLong;
}
else {
}
else {
result_is_fixnum = false;
if (sel == selLT) {
res = leftLong < rightLong;
Expand All @@ -1684,112 +1706,103 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, std::vector<Va
else {
abort();
}
}
if (!result_is_fixnum || FIXABLE(res)) {
}
if (!result_is_fixnum || FIXABLE(res)) {
Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ,
is_redefined_val, ConstantInt::getFalse(), "", bb);

is_redefined_val, ConstantInt::getFalse(), "", bb);
Function *f = bb->getParent();

BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f);
BasicBlock *elseBB = BasicBlock::Create("op_dispatch", f);
BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);

BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
Value *thenVal = result_is_fixnum
? ConstantInt::get(RubyObjTy, LONG2FIX(res))
: (res == 1 ? trueVal : falseVal);
? ConstantInt::get(RubyObjTy, LONG2FIX(res))
: (res == 1 ? trueVal : falseVal);
BranchInst::Create(mergeBB, thenBB);

bb = elseBB;
Value *elseVal = compile_dispatch_call(params);
elseBB = bb;
BranchInst::Create(mergeBB, elseBB);

PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
pn->addIncoming(thenVal, thenBB);
pn->addIncoming(elseVal, elseBB);
bb = mergeBB;

return pn;
}
// Non fixable (bignum), call the dispatcher.
}
// Non fixable (bignum), call the dispatcher.
return NULL;
}

Value *
RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, std::vector<Value *> &params)
{
// The not operator (!).
if (sel == selNot) {
return compile_negation_node(argc, params[1]);
}
// Pure arithmetic operations.
else if (sel == selPLUS || sel == selMINUS || sel == selDIV
|| sel == selMULT || sel == selLT || sel == selLE
|| sel == selGT || sel == selGE || sel == selEq
|| sel == selNeq || sel == selEqq) {

if (current_block_func != NULL || argc != 1) {
return NULL;
}

GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);

Value *leftVal = params[1]; // self
Value *rightVal = params.back();

VALUE leftRVal = 0, rightRVal = 0;
const bool leftIsConstant = unbox_ruby_constant(leftVal, &leftRVal);
const bool rightIsConst = unbox_ruby_constant(rightVal, &rightRVal);

if (leftIsConstant && rightIsConst && TYPE(leftRVal) == T_SYMBOL && TYPE(rightRVal) == T_SYMBOL) {
// Both operands are symbol constants.
if (sel == selEq || sel == selEqq || sel == selNeq) {
return compile_symbol_equality_node(sel, leftRVal, rightRVal, argc, params);
}
else {
return NULL;
}
}

const bool leftIsFixnumConstant = FIXNUM_P(leftRVal);
const bool rightIsFixnumConstant = FIXNUM_P(rightRVal);

long leftLong = leftIsFixnumConstant ? FIX2LONG(leftRVal) : 0;
long rightLong = rightIsFixnumConstant ? FIX2LONG(rightRVal) : 0;

bool leftIsFixFloatConstant = FIXFLOAT_P(leftRVal);
bool rightIsFixFloatConstant = FIXFLOAT_P(rightRVal);

double leftDouble = leftIsFixFloatConstant ? FIXFLOAT2DBL(leftRVal) : 0;
double rightDouble = rightIsFixFloatConstant ? FIXFLOAT2DBL(rightRVal) : 0;



if (leftIsFixnumConstant && rightIsFixnumConstant) {
return precompile_integral_arith_node(sel, leftLong, rightLong, argc, params);
}
else if (leftIsFixFloatConstant && rightIsFixnumConstant) {
return precompile_floating_arith_node(sel, leftDouble, (double)rightLong, argc, params);
}
else if (leftIsFixnumConstant && rightIsFixFloatConstant) {
return precompile_floating_arith_node(sel, (double)leftLong, rightDouble, argc, params);
}
else if (leftIsFixFloatConstant && rightIsFixFloatConstant) {
bool result_is_fixfloat = true;
double res;
// TODO: put checks in here for NaN, +/- infinity
if (sel == selPLUS) {
res = leftDouble + rightDouble;
}
else if (sel == selMINUS) {
res = leftDouble - rightDouble;
}
else if (sel == selMULT) {
res = leftDouble * rightDouble;
}
else if (sel == selDIV) {
if (rightDouble == 0.0) {
return NULL;
}
res = leftDouble / rightDouble;
} else {
result_is_fixfloat = false;
if (sel == selLT) {
res = leftDouble < rightDouble;
}
else if (sel == selLE) {
res = leftDouble <= rightDouble;
}
else if (sel == selGT) {
res = leftDouble > rightDouble;
}
else if (sel == selGE) {
res = leftDouble >= rightDouble;
}
else if ((sel == selEq) || (sel == selEqq)) {
res = leftDouble == rightDouble;
}
else if (sel == selNeq) {
res = leftDouble != rightDouble;
}
else {
abort();
}
}
if (!result_is_fixfloat || FIXABLE_DBL(res)) {
Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ,
is_redefined_val, ConstantInt::getFalse(), "", bb);

Function *f = bb->getParent();

BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f);
BasicBlock *elseBB = BasicBlock::Create("op_dispatch", f);
BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);

BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
Value *thenVal = result_is_fixfloat
? ConstantInt::get(RubyObjTy, DBL2FIXFLOAT(res))
: (res == 1 ? trueVal : falseVal);
BranchInst::Create(mergeBB, thenBB);

bb = elseBB;
Value *elseVal = compile_dispatch_call(params);
elseBB = bb;
BranchInst::Create(mergeBB, elseBB);

PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
pn->addIncoming(thenVal, thenBB);
pn->addIncoming(elseVal, elseBB);
bb = mergeBB;

return pn;
}
return precompile_floating_arith_node(sel, leftDouble, rightDouble, argc, params);
}
else if (!(leftIsFixFloatConstant || rightIsFixFloatConstant)){
else if (!(leftIsFixFloatConstant || rightIsFixFloatConstant)) {
// Either one or both of the operands was not a fixable constant.
Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ,
Expand Down
5 changes: 5 additions & 0 deletions compiler.h
Expand Up @@ -179,6 +179,11 @@ class RoxorCompiler {

PHINode *compile_negation_node(int argc, Value *val);
PHINode *compile_symbol_equality_node(SEL sel, VALUE leftRVal, VALUE rightRVal, int argc, std::vector<Value *> &params);
PHINode *
precompile_integral_arith_node(SEL sel, long leftLong, long rightLong, int argc, std::vector<Value *> &params);
PHINode *
precompile_floating_arith_node(SEL sel, double leftDouble, long rightDouble, int argc, std::vector<Value *> &params);



Value *compile_protected_call(Function *func,
Expand Down

0 comments on commit c87324d

Please sign in to comment.