OSDN Git Service

[x86] avoid vector load narrowing with extracted store uses (PR42305)
authorSanjay Patel <spatel@rotateright.com>
Wed, 19 Jun 2019 18:13:47 +0000 (18:13 +0000)
committerSanjay Patel <spatel@rotateright.com>
Wed, 19 Jun 2019 18:13:47 +0000 (18:13 +0000)
This is an exception to the rule that we should prefer xmm ops to ymm ops.
As shown in PR42305:
https://bugs.llvm.org/show_bug.cgi?id=42305
...the store folding opportunity with vextractf128 may result in better
perf by reducing the instruction count.

Differential Revision: https://reviews.llvm.org/D63517

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

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/sandybridge-loads.ll
test/CodeGen/X86/widen_load-3.ll

index 2beec98..e41dc8a 100644 (file)
@@ -4810,6 +4810,26 @@ bool X86TargetLowering::shouldReduceLoadWidth(SDNode *Load,
   if (BasePtr.getOpcode() == X86ISD::WrapperRIP)
     if (const auto *GA = dyn_cast<GlobalAddressSDNode>(BasePtr.getOperand(0)))
       return GA->getTargetFlags() != X86II::MO_GOTTPOFF;
+
+  // If this is an (1) AVX vector load with (2) multiple uses and (3) all of
+  // those uses are extracted directly into a store, then the extract + store
+  // can be store-folded. Therefore, it's probably not worth splitting the load.
+  EVT VT = Load->getValueType(0);
+  if ((VT.is256BitVector() || VT.is512BitVector()) && !Load->hasOneUse()) {
+    for (auto UI = Load->use_begin(), UE = Load->use_end(); UI != UE; ++UI) {
+      // Skip uses of the chain value. Result 0 of the node is the load value.
+      if (UI.getUse().getResNo() != 0)
+        continue;
+
+      // If this use is not an extract + store, it's probably worth splitting.
+      if (UI->getOpcode() != ISD::EXTRACT_SUBVECTOR || !UI->hasOneUse() ||
+          UI->use_begin()->getOpcode() != ISD::STORE)
+        return true;
+    }
+    // All non-chain uses are extract + store.
+    return false;
+  }
+
   return true;
 }
 
index 50766a2..60043ba 100644 (file)
@@ -30,10 +30,9 @@ define void @widestores(<8 x float>* %a, <8 x float>* %b, <8 x float>* %c) nounw
 ; CHECK-LABEL: widestores:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    vmovaps (%rdi), %ymm0
-; CHECK-NEXT:    vmovaps (%rsi), %xmm1
-; CHECK-NEXT:    vmovaps 16(%rsi), %xmm2
+; CHECK-NEXT:    vmovaps (%rsi), %ymm1
 ; CHECK-NEXT:    vmovaps %ymm0, (%rsi)
-; CHECK-NEXT:    vmovaps %xmm2, 16(%rdi)
+; CHECK-NEXT:    vextractf128 $1, %ymm1, 16(%rdi)
 ; CHECK-NEXT:    vmovaps %xmm1, (%rdi)
 ; CHECK-NEXT:    vzeroupper
 ; CHECK-NEXT:    retq
index 316f785..f456c48 100644 (file)
@@ -146,10 +146,10 @@ define void @load_split(<8 x float>* %ld, <4 x float>* %st1, <4 x float>* %st2)
 ; X86-AVX-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-AVX-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-AVX-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-AVX-NEXT:    vmovups (%edx), %xmm0
-; X86-AVX-NEXT:    vmovups 16(%edx), %xmm1
+; X86-AVX-NEXT:    vmovups (%edx), %ymm0
 ; X86-AVX-NEXT:    vmovups %xmm0, (%ecx)
-; X86-AVX-NEXT:    vmovups %xmm1, (%eax)
+; X86-AVX-NEXT:    vextractf128 $1, %ymm0, (%eax)
+; X86-AVX-NEXT:    vzeroupper
 ; X86-AVX-NEXT:    retl
 ;
 ; X64-SSE-LABEL: load_split:
@@ -162,10 +162,10 @@ define void @load_split(<8 x float>* %ld, <4 x float>* %st1, <4 x float>* %st2)
 ;
 ; X64-AVX-LABEL: load_split:
 ; X64-AVX:       # %bb.0:
-; X64-AVX-NEXT:    vmovups (%rdi), %xmm0
-; X64-AVX-NEXT:    vmovups 16(%rdi), %xmm1
+; X64-AVX-NEXT:    vmovups (%rdi), %ymm0
 ; X64-AVX-NEXT:    vmovups %xmm0, (%rsi)
-; X64-AVX-NEXT:    vmovups %xmm1, (%rdx)
+; X64-AVX-NEXT:    vextractf128 $1, %ymm0, (%rdx)
+; X64-AVX-NEXT:    vzeroupper
 ; X64-AVX-NEXT:    retq
   %t256 = load <8 x float>, <8 x float>* %ld, align 1
   %b128 = shufflevector <8 x float> %t256, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -178,39 +178,35 @@ define void @load_split(<8 x float>* %ld, <4 x float>* %st1, <4 x float>* %st2)
 define void @load_split_more(float* %src, i32* %idx, float* %dst) nounwind {
 ; X86-SSE-LABEL: load_split_more:
 ; X86-SSE:       # %bb.0:
-; X86-SSE-NEXT:    pushl %esi
 ; X86-SSE-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-SSE-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-SSE-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-SSE-NEXT:    movl (%edx), %esi
-; X86-SSE-NEXT:    movups (%ecx), %xmm0
-; X86-SSE-NEXT:    movups 16(%ecx), %xmm1
-; X86-SSE-NEXT:    movups %xmm0, (%eax,%esi,4)
-; X86-SSE-NEXT:    movl 4(%edx), %ecx
+; X86-SSE-NEXT:    movups (%edx), %xmm0
+; X86-SSE-NEXT:    movups 16(%edx), %xmm1
+; X86-SSE-NEXT:    movl (%ecx), %edx
+; X86-SSE-NEXT:    movups %xmm0, (%eax,%edx,4)
+; X86-SSE-NEXT:    movl 4(%ecx), %ecx
 ; X86-SSE-NEXT:    movups %xmm1, (%eax,%ecx,4)
-; X86-SSE-NEXT:    popl %esi
 ; X86-SSE-NEXT:    retl
 ;
 ; X86-AVX-LABEL: load_split_more:
 ; X86-AVX:       # %bb.0:
-; X86-AVX-NEXT:    pushl %esi
 ; X86-AVX-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-AVX-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-AVX-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-AVX-NEXT:    movl (%edx), %esi
-; X86-AVX-NEXT:    vmovups (%ecx), %xmm0
-; X86-AVX-NEXT:    vmovups 16(%ecx), %xmm1
-; X86-AVX-NEXT:    vmovups %xmm0, (%eax,%esi,4)
-; X86-AVX-NEXT:    movl 4(%edx), %ecx
-; X86-AVX-NEXT:    vmovups %xmm1, (%eax,%ecx,4)
-; X86-AVX-NEXT:    popl %esi
+; X86-AVX-NEXT:    vmovups (%edx), %ymm0
+; X86-AVX-NEXT:    movl (%ecx), %edx
+; X86-AVX-NEXT:    vmovups %xmm0, (%eax,%edx,4)
+; X86-AVX-NEXT:    movl 4(%ecx), %ecx
+; X86-AVX-NEXT:    vextractf128 $1, %ymm0, (%eax,%ecx,4)
+; X86-AVX-NEXT:    vzeroupper
 ; X86-AVX-NEXT:    retl
 ;
 ; X64-SSE-LABEL: load_split_more:
 ; X64-SSE:       # %bb.0:
-; X64-SSE-NEXT:    movslq (%rsi), %rax
 ; X64-SSE-NEXT:    movups (%rdi), %xmm0
 ; X64-SSE-NEXT:    movups 16(%rdi), %xmm1
+; X64-SSE-NEXT:    movslq (%rsi), %rax
 ; X64-SSE-NEXT:    movups %xmm0, (%rdx,%rax,4)
 ; X64-SSE-NEXT:    movslq 4(%rsi), %rax
 ; X64-SSE-NEXT:    movups %xmm1, (%rdx,%rax,4)
@@ -218,12 +214,12 @@ define void @load_split_more(float* %src, i32* %idx, float* %dst) nounwind {
 ;
 ; X64-AVX-LABEL: load_split_more:
 ; X64-AVX:       # %bb.0:
+; X64-AVX-NEXT:    vmovups (%rdi), %ymm0
 ; X64-AVX-NEXT:    movslq (%rsi), %rax
-; X64-AVX-NEXT:    vmovups (%rdi), %xmm0
-; X64-AVX-NEXT:    vmovups 16(%rdi), %xmm1
 ; X64-AVX-NEXT:    vmovups %xmm0, (%rdx,%rax,4)
 ; X64-AVX-NEXT:    movslq 4(%rsi), %rax
-; X64-AVX-NEXT:    vmovups %xmm1, (%rdx,%rax,4)
+; X64-AVX-NEXT:    vextractf128 $1, %ymm0, (%rdx,%rax,4)
+; X64-AVX-NEXT:    vzeroupper
 ; X64-AVX-NEXT:    retq
   %v.i = bitcast float* %src to <8 x float>*
   %tmp = load <8 x float>, <8 x float>* %v.i, align 1