Swift: Only build vldm/vstm with q register aligned register lists
authorArnold Schwaighofer <aschwaighofer@apple.com>
Wed, 4 Sep 2013 17:41:16 +0000 (17:41 +0000)
committerArnold Schwaighofer <aschwaighofer@apple.com>
Wed, 4 Sep 2013 17:41:16 +0000 (17:41 +0000)
Unaligned vldm/vstm need more uops and therefore are slower in general on swift.

radar://14522102

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189961 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMLoadStoreOptimizer.cpp
test/CodeGen/ARM/swift-vldm.ll [new file with mode: 0644]

index 1803a8a588763c5a4fdd03ca899a460e1a3ad332..237adb9b22ee99adb221c462572e18d523f73659 100644 (file)
@@ -489,7 +489,10 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
     if (Reg != ARM::SP &&
         NewOffset == Offset + (int)Size &&
         ((isNotVFP && RegNum > PRegNum) ||
-         ((Count < Limit) && RegNum == PRegNum+1))) {
+         ((Count < Limit) && RegNum == PRegNum+1)) &&
+        // On Swift we don't want vldm/vstm to start with a odd register num
+        // because Q register unaligned vldm/vstm need more uops.
+        (!STI->isSwift() || isNotVFP || Count != 1 || !(PRegNum & 0x1))) {
       Offset += Size;
       PRegNum = RegNum;
       ++Count;
diff --git a/test/CodeGen/ARM/swift-vldm.ll b/test/CodeGen/ARM/swift-vldm.ll
new file mode 100644 (file)
index 0000000..6d76ee4
--- /dev/null
@@ -0,0 +1,28 @@
+; RUN: llc < %s -mcpu=swift -mtriple=armv7s-apple-ios | FileCheck %s
+
+; vldm with registers not aligned with q registers need more micro-ops so that
+; so that there usage becomes unbeneficial on swift.
+
+; CHECK-LABEL: test_vldm
+; CHECK: vldmia  r1, {d18, d19, d20}
+; CHECK-NOT: vldmia  r1, {d17, d18, d19, d20}
+
+define double @test_vldm(double %a, double %b, double* nocapture %x) {
+entry:
+  %mul73 = fmul double %a, %b
+  %addr1 = getelementptr double * %x, i32 1
+  %addr2 = getelementptr double * %x, i32 2
+  %addr3 = getelementptr double * %x, i32 3
+  %load0 = load double * %x
+  %load1 = load double * %addr1
+  %load2 = load double * %addr2
+  %load3 = load double * %addr3
+  %sub = fsub double %mul73, %load1
+  %mul = fmul double %mul73, %load0
+  %add = fadd double %mul73, %load2
+  %div = fdiv double %mul73, %load3
+  %red = fadd double %sub, %mul
+  %red2 = fadd double %div, %add
+  %red3 = fsub double %red, %red2
+  ret double %red3
+}