[macruby-changes] [1851] MacRuby/branches/fp-optimized-experimental

source_changes at macosforge.org source_changes at macosforge.org
Fri Jun 12 19:32:21 PDT 2009


Revision: 1851
          http://trac.macosforge.org/projects/ruby/changeset/1851
Author:   pthomson at apple.com
Date:     2009-06-12 19:32:21 -0700 (Fri, 12 Jun 2009)
Log Message:
-----------
Added support for optimizing functions that add a constant floating point value.

Modified Paths:
--------------
    MacRuby/branches/fp-optimized-experimental/compiler.cpp
    MacRuby/branches/fp-optimized-experimental/compiler.h

Modified: MacRuby/branches/fp-optimized-experimental/compiler.cpp
===================================================================
--- MacRuby/branches/fp-optimized-experimental/compiler.cpp	2009-06-13 00:54:47 UTC (rev 1850)
+++ MacRuby/branches/fp-optimized-experimental/compiler.cpp	2009-06-13 02:32:21 UTC (rev 1851)
@@ -1709,8 +1709,7 @@
 	}
 	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);
+		Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ, is_redefined_val, ConstantInt::getFalse(), "", bb);
 		
 		Function *f = bb->getParent();
 		
@@ -1740,6 +1739,261 @@
 	return NULL;
 }
 
+PHINode *
+RoxorCompiler::compile_variable_and_integral_node(SEL sel, long fixedLong, Value *targetVal, Value *otherVal, 
+												  int argc, std::vector<Value *> &params) {
+	
+	GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
+	// 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, is_redefined_val, ConstantInt::getFalse(), "", bb);
+	
+	Function *f = bb->getParent();
+	
+	BasicBlock *then1BB = BasicBlock::Create("op_not_redefined", f);
+	BasicBlock *then2BB = BasicBlock::Create("op_optimize", f);
+	BasicBlock *elseBB  = BasicBlock::Create("op_dispatch", f);
+	BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);
+	
+	BranchInst::Create(then1BB, elseBB, isOpRedefined, bb);
+	bb = then1BB;
+	
+	Value *andOp = BinaryOperator::CreateAnd(targetVal, threeVal, "", bb);
+	Value *isFixnum = new ICmpInst(ICmpInst::ICMP_EQ, andOp, oneVal, "", bb);
+	
+	
+	Value *fastEqqVal = NULL;
+	BasicBlock *fastEqqBB = NULL;
+	if (sel == selEqq) {
+		// compile_fast_eqq_call won't be called if #=== has been redefined
+		// fixnum optimizations are done separately
+		fastEqqBB = BasicBlock::Create("fast_eqq", f);
+		BranchInst::Create(then2BB, fastEqqBB, isFixnum, bb);
+		bb = fastEqqBB;
+		fastEqqVal = compile_fast_eqq_call(targetVal, otherVal);
+		fastEqqBB = bb;
+		BranchInst::Create(mergeBB, bb);
+	}
+	else {
+		BranchInst::Create(then2BB, elseBB, isFixnum, bb);
+	}
+	bb = then2BB;
+	
+	Value *unboxedLeft = ConstantInt::get(RubyObjTy, fixedLong);
+	Value *unboxedRight = BinaryOperator::CreateAShr(targetVal, twoVal, "", bb);
+	
+	Value *opVal;
+	bool result_is_fixnum = true;
+	if (sel == selPLUS) {
+		opVal = BinaryOperator::CreateAdd(unboxedLeft, unboxedRight, "", bb);
+	}
+	else if (sel == selMINUS) {
+		opVal = BinaryOperator::CreateSub(unboxedLeft, unboxedRight, "", bb);
+	}
+	else if (sel == selDIV) {
+		opVal = BinaryOperator::CreateSDiv(unboxedLeft, unboxedRight, "", bb);
+	}
+	else if (sel == selMULT) {
+		opVal = BinaryOperator::CreateMul(unboxedLeft, unboxedRight, "", bb);
+	}
+	else {
+		result_is_fixnum = false;
+		
+		CmpInst::Predicate predicate;
+		
+		if (sel == selLT) {
+		    predicate = ICmpInst::ICMP_SLT;
+		}
+		else if (sel == selLE) {
+		    predicate = ICmpInst::ICMP_SLE;
+		}
+		else if (sel == selGT) {
+		    predicate = ICmpInst::ICMP_SGT;
+		}
+		else if (sel == selGE) {
+		    predicate = ICmpInst::ICMP_SGE;
+		}
+		else if ((sel == selEq) || (sel == selEqq)) {
+		    predicate = ICmpInst::ICMP_EQ;
+		}
+		else if (sel == selNeq) {
+		    predicate = ICmpInst::ICMP_NE;
+		}
+		else {
+		    abort();
+		}
+		
+		opVal = new ICmpInst(predicate, unboxedLeft, unboxedRight, "", bb);
+		opVal = SelectInst::Create(opVal, trueVal, falseVal, "", bb);
+	}
+	
+	Value *thenVal;
+	BasicBlock *then3BB;
+	
+	if (result_is_fixnum) { 
+		Value *shift = BinaryOperator::CreateShl(opVal, twoVal, "", bb);
+		thenVal = BinaryOperator::CreateOr(shift, oneVal, "", bb);
+		
+		// Is result fixable?
+		Value *fixnumMax = ConstantInt::get(IntTy, FIXNUM_MAX + 1);
+		Value *isFixnumMaxOk = new ICmpInst(ICmpInst::ICMP_SLT, opVal, fixnumMax, "", bb);
+		
+		then3BB = BasicBlock::Create("op_fixable_max", f);
+		
+		BranchInst::Create(then3BB, elseBB, isFixnumMaxOk, bb);
+		
+		bb = then3BB;
+		Value *fixnumMin = ConstantInt::get(IntTy, FIXNUM_MIN);
+		Value *isFixnumMinOk = new ICmpInst(ICmpInst::ICMP_SGE, opVal, fixnumMin, "", bb);
+		
+		BranchInst::Create(mergeBB, elseBB, isFixnumMinOk, bb);
+	}
+	else {
+		thenVal = opVal;
+		then3BB = then2BB;
+		BranchInst::Create(mergeBB, then3BB);
+	}
+	
+	bb = elseBB;
+	Value *elseVal = compile_dispatch_call(params);
+	elseBB = bb;
+	BranchInst::Create(mergeBB, elseBB);
+	
+	bb = mergeBB;
+	PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
+	pn->addIncoming(thenVal, then3BB);
+	pn->addIncoming(elseVal, elseBB);
+	
+	if (sel == selEqq) {
+		pn->addIncoming(fastEqqVal, fastEqqBB);
+	}
+	
+	return pn;
+}
+
+PHINode *
+RoxorCompiler::compile_variable_and_floating_node(SEL sel, double fixedDouble, Value *targetVal, Value *otherVal,
+												  int argc, std::vector<Value *> &params)
+{
+	GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
+	// 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, is_redefined_val, ConstantInt::getFalse(), "", bb);
+	
+	Function *f = bb->getParent();
+	
+	BasicBlock *then1BB = BasicBlock::Create("op_not_redefined", f);
+	BasicBlock *then2BB = BasicBlock::Create("op_optimize", f);
+	BasicBlock *elseBB  = BasicBlock::Create("op_dispatch", f);
+	BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);
+	
+	BranchInst::Create(then1BB, elseBB, isOpRedefined, bb);
+	bb = then1BB;
+	
+	Value *andOp = BinaryOperator::CreateAnd(targetVal, threeVal, "", bb);
+	Value *isDouble = new ICmpInst(ICmpInst::ICMP_EQ, andOp, oneVal, "", bb);
+	
+	Value *fastEqqVal = NULL;
+	BasicBlock *fastEqqBB = NULL;
+	if (sel == selEqq) {
+		// compile_fast_eqq_call won't be called if #=== has been redefined
+		// fixnum optimizations are done separately
+		fastEqqBB = BasicBlock::Create("fast_eqq", f);
+		BranchInst::Create(then2BB, fastEqqBB, isDouble, bb);
+		bb = fastEqqBB;
+		fastEqqVal = compile_fast_eqq_call(targetVal, otherVal);
+		fastEqqBB = bb;
+		BranchInst::Create(mergeBB, bb);
+	}
+	else {
+		BranchInst::Create(then2BB, elseBB, isDouble, bb);
+	}
+	bb = then2BB;
+	
+	Value *left = ConstantFP::get(Type::DoubleTy, fixedDouble);
+	Value *right = BinaryOperator::CreateXor(targetVal, threeVal, "", bb);
+	right = new BitCastInst(right, Type::DoubleTy, "", bb);
+	
+	
+	Value *opVal;
+	bool result_is_double = true;
+	if (sel == selPLUS) {
+		opVal = BinaryOperator::CreateAdd(left, right, "", bb);
+	}
+	else if (sel == selMINUS) {
+		opVal = BinaryOperator::CreateSub(left, right, "", bb);
+	}
+	else if (sel == selDIV) {
+		opVal = BinaryOperator::CreateSDiv(left, right, "", bb);
+	}
+	else if (sel == selMULT) {
+		opVal = BinaryOperator::CreateMul(left, right, "", bb);
+	}
+	else {
+		result_is_double = false;
+		
+		CmpInst::Predicate predicate;
+		
+		if (sel == selLT) {
+		    predicate = FCmpInst::FCMP_OLT;
+		}
+		else if (sel == selLE) {
+		    predicate = FCmpInst::FCMP_OLE;
+		}
+		else if (sel == selGT) {
+		    predicate = FCmpInst::FCMP_OGT;
+		}
+		else if (sel == selGE) {
+		    predicate = FCmpInst::FCMP_OGE;
+		}
+		else if ((sel == selEq) || (sel == selEqq)) {
+		    predicate = FCmpInst::FCMP_OEQ;
+		}
+		else if (sel == selNeq) {
+		    predicate = FCmpInst::FCMP_ONE;
+		}
+		else {
+		    abort();
+		}
+		
+		opVal = new FCmpInst(predicate, left, right, "", bb);
+		opVal = SelectInst::Create(opVal, trueVal, falseVal, "", bb);
+	}
+	
+	Value *thenVal;
+	BasicBlock *then3BB;
+	
+	if (result_is_double) { 
+		Value *casted = new BitCastInst(opVal, IntTy, "", bb);
+		thenVal = BinaryOperator::CreateOr(casted, threeVal, "", bb);
+		
+		then3BB = then2BB;
+		BranchInst::Create(mergeBB, then3BB);
+	}
+	else {
+		thenVal = opVal;
+		then3BB = then2BB;
+		BranchInst::Create(mergeBB, then3BB);
+	}
+	
+	bb = elseBB;
+	Value *elseVal = compile_dispatch_call(params);
+	elseBB = bb;
+	BranchInst::Create(mergeBB, elseBB);
+	
+	bb = mergeBB;
+	PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
+	pn->addIncoming(thenVal, then3BB);
+	pn->addIncoming(elseVal, elseBB);
+	
+	if (sel == selEqq) {
+		pn->addIncoming(fastEqqVal, fastEqqBB);
+	}
+	
+	return pn;
+	
+}
+
 Value *
 RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, std::vector<Value *> &params)
 {
@@ -1756,8 +2010,6 @@
 	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();
@@ -1802,168 +2054,23 @@
 	else if (leftIsFixFloatConstant && rightIsFixFloatConstant) {
 		return precompile_floating_arith_node(sel, leftDouble, rightDouble, argc, params);
 	}
-	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, 
-		    is_redefined_val, ConstantInt::getFalse(), "", bb);
-
-	    Function *f = bb->getParent();
-
-	    BasicBlock *then1BB = BasicBlock::Create("op_not_redefined", f);
-	    BasicBlock *then2BB = BasicBlock::Create("op_optimize", f);
-	    BasicBlock *elseBB  = BasicBlock::Create("op_dispatch", f);
-	    BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);
-
-	    BranchInst::Create(then1BB, elseBB, isOpRedefined, bb);
-
- 	    bb = then1BB;
-
-	    Value *leftAndOp = NULL;
-	    if (!leftIsFixnumConstant) {
-		leftAndOp = BinaryOperator::CreateAnd(leftVal, threeVal, "", 
-			bb);
-	    }
-
-	    Value *rightAndOp = NULL;
-	    if (!rightIsFixnumConstant) {
-		rightAndOp = BinaryOperator::CreateAnd(rightVal, threeVal, "", 
-			bb);
-	    }
-
-	    Value *areFixnums = NULL;
-	    if (leftAndOp != NULL && rightAndOp != NULL) {
-		Value *foo = BinaryOperator::CreateAdd(leftAndOp, rightAndOp, 
-			"", bb);
-		areFixnums = new ICmpInst(ICmpInst::ICMP_EQ, foo, twoVal, "", bb);
-	    }
-	    else if (leftAndOp != NULL) {
-		areFixnums = new ICmpInst(ICmpInst::ICMP_EQ, leftAndOp, oneVal, "", bb);
-	    }
-	    else {
-		areFixnums = new ICmpInst(ICmpInst::ICMP_EQ, rightAndOp, oneVal, "", bb);
-	    }
-	
-	    Value *fastEqqVal = NULL;
-	    BasicBlock *fastEqqBB = NULL;
-	    if (sel == selEqq) {
-		// compile_fast_eqq_call won't be called if #=== has been redefined
-		// fixnum optimizations are done separately
-		fastEqqBB = BasicBlock::Create("fast_eqq", f);
-		BranchInst::Create(then2BB, fastEqqBB, areFixnums, bb);
-		bb = fastEqqBB;
-		fastEqqVal = compile_fast_eqq_call(leftVal, rightVal);
-		fastEqqBB = bb;
-		BranchInst::Create(mergeBB, bb);
-	    }
-	    else {
-		BranchInst::Create(then2BB, elseBB, areFixnums, bb);
-	    }
-	    bb = then2BB;
-
-	    Value *unboxedLeft;
-	    if (leftIsFixnumConstant) {
-		unboxedLeft = ConstantInt::get(RubyObjTy, leftLong);
-	    }
-	    else {
-		unboxedLeft = BinaryOperator::CreateAShr(leftVal, twoVal, "", bb);
-	    }
-
-	    Value *unboxedRight;
-	    if (rightIsFixnumConstant) {
-		unboxedRight = ConstantInt::get(RubyObjTy, rightLong);
-	    }
-	    else {
-		unboxedRight = BinaryOperator::CreateAShr(rightVal, twoVal, "", bb);
-	    }
-
-	    Value *opVal;
-	    bool result_is_fixnum = true;
-	    if (sel == selPLUS) {
-		opVal = BinaryOperator::CreateAdd(unboxedLeft, unboxedRight, "", bb);
-	    }
-	    else if (sel == selMINUS) {
-		opVal = BinaryOperator::CreateSub(unboxedLeft, unboxedRight, "", bb);
-	    }
-	    else if (sel == selDIV) {
-		opVal = BinaryOperator::CreateSDiv(unboxedLeft, unboxedRight, "", bb);
-	    }
-	    else if (sel == selMULT) {
-		opVal = BinaryOperator::CreateMul(unboxedLeft, unboxedRight, "", bb);
-	    }
-	    else {
-		result_is_fixnum = false;
-
-		CmpInst::Predicate predicate;
-
-		if (sel == selLT) {
-		    predicate = ICmpInst::ICMP_SLT;
+	else if ((!(leftIsFixFloatConstant || rightIsFixFloatConstant)) && (leftIsFixnumConstant || rightIsFixnumConstant)) {
+		// One of the operands is a fixnum, the other is a variable
+		if (leftIsFixnumConstant) {
+			return compile_variable_and_integral_node(sel, leftLong, rightVal, leftVal, argc, params);
 		}
-		else if (sel == selLE) {
-		    predicate = ICmpInst::ICMP_SLE;
+		else {
+			return compile_variable_and_integral_node(sel, rightLong, leftVal, rightVal, argc, params);
 		}
-		else if (sel == selGT) {
-		    predicate = ICmpInst::ICMP_SGT;
+	} else if((!(leftIsFixnumConstant || rightIsFixnumConstant)) && (leftIsFixFloatConstant || rightIsFixFloatConstant)) {
+		if (leftIsFixFloatConstant) {
+			return compile_variable_and_floating_node(sel, leftDouble, rightVal, leftVal, argc, params);
+		} else {
+			return compile_variable_and_floating_node(sel, rightDouble, leftVal, rightVal, argc, params);
 		}
-		else if (sel == selGE) {
-		    predicate = ICmpInst::ICMP_SGE;
-		}
-		else if ((sel == selEq) || (sel == selEqq)) {
-		    predicate = ICmpInst::ICMP_EQ;
-		}
-		else if (sel == selNeq) {
-		    predicate = ICmpInst::ICMP_NE;
-		}
-		else {
-		    abort();
-		}
-
-		opVal = new ICmpInst(predicate, unboxedLeft, unboxedRight, "", bb);
-		opVal = SelectInst::Create(opVal, trueVal, falseVal, "", bb);
-	    }
-
-	    Value *thenVal;
-	    BasicBlock *then3BB;
-
-	    if (result_is_fixnum) { 
-		Value *shift = BinaryOperator::CreateShl(opVal, twoVal, "", bb);
-		thenVal = BinaryOperator::CreateOr(shift, oneVal, "", bb);
-
-		// Is result fixable?
-		Value *fixnumMax = ConstantInt::get(IntTy, FIXNUM_MAX + 1);
-		Value *isFixnumMaxOk = new ICmpInst(ICmpInst::ICMP_SLT, opVal, fixnumMax, "", bb);
-
-		then3BB = BasicBlock::Create("op_fixable_max", f);
-
-		BranchInst::Create(then3BB, elseBB, isFixnumMaxOk, bb);
-
-		bb = then3BB;
-		Value *fixnumMin = ConstantInt::get(IntTy, FIXNUM_MIN);
-		Value *isFixnumMinOk = new ICmpInst(ICmpInst::ICMP_SGE, opVal, fixnumMin, "", bb);
-
-		BranchInst::Create(mergeBB, elseBB, isFixnumMinOk, bb);
-	    }
-	    else {
-		thenVal = opVal;
-		then3BB = then2BB;
-		BranchInst::Create(mergeBB, then3BB);
-	    }
-
-	    bb = elseBB;
-	    Value *elseVal = compile_dispatch_call(params);
-	    elseBB = bb;
-	    BranchInst::Create(mergeBB, elseBB);
-
-	    bb = mergeBB;
-	    PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
-	    pn->addIncoming(thenVal, then3BB);
-	    pn->addIncoming(elseVal, elseBB);
-
-	    if (sel == selEqq) {
-		pn->addIncoming(fastEqqVal, fastEqqBB);
-	    }
-
-	    return pn;
+	} else {
+		printf("Both are variables, dying\n");
+		return NULL;
 	}
 	}
     // Other operators (#<< or #[] or #[]=)
@@ -2066,6 +2173,7 @@
 	bb = mergeBB;
 	PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
 	pn->addIncoming(thenVal, thenBB);
+	
 	pn->addIncoming(elseVal, elseBB);
 
 	return pn;
@@ -2125,6 +2233,8 @@
 	PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
 	pn->addIncoming(thenVal, thenBB);
 	pn->addIncoming(elseVal, elseBB);
+		
+	
 
 	return pn;
 

Modified: MacRuby/branches/fp-optimized-experimental/compiler.h
===================================================================
--- MacRuby/branches/fp-optimized-experimental/compiler.h	2009-06-13 00:54:47 UTC (rev 1850)
+++ MacRuby/branches/fp-optimized-experimental/compiler.h	2009-06-13 02:32:21 UTC (rev 1851)
@@ -183,9 +183,13 @@
 	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);
+	PHINode *
+	compile_variable_and_integral_node(SEL sel, long fixedLong, Value *val, Value *other, int argc,
+													  std::vector<Value *> &params);
+	PHINode *
+	compile_variable_and_floating_node(SEL sel, double fixedDouble, Value *val, Value *other,
+									   int argc, std::vector<Value *> &params);
 
-
-
 	Value *compile_protected_call(Function *func,
 		std::vector<Value *> &params);
 	void compile_dispatch_arguments(NODE *args,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090612/c0a79f0c/attachment-0001.html>


More information about the macruby-changes mailing list