[llvm] [PowerPC] Fix shuffle combine with undef elements (PR #77787)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 12 01:02:10 PST 2024


https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/77787

>From 296ed0bbb6972d5f2480d9f207b56249a6e5ea39 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 11 Jan 2024 15:36:40 +0100
Subject: [PATCH 1/3] [PowerPC] Fix shuffle combine with undef elements

This custom DAG combine works on a shuffle where one source vector
is a zero splat, which means we can adjust the shuffle indices to
refer to any element of the splat -- as long as we stay in the same
vector.

In the case where an undef (-1) index into the non-splat vector was
used, we ended up adjusting the splat index to -1+NumElements,
which points into the wrong vector.

Fix this by not adjusting indices where the other one is undef.
There are four cases this theoretically affects, but in practice
I only mangaged to demonstrate a miscompile with one of them.
I think two of theses are effectively dead due to the operand
canonicalization at the start of the transform.

Fixes https://github.com/llvm/llvm-project/issues/77748.
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 8 ++++----
 llvm/test/CodeGen/PowerPC/pr77748.ll        | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 4e164fda1d8dd8..743f6493f02215 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15428,7 +15428,7 @@ SDValue PPCTargetLowering::combineVectorShuffle(ShuffleVectorSDNode *SVN,
     // vector_shuffle<0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23> t1, <zero>
     if (Mask[0] < NumElts)
       for (int i = 1, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0)
+        if (ShuffV[i] < 0 || ShuffV[i - 1] < 0)
           continue;
         ShuffV[i] = (ShuffV[i - 1] + NumElts);
       }
@@ -15436,7 +15436,7 @@ SDValue PPCTargetLowering::combineVectorShuffle(ShuffleVectorSDNode *SVN,
     // vector_shuffle<16,0,17,1,18,2,19,3,20,4,21,5,22,6,23,7> t1, <zero>
     else
       for (int i = 0, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0)
+        if (ShuffV[i] < 0 || ShuffV[i + 1] < 0)
           continue;
         ShuffV[i] = (ShuffV[i + 1] + NumElts);
       }
@@ -15445,7 +15445,7 @@ SDValue PPCTargetLowering::combineVectorShuffle(ShuffleVectorSDNode *SVN,
     // vector_shuffle<0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23> <zero>, t1
     if (Mask[0] < NumElts)
       for (int i = 0, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0)
+        if (ShuffV[i] < 0 || ShuffV[i + 1] < 0)
           continue;
         ShuffV[i] = ShuffV[i + 1] - NumElts;
       }
@@ -15453,7 +15453,7 @@ SDValue PPCTargetLowering::combineVectorShuffle(ShuffleVectorSDNode *SVN,
     // vector_shuffle<16,0,17,1,18,2,19,3,20,4,21,5,22,6,23,7> <zero>, t1
     else
       for (int i = 1, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0)
+        if (ShuffV[i] < 0 || ShuffV[i - 1] < 0)
           continue;
         ShuffV[i] = ShuffV[i - 1] - NumElts;
       }
diff --git a/llvm/test/CodeGen/PowerPC/pr77748.ll b/llvm/test/CodeGen/PowerPC/pr77748.ll
index 661ea29445a891..7ec721def0093b 100644
--- a/llvm/test/CodeGen/PowerPC/pr77748.ll
+++ b/llvm/test/CodeGen/PowerPC/pr77748.ll
@@ -14,13 +14,13 @@
 ; LE-NEXT: 	.byte	28
 ; LE-NEXT: 	.byte	12
 ; LE-NEXT: 	.byte	31
-; LE-NEXT: 	.byte	16
+; LE-NEXT: 	.byte	15
 ; LE-NEXT: 	.byte	31
-; LE-NEXT: 	.byte	16
+; LE-NEXT: 	.byte	15
 ; LE-NEXT: 	.byte	31
-; LE-NEXT: 	.byte	16
+; LE-NEXT: 	.byte	15
 ; LE-NEXT: 	.byte	31
-; LE-NEXT: 	.byte	16
+; LE-NEXT: 	.byte	15
 
 ; BE-LABEL: .LCPI0_0:
 ; BE-NEXT: 	.byte	0

>From 58fad1ee53059440dfb3e8a201686026792ddec6 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 12 Jan 2024 10:01:02 +0100
Subject: [PATCH 2/3] Normalize which element is picked for undef

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 743f6493f02215..aec58d1c0dcb9f 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15428,34 +15428,38 @@ SDValue PPCTargetLowering::combineVectorShuffle(ShuffleVectorSDNode *SVN,
     // vector_shuffle<0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23> t1, <zero>
     if (Mask[0] < NumElts)
       for (int i = 1, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0 || ShuffV[i - 1] < 0)
+        if (ShuffV[i] < 0)
           continue;
-        ShuffV[i] = (ShuffV[i - 1] + NumElts);
+        // If element from non-splat is undef, pick first element from splat.
+        ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
       }
     // Example (odd elements from first vector):
     // vector_shuffle<16,0,17,1,18,2,19,3,20,4,21,5,22,6,23,7> t1, <zero>
     else
       for (int i = 0, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0 || ShuffV[i + 1] < 0)
+        if (ShuffV[i] < 0)
           continue;
-        ShuffV[i] = (ShuffV[i + 1] + NumElts);
+        // If element from non-splat is undef, pick first element from splat.
+        ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
       }
   } else {
     // Example (even elements from first vector):
     // vector_shuffle<0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23> <zero>, t1
     if (Mask[0] < NumElts)
       for (int i = 0, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0 || ShuffV[i + 1] < 0)
+        if (ShuffV[i] < 0)
           continue;
-        ShuffV[i] = ShuffV[i + 1] - NumElts;
+        // If element from non-splat is undef, pick first element from splat.
+        ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
       }
     // Example (odd elements from first vector):
     // vector_shuffle<16,0,17,1,18,2,19,3,20,4,21,5,22,6,23,7> <zero>, t1
     else
       for (int i = 1, e = Mask.size(); i < e; i += 2) {
-        if (ShuffV[i] < 0 || ShuffV[i - 1] < 0)
+        if (ShuffV[i] < 0)
           continue;
-        ShuffV[i] = ShuffV[i - 1] - NumElts;
+        // If element from non-splat is undef, pick first element from splat.
+        ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
       }
   }
 

>From 8ecb03824e0644607fd8f114ed18092678b0cb0c Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 12 Jan 2024 10:01:25 +0100
Subject: [PATCH 3/3] Drop TODO

---
 llvm/test/CodeGen/PowerPC/pr77748.ll | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/test/CodeGen/PowerPC/pr77748.ll b/llvm/test/CodeGen/PowerPC/pr77748.ll
index 7ec721def0093b..d4928f95002c1f 100644
--- a/llvm/test/CodeGen/PowerPC/pr77748.ll
+++ b/llvm/test/CodeGen/PowerPC/pr77748.ll
@@ -2,8 +2,6 @@
 ; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mattr=+altivec -ppc-asm-full-reg-names < %s | FileCheck %s --check-prefixes=LE
 ; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mattr=+altivec,+direct-move -ppc-asm-full-reg-names < %s | FileCheck %s --check-prefixes=BE
 
-; FIXME: This is miscompile.
-
 ; LE-LABEL: .LCPI0_0:
 ; LE-NEXT: 	.byte	31
 ; LE-NEXT: 	.byte	15



More information about the llvm-commits mailing list