Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Unified Diff: src/arm/macro-assembler-arm.cc

Issue 2313863003: [arm] Improve Float(32|64)(Max|Min). (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/compiler/arm/code-generator-arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/macro-assembler-arm.cc
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 496d9bd69261f266eeae53d86aa90834fb24bfad..2e9356967c6e10ce9af35557bba74f7985e78cf2 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -250,15 +250,17 @@ void MacroAssembler::Move(Register dst, Register src, Condition cond) {
}
}
-void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src) {
+void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src,
+ Condition cond) {
if (!dst.is(src)) {
- vmov(dst, src);
+ vmov(dst, src, cond);
}
}
-void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) {
+void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src,
+ Condition cond) {
if (!dst.is(src)) {
- vmov(dst, src);
+ vmov(dst, src, cond);
}
}
@@ -3428,6 +3430,144 @@ void MacroAssembler::RestoreFPRegs(Register location, Register scratch) {
add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
}
+template <typename T>
+void MacroAssembler::FloatMaxHelper(T result, T left, T right,
+ Label* out_of_line) {
+ // This trivial case is caught sooner, so that the out-of-line code can be
+ // completely avoided.
+ DCHECK(!left.is(right));
+
+ if (CpuFeatures::IsSupported(ARMv8)) {
+ CpuFeatureScope scope(this, ARMv8);
+ VFPCompareAndSetFlags(left, right);
+ b(vs, out_of_line);
+ vmaxnm(result, left, right);
+ } else {
+ Label done;
+ VFPCompareAndSetFlags(left, right);
+ b(vs, out_of_line);
+ // Avoid a conditional instruction if the result register is unique.
+ bool aliased_result_reg = result.is(left) || result.is(right);
+ Move(result, right, aliased_result_reg ? mi : al);
+ Move(result, left, gt);
+ b(ne, &done);
+ // Left and right are equal, but check for +/-0.
+ VFPCompareAndSetFlags(left, 0.0);
+ b(eq, out_of_line);
+ // The arguments are equal and not zero, so it doesn't matter which input we
+ // pick. We have already moved one input into the result (if it didn't
+ // already alias) so there's nothing more to do.
+ bind(&done);
+ }
+}
+
+template <typename T>
+void MacroAssembler::FloatMaxOutOfLineHelper(T result, T left, T right) {
+ DCHECK(!left.is(right));
+
+ // ARMv8: At least one of left and right is a NaN.
+ // Anything else: At least one of left and right is a NaN, or both left and
+ // right are zeroes with unknown sign.
+
+ // If left and right are +/-0, select the one with the most positive sign.
+ // If left or right are NaN, vadd propagates the appropriate one.
+ vadd(result, left, right);
+}
+
+template <typename T>
+void MacroAssembler::FloatMinHelper(T result, T left, T right,
+ Label* out_of_line) {
+ // This trivial case is caught sooner, so that the out-of-line code can be
+ // completely avoided.
+ DCHECK(!left.is(right));
+
+ if (CpuFeatures::IsSupported(ARMv8)) {
+ CpuFeatureScope scope(this, ARMv8);
+ VFPCompareAndSetFlags(left, right);
+ b(vs, out_of_line);
+ vminnm(result, left, right);
+ } else {
+ Label done;
+ VFPCompareAndSetFlags(left, right);
+ b(vs, out_of_line);
+ // Avoid a conditional instruction if the result register is unique.
+ bool aliased_result_reg = result.is(left) || result.is(right);
+ Move(result, left, aliased_result_reg ? mi : al);
+ Move(result, right, gt);
+ b(ne, &done);
+ // Left and right are equal, but check for +/-0.
+ VFPCompareAndSetFlags(left, 0.0);
+ // If the arguments are equal and not zero, it doesn't matter which input we
+ // pick. We have already moved one input into the result (if it didn't
+ // already alias) so there's nothing more to do.
+ b(ne, &done);
+ // At this point, both left and right are either 0 or -0.
+ // We could use a single 'vorr' instruction here if we had NEON support.
+ // The algorithm used is -((-L) + (-R)), which is most efficiently expressed
+ // as -((-L) - R).
+ if (left.is(result)) {
+ DCHECK(!right.is(result));
+ vneg(result, left);
+ vsub(result, result, right);
+ vneg(result, result);
+ } else {
+ DCHECK(!left.is(result));
+ vneg(result, right);
+ vsub(result, result, left);
+ vneg(result, result);
+ }
+ bind(&done);
+ }
+}
+
+template <typename T>
+void MacroAssembler::FloatMinOutOfLineHelper(T result, T left, T right) {
+ DCHECK(!left.is(right));
+
+ // At least one of left and right is a NaN. Use vadd to propagate the NaN
+ // appropriately. +/-0 is handled inline.
+ vadd(result, left, right);
+}
+
+void MacroAssembler::FloatMax(SwVfpRegister result, SwVfpRegister left,
+ SwVfpRegister right, Label* out_of_line) {
+ FloatMaxHelper(result, left, right, out_of_line);
+}
+
+void MacroAssembler::FloatMin(SwVfpRegister result, SwVfpRegister left,
+ SwVfpRegister right, Label* out_of_line) {
+ FloatMinHelper(result, left, right, out_of_line);
+}
+
+void MacroAssembler::FloatMax(DwVfpRegister result, DwVfpRegister left,
+ DwVfpRegister right, Label* out_of_line) {
+ FloatMaxHelper(result, left, right, out_of_line);
+}
+
+void MacroAssembler::FloatMin(DwVfpRegister result, DwVfpRegister left,
+ DwVfpRegister right, Label* out_of_line) {
+ FloatMinHelper(result, left, right, out_of_line);
+}
+
+void MacroAssembler::FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left,
+ SwVfpRegister right) {
+ FloatMaxOutOfLineHelper(result, left, right);
+}
+
+void MacroAssembler::FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left,
+ SwVfpRegister right) {
+ FloatMinOutOfLineHelper(result, left, right);
+}
+
+void MacroAssembler::FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left,
+ DwVfpRegister right) {
+ FloatMaxOutOfLineHelper(result, left, right);
+}
+
+void MacroAssembler::FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left,
+ DwVfpRegister right) {
+ FloatMinOutOfLineHelper(result, left, right);
+}
void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
Register first, Register second, Register scratch1, Register scratch2,
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/compiler/arm/code-generator-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698