Log Message
Speed up TransformationMatrix::multiply() on modern ARM https://bugs.webkit.org/show_bug.cgi?id=101084
Reviewed by Gavin Barraclough. Source/WebCore: The main improvements are: -Store the full source matrix in the registers d16 to d31. This way we avoid going back and forth to memory to use the operands. Since the full matrix is in register, we can also directly modify the memory of m_matrix, we no longer need the temporary matrix memcopied at the end. -Use of LoadMultiple and StoreMultiple to load-store the matrix parameters. -Use Multiply-Accumulate instead of VMUL followed by VADD. This half the number of instruction. -On regular ARMv7, using a loop to reuse the same code for each row also improve the performance. Depending on the hardware, the new code takes 20% to 42% less time than the basic implementation. * platform/graphics/transforms/TransformationMatrix.cpp: (WebCore::TransformationMatrix::multiply): * platform/graphics/transforms/TransformationMatrix.h: (TransformationMatrix): Source/WTF: * wtf/Platform.h: Add CPU(ARM_VFP) for detecting VFP availability. Add CPU(APPLE_ARMV7S) for the Apple ARMv7S architecture.
Modified Paths
Diff
Modified: trunk/Source/WTF/ChangeLog (133652 => 133653)
--- trunk/Source/WTF/ChangeLog 2012-11-06 20:08:19 UTC (rev 133652)
+++ trunk/Source/WTF/ChangeLog 2012-11-06 20:10:46 UTC (rev 133653)
@@ -1,3 +1,14 @@
+2012-11-06 Benjamin Poulain <[email protected]>
+
+ Speed up TransformationMatrix::multiply() on modern ARM
+ https://bugs.webkit.org/show_bug.cgi?id=101084
+
+ Reviewed by Gavin Barraclough.
+
+ * wtf/Platform.h:
+ Add CPU(ARM_VFP) for detecting VFP availability.
+ Add CPU(APPLE_ARMV7S) for the Apple ARMv7S architecture.
+
2012-11-06 Laszlo Gombos <[email protected]>
Refactor setting TEXTURE_MAPPER_GL
Modified: trunk/Source/WTF/wtf/Platform.h (133652 => 133653)
--- trunk/Source/WTF/wtf/Platform.h 2012-11-06 20:08:19 UTC (rev 133652)
+++ trunk/Source/WTF/wtf/Platform.h 2012-11-06 20:10:46 UTC (rev 133653)
@@ -302,6 +302,14 @@
#define HAVE_ARM_NEON_INTRINSICS 1
#endif
+#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
+#define WTF_CPU_ARM_VFP 1
+#endif
+
+#if defined(__ARM_ARCH_7S__)
+#define WTF_CPU_APPLE_ARMV7S 1
+#endif
+
#endif /* ARM */
#if CPU(ARM) || CPU(MIPS) || CPU(SH4) || CPU(SPARC)
Modified: trunk/Source/WebCore/ChangeLog (133652 => 133653)
--- trunk/Source/WebCore/ChangeLog 2012-11-06 20:08:19 UTC (rev 133652)
+++ trunk/Source/WebCore/ChangeLog 2012-11-06 20:10:46 UTC (rev 133653)
@@ -1,3 +1,26 @@
+2012-11-06 Benjamin Poulain <[email protected]>
+
+ Speed up TransformationMatrix::multiply() on modern ARM
+ https://bugs.webkit.org/show_bug.cgi?id=101084
+
+ Reviewed by Gavin Barraclough.
+
+ The main improvements are:
+ -Store the full source matrix in the registers d16 to d31. This way we avoid going
+ back and forth to memory to use the operands.
+ Since the full matrix is in register, we can also directly modify the memory of m_matrix,
+ we no longer need the temporary matrix memcopied at the end.
+ -Use of LoadMultiple and StoreMultiple to load-store the matrix parameters.
+ -Use Multiply-Accumulate instead of VMUL followed by VADD. This half the number of instruction.
+ -On regular ARMv7, using a loop to reuse the same code for each row also improve the performance.
+
+ Depending on the hardware, the new code takes 20% to 42% less time than the basic implementation.
+
+ * platform/graphics/transforms/TransformationMatrix.cpp:
+ (WebCore::TransformationMatrix::multiply):
+ * platform/graphics/transforms/TransformationMatrix.h:
+ (TransformationMatrix):
+
2012-11-06 Sheriff Bot <[email protected]>
Unreviewed, rolling out r133529 and r133562.
Modified: trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp (133652 => 133653)
--- trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp 2012-11-06 20:08:19 UTC (rev 133652)
+++ trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp 2012-11-06 20:10:46 UTC (rev 133653)
@@ -971,6 +971,149 @@
//
TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat)
{
+#if CPU(APPLE_ARMV7S)
+ double* leftMatrix = &(m_matrix[0][0]);
+ const double* rightMatrix = &(mat.m_matrix[0][0]);
+ asm volatile (// First row of leftMatrix.
+ "mov r3, %[leftMatrix]\n\t"
+ "vld1.64 { d16-d19 }, [%[leftMatrix], :128]!\n\t"
+ "vld1.64 { d0-d3}, [%[rightMatrix], :128]!\n\t"
+ "vmul.f64 d4, d0, d16\n\t"
+ "vld1.64 { d20-d23 }, [%[leftMatrix], :128]!\n\t"
+ "vmla.f64 d4, d1, d20\n\t"
+ "vld1.64 { d24-d27 }, [%[leftMatrix], :128]!\n\t"
+ "vmla.f64 d4, d2, d24\n\t"
+ "vld1.64 { d28-d31 }, [%[leftMatrix], :128]!\n\t"
+ "vmla.f64 d4, d3, d28\n\t"
+
+ "vmul.f64 d5, d0, d17\n\t"
+ "vmla.f64 d5, d1, d21\n\t"
+ "vmla.f64 d5, d2, d25\n\t"
+ "vmla.f64 d5, d3, d29\n\t"
+
+ "vmul.f64 d6, d0, d18\n\t"
+ "vmla.f64 d6, d1, d22\n\t"
+ "vmla.f64 d6, d2, d26\n\t"
+ "vmla.f64 d6, d3, d30\n\t"
+
+ "vmul.f64 d7, d0, d19\n\t"
+ "vmla.f64 d7, d1, d23\n\t"
+ "vmla.f64 d7, d2, d27\n\t"
+ "vmla.f64 d7, d3, d31\n\t"
+ "vld1.64 { d0-d3}, [%[rightMatrix], :128]!\n\t"
+ "vst1.64 { d4-d7 }, [r3, :128]!\n\t"
+
+ // Second row of leftMatrix.
+ "vmul.f64 d4, d0, d16\n\t"
+ "vmla.f64 d4, d1, d20\n\t"
+ "vmla.f64 d4, d2, d24\n\t"
+ "vmla.f64 d4, d3, d28\n\t"
+
+ "vmul.f64 d5, d0, d17\n\t"
+ "vmla.f64 d5, d1, d21\n\t"
+ "vmla.f64 d5, d2, d25\n\t"
+ "vmla.f64 d5, d3, d29\n\t"
+
+ "vmul.f64 d6, d0, d18\n\t"
+ "vmla.f64 d6, d1, d22\n\t"
+ "vmla.f64 d6, d2, d26\n\t"
+ "vmla.f64 d6, d3, d30\n\t"
+
+ "vmul.f64 d7, d0, d19\n\t"
+ "vmla.f64 d7, d1, d23\n\t"
+ "vmla.f64 d7, d2, d27\n\t"
+ "vmla.f64 d7, d3, d31\n\t"
+ "vld1.64 { d0-d3}, [%[rightMatrix], :128]!\n\t"
+ "vst1.64 { d4-d7 }, [r3, :128]!\n\t"
+
+ // Third row of leftMatrix.
+ "vmul.f64 d4, d0, d16\n\t"
+ "vmla.f64 d4, d1, d20\n\t"
+ "vmla.f64 d4, d2, d24\n\t"
+ "vmla.f64 d4, d3, d28\n\t"
+
+ "vmul.f64 d5, d0, d17\n\t"
+ "vmla.f64 d5, d1, d21\n\t"
+ "vmla.f64 d5, d2, d25\n\t"
+ "vmla.f64 d5, d3, d29\n\t"
+
+ "vmul.f64 d6, d0, d18\n\t"
+ "vmla.f64 d6, d1, d22\n\t"
+ "vmla.f64 d6, d2, d26\n\t"
+ "vmla.f64 d6, d3, d30\n\t"
+
+ "vmul.f64 d7, d0, d19\n\t"
+ "vmla.f64 d7, d1, d23\n\t"
+ "vmla.f64 d7, d2, d27\n\t"
+ "vmla.f64 d7, d3, d31\n\t"
+ "vld1.64 { d0-d3}, [%[rightMatrix], :128]\n\t"
+ "vst1.64 { d4-d7 }, [r3, :128]!\n\t"
+
+ // Fourth and last row of leftMatrix.
+ "vmul.f64 d4, d0, d16\n\t"
+ "vmla.f64 d4, d1, d20\n\t"
+ "vmla.f64 d4, d2, d24\n\t"
+ "vmla.f64 d4, d3, d28\n\t"
+
+ "vmul.f64 d5, d0, d17\n\t"
+ "vmla.f64 d5, d1, d21\n\t"
+ "vmla.f64 d5, d2, d25\n\t"
+ "vmla.f64 d5, d3, d29\n\t"
+
+ "vmul.f64 d6, d0, d18\n\t"
+ "vmla.f64 d6, d1, d22\n\t"
+ "vmla.f64 d6, d2, d26\n\t"
+ "vmla.f64 d6, d3, d30\n\t"
+
+ "vmul.f64 d7, d0, d19\n\t"
+ "vmla.f64 d7, d1, d23\n\t"
+ "vmla.f64 d7, d2, d27\n\t"
+ "vmla.f64 d7, d3, d31\n\t"
+ "vst1.64 { d4-d7 }, [r3, :128]\n\t"
+ : [leftMatrix]"+r"(leftMatrix), [rightMatrix]"+r"(rightMatrix)
+ :
+ : "memory", "r3", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31");
+#elif CPU(ARM_VFP) && PLATFORM(IOS)
+
+#define MATRIX_MULTIPLY_ONE_LINE \
+ "vldmia.64 %[rightMatrix]!, { d0-d3}\n\t" \
+ "vmul.f64 d4, d0, d16\n\t" \
+ "vmla.f64 d4, d1, d20\n\t" \
+ "vmla.f64 d4, d2, d24\n\t" \
+ "vmla.f64 d4, d3, d28\n\t" \
+ \
+ "vmul.f64 d5, d0, d17\n\t" \
+ "vmla.f64 d5, d1, d21\n\t" \
+ "vmla.f64 d5, d2, d25\n\t" \
+ "vmla.f64 d5, d3, d29\n\t" \
+ \
+ "vmul.f64 d6, d0, d18\n\t" \
+ "vmla.f64 d6, d1, d22\n\t" \
+ "vmla.f64 d6, d2, d26\n\t" \
+ "vmla.f64 d6, d3, d30\n\t" \
+ \
+ "vmul.f64 d7, d0, d19\n\t" \
+ "vmla.f64 d7, d1, d23\n\t" \
+ "vmla.f64 d7, d2, d27\n\t" \
+ "vmla.f64 d7, d3, d31\n\t" \
+ "vstmia.64 %[leftMatrix]!, { d4-d7 }\n\t"
+
+ double* leftMatrix = &(m_matrix[0][0]);
+ const double* rightMatrix = &(mat.m_matrix[0][0]);
+ // We load the full m_matrix at once in d16-d31.
+ asm volatile("vldmia.64 %[leftMatrix], { d16-d31 }\n\t"
+ :
+ : [leftMatrix]"r"(leftMatrix)
+ : "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31");
+ for (unsigned i = 0; i < 4; ++i) {
+ asm volatile(MATRIX_MULTIPLY_ONE_LINE
+ : [leftMatrix]"+r"(leftMatrix), [rightMatrix]"+r"(rightMatrix)
+ :
+ : "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7");
+ }
+#undef MATRIX_MULTIPLY_ONE_LINE
+
+#else
Matrix4 tmp;
tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0]
@@ -1010,6 +1153,7 @@
+ mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]);
setMatrix(tmp);
+#endif
return *this;
}
Modified: trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h (133652 => 133653)
--- trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h 2012-11-06 20:08:19 UTC (rev 133652)
+++ trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h 2012-11-06 20:10:46 UTC (rev 133653)
@@ -72,7 +72,11 @@
class TransformationMatrix {
WTF_MAKE_FAST_ALLOCATED;
public:
+#if CPU(APPLE_ARMV7S)
+ typedef double Matrix4[4][4] __attribute__((aligned (16)));
+#else
typedef double Matrix4[4][4];
+#endif
TransformationMatrix() { makeIdentity(); }
TransformationMatrix(const AffineTransform& t);
_______________________________________________ webkit-changes mailing list [email protected] http://lists.webkit.org/mailman/listinfo/webkit-changes
