From da757a1b062c24e1011c5aadf31fe2f1cde59c97 Mon Sep 17 00:00:00 2001
From: Alan Hayward <a74nh@users.noreply.github.com>
Date: Thu, 8 Aug 2024 15:41:47 +0100
Subject: [PATCH] ARM64-SVE: Avoid containing non-embedded conditional select
 #105719 (#105812)

---
 eng/pipelines/coreclr/jitstress-isas-sve.yml  |  9 ++--
 src/coreclr/jit/lowerarmarch.cpp              | 46 ++++++++++++++++++-
 .../JitBlue/Runtime_105719/Runtime_105719.cs  | 31 +++++++++++++
 .../Runtime_105719/Runtime_105719.csproj      |  9 ++++
 4 files changed, 90 insertions(+), 5 deletions(-)
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.cs
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.csproj

diff --git a/eng/pipelines/coreclr/jitstress-isas-sve.yml b/eng/pipelines/coreclr/jitstress-isas-sve.yml
index ec27ba55c3ed0c..c5aca49e62322f 100644
--- a/eng/pipelines/coreclr/jitstress-isas-sve.yml
+++ b/eng/pipelines/coreclr/jitstress-isas-sve.yml
@@ -8,12 +8,15 @@ pr:
     - main
   paths:
     include:
+    - src/coreclr/jit/codegenarmarch.cpp
+    - src/coreclr/jit/emitarm64sve.cpp
+    - src/coreclr/jit/emitfmtsarm64sve.h
+    - src/coreclr/jit/hwintrinsicarm64.cpp
     - src/coreclr/jit/hwintrinsiccodegenarm64.cpp
     - src/coreclr/jit/hwintrinsiclistarm64sve.h
-    - src/coreclr/jit/hwintrinsicarm64.cpp
     - src/coreclr/jit/instrsarm64sve.h
-    - src/coreclr/jit/emitarm64sve.cpp
-    - src/coreclr/jit/emitfmtsarm64sve.h
+    - src/coreclr/jit/lowerarmarch.cpp
+    - src/coreclr/jit/lsraarmarch.cpp
     - src/coreclr/jit/lsraarm64.cpp
 
 schedules:
diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp
index 290acc1df639e0..19c790d84eb261 100644
--- a/src/coreclr/jit/lowerarmarch.cpp
+++ b/src/coreclr/jit/lowerarmarch.cpp
@@ -4050,7 +4050,7 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* cndSelNode)
             GenTree* nestedOp2 = nestedCndSel->Op(2);
             GenTree* nestedOp3 = nestedCndSel->Op(3);
 
-            JITDUMP("lowering ConditionalSelect HWIntrinisic (before):\n");
+            JITDUMP("lowering nested ConditionalSelect HWIntrinisic (before):\n");
             DISPTREERANGE(BlockRange(), cndSelNode);
             JITDUMP("\n");
 
@@ -4072,13 +4072,55 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* cndSelNode)
             BlockRange().Remove(nestedOp1);
             BlockRange().Remove(nestedCndSel);
 
-            JITDUMP("lowering ConditionalSelect HWIntrinisic (after):\n");
+            JITDUMP("lowering nested ConditionalSelect HWIntrinisic (after):\n");
             DISPTREERANGE(BlockRange(), cndSelNode);
             JITDUMP("\n");
 
             return cndSelNode;
         }
     }
+    else if (op1->IsMaskAllBitsSet())
+    {
+        // Any case where op2 is not an embedded HWIntrinsic
+        if (!op2->OperIsHWIntrinsic() ||
+            !HWIntrinsicInfo::IsEmbeddedMaskedOperation(op2->AsHWIntrinsic()->GetHWIntrinsicId()))
+        {
+            JITDUMP("lowering ConditionalSelect HWIntrinisic (before):\n");
+            DISPTREERANGE(BlockRange(), cndSelNode);
+            JITDUMP("\n");
+
+            // Transform
+            // CndSel(AllTrue, op2, op3) to
+            // op2
+
+            LIR::Use use;
+            if (BlockRange().TryGetUse(cndSelNode, &use))
+            {
+                use.ReplaceWith(op2);
+            }
+            else
+            {
+                op2->SetUnusedValue();
+            }
+
+            if (op3->IsMaskZero())
+            {
+                BlockRange().Remove(op3);
+            }
+            else
+            {
+                op3->SetUnusedValue();
+            }
+            op1->SetUnusedValue();
+            BlockRange().Remove(cndSelNode);
+
+            JITDUMP("lowering ConditionalSelect HWIntrinisic (after):\n");
+            DISPTREERANGE(BlockRange(), op2);
+            JITDUMP("\n");
+
+            return op2;
+        }
+    }
 
     ContainCheckHWIntrinsic(cndSelNode);
     return cndSelNode->gtNext;
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.cs b/src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.cs
new file mode 100644
index 00000000000000..c8eff043c9bdad
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+using System;
+using System.Runtime.CompilerServices;
+using System.Numerics;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+public class Runtime_105723
+{
+    [Fact]
+    public static void TestEntryPoint()
+    {
+        if (Sve.IsSupported)
+        {
+            var vr3 = Sve.CreateTrueMaskInt32();
+            var vr4 = Vector.Create<int>(1);
+            var vr5 = Vector128.CreateScalar(0).AsVector();
+            Vector<int> vr6 = Sve.ConditionalSelect(vr3, vr4, vr5);
+            Consume(vr6);
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private static void Consume(Vector<int> v)
+    {
+        ;
+    }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.csproj
new file mode 100644
index 00000000000000..bb40d49ed68241
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_105719/Runtime_105719.csproj
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <Optimize>True</Optimize>
+    <NoWarn>$(NoWarn);SYSLIB5003</NoWarn>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>