[llvm] 11850a6 - [WebAssembly] Expand setcc of v2i64

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 31 14:22:36 PDT 2019


Author: Thomas Lively
Date: 2019-10-31T14:22:30-07:00
New Revision: 11850a6305c5778b180243eb06aefe86762dd4ce

URL: https://github.com/llvm/llvm-project/commit/11850a6305c5778b180243eb06aefe86762dd4ce
DIFF: https://github.com/llvm/llvm-project/commit/11850a6305c5778b180243eb06aefe86762dd4ce.diff

LOG: [WebAssembly] Expand setcc of v2i64

Summary:
The SIMD spec does not include i64x2 comparisons, so they need to be
expanded. Using setOperationAction to expand them also causes f64x2
comparisons to be expanded, so setCondCodeAction needs to be used
instead. But since there are no legal condition codes, the legalizer
does not know how to expand the comparisons. We therefore manually
unroll the operation, taking care to fill each lane with -1 or 0
rather than 1 or 0 for consistency with the other vector comparisons.

Reviewers: aheejin

Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

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

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
    llvm/test/CodeGen/WebAssembly/simd-comparisons.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index f06afdbcea9e..2f698711a746 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -189,6 +189,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
         setOperationAction(Op, MVT::v2f64, Expand);
     }
 
+    // Expand operations not supported for i64x2 vectors
+    if (Subtarget->hasUnimplementedSIMD128())
+      for (unsigned CC = 0; CC < ISD::SETCC_INVALID; ++CC)
+        setCondCodeAction(static_cast<ISD::CondCode>(CC), MVT::v2i64, Custom);
+
     // Expand additional SIMD ops that V8 hasn't implemented yet
     if (!Subtarget->hasUnimplementedSIMD128()) {
       setOperationAction(ISD::FSQRT, MVT::v4f32, Expand);
@@ -1011,6 +1016,8 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
     return LowerBUILD_VECTOR(Op, DAG);
   case ISD::VECTOR_SHUFFLE:
     return LowerVECTOR_SHUFFLE(Op, DAG);
+  case ISD::SETCC:
+    return LowerSETCC(Op, DAG);
   case ISD::SHL:
   case ISD::SRA:
   case ISD::SRL:
@@ -1472,6 +1479,29 @@ WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
   return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
 }
 
+SDValue WebAssemblyTargetLowering::LowerSETCC(SDValue Op,
+                                              SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  // The legalizer does not know how to expand the comparison modes of i64x2
+  // vectors because no comparison modes are supported. We could solve this by
+  // expanding all i64x2 SETCC nodes, but that seems to expand f64x2 SETCC nodes
+  // (which return i64x2 results) as well. So instead we manually unroll i64x2
+  // comparisons here.
+  assert(Subtarget->hasUnimplementedSIMD128());
+  assert(Op->getOperand(0)->getSimpleValueType(0) == MVT::v2i64);
+  SmallVector<SDValue, 2> LHS, RHS;
+  DAG.ExtractVectorElements(Op->getOperand(0), LHS);
+  DAG.ExtractVectorElements(Op->getOperand(1), RHS);
+  const SDValue &CC = Op->getOperand(2);
+  auto MakeLane = [&](unsigned I) {
+    return DAG.getNode(ISD::SELECT_CC, DL, MVT::i64, LHS[I], RHS[I],
+                       DAG.getConstant(uint64_t(-1), DL, MVT::i64),
+                       DAG.getConstant(uint64_t(0), DL, MVT::i64), CC);
+  };
+  return DAG.getBuildVector(Op->getValueType(0), DL,
+                            {MakeLane(0), MakeLane(1)});
+}
+
 SDValue
 WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
                                                     SelectionDAG &DAG) const {

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
index a53e24a05542..90936670c471 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -108,6 +108,7 @@ class WebAssemblyTargetLowering final : public TargetLowering {
   SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerAccessVectorElement(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
 };

diff  --git a/llvm/test/CodeGen/WebAssembly/simd-comparisons.ll b/llvm/test/CodeGen/WebAssembly/simd-comparisons.ll
index 2decd38fa84a..3b6af73eb15f 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-comparisons.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-comparisons.ll
@@ -637,6 +637,156 @@ define <4 x i32> @compare_sext_uge_v4i32 (<4 x i32> %x, <4 x i32> %y) {
   ret <4 x i32> %res
 }
 
+; CHECK-LABEL: compare_eq_v2i64:
+; SIMD128-NEXT: .functype compare_eq_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_eq_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp eq <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_eq_v2i64:
+; SIMD128-NEXT: .functype compare_sext_eq_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_eq_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp eq <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_ne_v2i64:
+; SIMD128-NEXT: .functype compare_ne_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_ne_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp ne <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_ne_v2i64:
+; SIMD128-NEXT: .functype compare_sext_ne_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_ne_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp ne <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_slt_v2i64:
+; SIMD128-NEXT: .functype compare_slt_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_slt_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp slt <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_slt_v2i64:
+; SIMD128-NEXT: .functype compare_sext_slt_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_slt_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp slt <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_ult_v2i64:
+; SIMD128-NEXT: .functype compare_ult_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_ult_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp ult <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_ult_v2i64:
+; SIMD128-NEXT: .functype compare_sext_ult_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_ult_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp ult <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_sle_v2i64:
+; SIMD128-NEXT: .functype compare_sle_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_sle_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp sle <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_sle_v2i64:
+; SIMD128-NEXT: .functype compare_sext_sle_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_sle_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp sle <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_ule_v2i64:
+; SIMD128-NEXT: .functype compare_ule_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_ule_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp ule <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_ule_v2i64:
+; SIMD128-NEXT: .functype compare_sext_ule_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_ule_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp ule <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_sgt_v2i64:
+; SIMD128-NEXT: .functype compare_sgt_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_sgt_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp sgt <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_sgt_v2i64:
+; SIMD128-NEXT: .functype compare_sext_sgt_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_sgt_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp sgt <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_ugt_v2i64:
+; SIMD128-NEXT: .functype compare_ugt_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_ugt_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp ugt <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_ugt_v2i64:
+; SIMD128-NEXT: .functype compare_sext_ugt_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_ugt_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp ugt <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_sge_v2i64:
+; SIMD128-NEXT: .functype compare_sge_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_sge_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp sge <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_sge_v2i64:
+; SIMD128-NEXT: .functype compare_sext_sge_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_sge_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp sge <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
+; CHECK-LABEL: compare_uge_v2i64:
+; SIMD128-NEXT: .functype compare_uge_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i1> @compare_uge_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %res = icmp uge <2 x i64> %x, %y
+  ret <2 x i1> %res
+}
+
+; CHECK-LABEL: compare_sext_uge_v2i64:
+; SIMD128-NEXT: .functype compare_sext_uge_v2i64 (v128, v128) -> (v128){{$}}
+define <2 x i64> @compare_sext_uge_v2i64 (<2 x i64> %x, <2 x i64> %y) {
+  %cmp = icmp uge <2 x i64> %x, %y
+  %res = sext <2 x i1> %cmp to <2 x i64>
+  ret <2 x i64> %res
+}
+
 ; CHECK-LABEL: compare_oeq_v4f32:
 ; NO-SIMD128-NOT: f32x4
 ; SIMD128-NEXT: .functype compare_oeq_v4f32 (v128, v128) -> (v128){{$}}


        


More information about the llvm-commits mailing list