Improve the assembly code for power function with integer exponential on x64
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Sep 2012 08:04:31 +0000 (08:04 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Sep 2012 08:04:31 +0000 (08:04 +0000)
The change removes one unused multiply and reschedules
the shift, multiply and jump instructions to reduce
stall. Experiment shows it improve about 20% performance
on x64 for exponetials from about 100 to 2000.

Review URL: https://chromiumcodereview.appspot.com/10939013
Patch from Xi Qian <xi.qian@intel.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12535 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/code-stubs-ia32.cc
src/x64/code-stubs-x64.cc

index 1fdbaf1..96d45d3 100644 (file)
@@ -3213,7 +3213,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
   __ movsd(double_scratch2, double_result);  // Load double_exponent with 1.
 
   // Get absolute value of exponent.
-  Label no_neg, while_true, no_multiply, while_false;
+  Label no_neg, while_true, while_false;
   __ test(scratch, scratch);
   __ j(positive, &no_neg, Label::kNear);
   __ neg(scratch);
index 62a89b8..c5025cf 100644 (file)
@@ -2262,21 +2262,28 @@ void MathPowStub::Generate(MacroAssembler* masm) {
   __ movsd(double_scratch2, double_result);  // Load double_exponent with 1.
 
   // Get absolute value of exponent.
-  Label no_neg, while_true, no_multiply;
+  Label no_neg, while_true, while_false;
   __ testl(scratch, scratch);
   __ j(positive, &no_neg, Label::kNear);
   __ negl(scratch);
   __ bind(&no_neg);
 
-  __ bind(&while_true);
+  __ j(zero, &while_false, Label::kNear);
   __ shrl(scratch, Immediate(1));
-  __ j(not_carry, &no_multiply, Label::kNear);
-  __ mulsd(double_result, double_scratch);
-  __ bind(&no_multiply);
+  // Above condition means CF==0 && ZF==0.  This means that the
+  // bit that has been shifted out is 0 and the result is not 0.
+  __ j(above, &while_true, Label::kNear);
+  __ movsd(double_result, double_scratch);
+  __ j(zero, &while_false, Label::kNear);
 
+  __ bind(&while_true);
+  __ shrl(scratch, Immediate(1));
   __ mulsd(double_scratch, double_scratch);
+  __ j(above, &while_true, Label::kNear);
+  __ mulsd(double_result, double_scratch);
   __ j(not_zero, &while_true);
 
+  __ bind(&while_false);
   // If the exponent is negative, return 1/result.
   __ testl(exponent, exponent);
   __ j(greater, &done);