]> granicus.if.org Git - llvm/commitdiff
[Hexagon] Generate min/max instructions for 64-bit vectors
authorKrzysztof Parzyszek <kparzysz@quicinc.com>
Fri, 16 Aug 2019 16:16:27 +0000 (16:16 +0000)
committerKrzysztof Parzyszek <kparzysz@quicinc.com>
Fri, 16 Aug 2019 16:16:27 +0000 (16:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369124 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Hexagon/HexagonISelLowering.cpp
lib/Target/Hexagon/HexagonISelLowering.h
lib/Target/Hexagon/HexagonPatterns.td
lib/Target/Hexagon/HexagonPatternsHVX.td
test/CodeGen/Hexagon/isel-minmax-v64bit.ll [new file with mode: 0644]
test/CodeGen/Hexagon/isel-vselect-v4i8.ll

index 61cac288e48545b2aff853302d24b3cde1a1583d..a443a29e061ef301b1cd9d6bb1808890564daa16 100644 (file)
@@ -1501,11 +1501,15 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::STORE, VT, Custom);
   }
 
-  for (MVT VT : {MVT::v2i16, MVT::v4i8, MVT::v2i32, MVT::v4i16, MVT::v2i32}) {
-    setCondCodeAction(ISD::SETLT,  VT, Expand);
+  for (MVT VT : {MVT::v2i16, MVT::v4i8, MVT::v8i8, MVT::v2i32, MVT::v4i16,
+                 MVT::v2i32}) {
+    setCondCodeAction(ISD::SETNE,  VT, Expand);
     setCondCodeAction(ISD::SETLE,  VT, Expand);
-    setCondCodeAction(ISD::SETULT, VT, Expand);
+    setCondCodeAction(ISD::SETGE,  VT, Expand);
+    setCondCodeAction(ISD::SETLT,  VT, Expand);
     setCondCodeAction(ISD::SETULE, VT, Expand);
+    setCondCodeAction(ISD::SETUGE, VT, Expand);
+    setCondCodeAction(ISD::SETULT, VT, Expand);
   }
 
   // Custom-lower bitcasts from i8 to v8i1.
@@ -1560,6 +1564,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FSUB, MVT::f64, Legal);
   }
 
+  setTargetDAGCombine(ISD::VSELECT);
+
   if (Subtarget.useHVXOps())
     initializeHVXLowering();
 
@@ -1649,6 +1655,8 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case HexagonISD::VINSERTW0:     return "HexagonISD::VINSERTW0";
   case HexagonISD::VROR:          return "HexagonISD::VROR";
   case HexagonISD::READCYCLE:     return "HexagonISD::READCYCLE";
+  case HexagonISD::PTRUE:         return "HexagonISD::PTRUE";
+  case HexagonISD::PFALSE:        return "HexagonISD::PFALSE";
   case HexagonISD::VZERO:         return "HexagonISD::VZERO";
   case HexagonISD::VSPLATW:       return "HexagonISD::VSPLATW";
   case HexagonISD::D2P:           return "HexagonISD::D2P";
@@ -2464,6 +2472,23 @@ HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
     return buildVector64(Ops, dl, VecTy, DAG);
 
   if (VecTy == MVT::v8i1 || VecTy == MVT::v4i1 || VecTy == MVT::v2i1) {
+    // Check if this is a special case or all-0 or all-1.
+    bool All0 = true, All1 = true;
+    for (SDValue P : Ops) {
+      auto *CN = dyn_cast<ConstantSDNode>(P.getNode());
+      if (CN == nullptr) {
+        All0 = All1 = false;
+        break;
+      }
+      uint32_t C = CN->getZExtValue();
+      All0 &= (C == 0);
+      All1 &= (C == 1);
+    }
+    if (All0)
+      return DAG.getNode(HexagonISD::PFALSE, dl, VecTy);
+    if (All1)
+      return DAG.getNode(HexagonISD::PTRUE, dl, VecTy);
+
     // For each i1 element in the resulting predicate register, put 1
     // shifted by the index of the element into a general-purpose register,
     // then or them together and transfer it back into a predicate register.
@@ -2890,7 +2915,37 @@ HexagonTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
   if (isHvxOperation(Op)) {
     if (SDValue V = PerformHvxDAGCombine(N, DCI))
       return V;
+    return SDValue();
+  }
+
+  const SDLoc &dl(Op);
+  unsigned Opc = Op.getOpcode();
+
+  if (Opc == HexagonISD::P2D) {
+    SDValue P = Op.getOperand(0);
+    switch (P.getOpcode()) {
+      case HexagonISD::PTRUE:
+        return DCI.DAG.getConstant(-1, dl, ty(Op));
+      case HexagonISD::PFALSE:
+        return getZero(dl, ty(Op), DCI.DAG);
+      default:
+        break;
+    }
+  } else if (Opc == ISD::VSELECT) {
+    // This is pretty much duplicated in HexagonISelLoweringHVX...
+    //
+    // (vselect (xor x, ptrue), v0, v1) -> (vselect x, v1, v0)
+    SDValue Cond = Op.getOperand(0);
+    if (Cond->getOpcode() == ISD::XOR) {
+      SDValue C0 = Cond.getOperand(0), C1 = Cond.getOperand(1);
+      if (C1->getOpcode() == HexagonISD::PTRUE) {
+        SDValue VSel = DCI.DAG.getNode(ISD::VSELECT, dl, ty(Op), C0,
+                                       Op.getOperand(2), Op.getOperand(1));
+        return VSel;
+      }
+    }
   }
+
   return SDValue();
 }
 
index 4bc49dd508cd778c5ab0effc4adac4c8679b3817..642ad1db19c116a9ca9ed9248c4cfd4b7e8cd5a4 100644 (file)
@@ -68,6 +68,8 @@ namespace HexagonISD {
       EH_RETURN,
       DCFETCH,
       READCYCLE,
+      PTRUE,
+      PFALSE,
       D2P,         // Convert 8-byte value to 8-bit predicate register. [*]
       P2D,         // Convert 8-bit predicate register to 8-byte value. [*]
       V2Q,         // Convert HVX vector to a vector predicate reg. [*]
index 9a0e0670188fdc01ce9016b98aebbb4a6fb03d2d..bfdeec7c5cf32f77a4112ed23dc57afd961b663d 100644 (file)
@@ -99,13 +99,21 @@ def HWI8:   PatLeaf<(VecPI8  HvxWR:$R)>;
 def HWI16:  PatLeaf<(VecPI16 HvxWR:$R)>;
 def HWI32:  PatLeaf<(VecPI32 HvxWR:$R)>;
 
+def SDTVecLeaf:
+  SDTypeProfile<1, 0, [SDTCisVec<0>]>;
 def SDTVecVecIntOp:
   SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1,2>,
                        SDTCisVT<3,i32>]>;
 
+def HexagonPTRUE:      SDNode<"HexagonISD::PTRUE",      SDTVecLeaf>;
+def HexagonPFALSE:     SDNode<"HexagonISD::PFALSE",     SDTVecLeaf>;
 def HexagonVALIGN:     SDNode<"HexagonISD::VALIGN",     SDTVecVecIntOp>;
 def HexagonVALIGNADDR: SDNode<"HexagonISD::VALIGNADDR", SDTIntUnaryOp>;
 
+def ptrue:  PatFrag<(ops), (HexagonPTRUE)>;
+def pfalse: PatFrag<(ops), (HexagonPFALSE)>;
+def pnot:   PatFrag<(ops node:$Pu), (xor node:$Pu, ptrue)>;
+
 def valign: PatFrag<(ops node:$Vt, node:$Vs, node:$Ru),
                     (HexagonVALIGN node:$Vt, node:$Vs, node:$Ru)>;
 def valignaddr: PatFrag<(ops node:$Addr), (HexagonVALIGNADDR node:$Addr)>;
@@ -320,6 +328,17 @@ multiclass SelMinMax_pats<PatFrag CmpOp, PatFrag Val,
            (InstB Val:$A, Val:$B)>;
 }
 
+multiclass MinMax_pats<InstHexagon PickT, InstHexagon PickS,
+                       PatFrag Sel, PatFrag CmpOp,
+                       ValueType CmpType, PatFrag CmpPred> {
+  def: Pat<(Sel (CmpType (CmpOp CmpPred:$Vs, CmpPred:$Vt)),
+                CmpPred:$Vt, CmpPred:$Vs),
+           (PickT CmpPred:$Vs, CmpPred:$Vt)>;
+  def: Pat<(Sel (CmpType (CmpOp CmpPred:$Vs, CmpPred:$Vt)),
+                CmpPred:$Vs, CmpPred:$Vt),
+           (PickS CmpPred:$Vs, CmpPred:$Vt)>;
+}
+
 
 // Frags for commonly used SDNodes.
 def Add: pf2<add>;    def And: pf2<and>;    def Sra: pf2<sra>;
@@ -497,7 +516,9 @@ def: Pat<(v2i16 (trunc V2I32:$Rs)),
 //
 
 def: Pat<(not I1:$Ps),      (C2_not I1:$Ps)>;
-def: Pat<(not V8I1:$Ps),    (C2_not V8I1:$Ps)>;
+def: Pat<(pnot V2I1:$Ps),   (C2_not V2I1:$Ps)>;
+def: Pat<(pnot V4I1:$Ps),   (C2_not V4I1:$Ps)>;
+def: Pat<(pnot V8I1:$Ps),   (C2_not V8I1:$Ps)>;
 def: Pat<(add I1:$Ps, -1),  (C2_not I1:$Ps)>;
 
 multiclass BoolOpR_RR_pat<InstHexagon MI, PatFrag Op> {
@@ -823,6 +844,14 @@ def: Pat<(vselect V4I1:$Pu, V4I16:$Rs, V4I16:$Rt),
 def: Pat<(vselect V2I1:$Pu, V2I32:$Rs, V2I32:$Rt),
          (C2_vmux V2I1:$Pu, V2I32:$Rs, V2I32:$Rt)>;
 
+def: Pat<(vselect (pnot V8I1:$Pu), V8I8:$Rs, V8I8:$Rt),
+         (C2_vmux V8I1:$Pu, V8I8:$Rt, V8I8:$Rs)>;
+def: Pat<(vselect (pnot V4I1:$Pu), V4I16:$Rs, V4I16:$Rt),
+         (C2_vmux V4I1:$Pu, V4I16:$Rt, V4I16:$Rs)>;
+def: Pat<(vselect (pnot V2I1:$Pu), V2I32:$Rs, V2I32:$Rt),
+         (C2_vmux V2I1:$Pu, V2I32:$Rt, V2I32:$Rs)>;
+
+
 // From LegalizeDAG.cpp: (Pu ? Pv : Pw) <=> (Pu & Pv) | (!Pu & Pw).
 def: Pat<(select I1:$Pu, I1:$Pv, I1:$Pw),
          (C2_or (C2_and  I1:$Pu, I1:$Pv),
@@ -855,32 +884,44 @@ let AddedComplexity = 200 in {
 }
 
 let AddedComplexity = 200 in {
-  defm: SelMinMax_pats<setge,  I32, A2_max,   A2_min>;
-  defm: SelMinMax_pats<setgt,  I32, A2_max,   A2_min>;
-  defm: SelMinMax_pats<setle,  I32, A2_min,   A2_max>;
-  defm: SelMinMax_pats<setlt,  I32, A2_min,   A2_max>;
-  defm: SelMinMax_pats<setuge, I32, A2_maxu,  A2_minu>;
-  defm: SelMinMax_pats<setugt, I32, A2_maxu,  A2_minu>;
-  defm: SelMinMax_pats<setule, I32, A2_minu,  A2_maxu>;
-  defm: SelMinMax_pats<setult, I32, A2_minu,  A2_maxu>;
-
-  defm: SelMinMax_pats<setge,  I64, A2_maxp,  A2_minp>;
-  defm: SelMinMax_pats<setgt,  I64, A2_maxp,  A2_minp>;
-  defm: SelMinMax_pats<setle,  I64, A2_minp,  A2_maxp>;
-  defm: SelMinMax_pats<setlt,  I64, A2_minp,  A2_maxp>;
-  defm: SelMinMax_pats<setuge, I64, A2_maxup, A2_minup>;
-  defm: SelMinMax_pats<setugt, I64, A2_maxup, A2_minup>;
-  defm: SelMinMax_pats<setule, I64, A2_minup, A2_maxup>;
-  defm: SelMinMax_pats<setult, I64, A2_minup, A2_maxup>;
+  defm: MinMax_pats<A2_min,   A2_max,   select,  setgt, i1, I32>;
+  defm: MinMax_pats<A2_min,   A2_max,   select,  setge, i1, I32>;
+  defm: MinMax_pats<A2_max,   A2_min,   select,  setlt, i1, I32>;
+  defm: MinMax_pats<A2_max,   A2_min,   select,  setle, i1, I32>;
+  defm: MinMax_pats<A2_minu,  A2_maxu,  select, setugt, i1, I32>;
+  defm: MinMax_pats<A2_minu,  A2_maxu,  select, setuge, i1, I32>;
+  defm: MinMax_pats<A2_maxu,  A2_minu,  select, setult, i1, I32>;
+  defm: MinMax_pats<A2_maxu,  A2_minu,  select, setule, i1, I32>;
+
+  defm: MinMax_pats<A2_minp,  A2_maxp,  select,  setgt, i1, I64>;
+  defm: MinMax_pats<A2_minp,  A2_maxp,  select,  setge, i1, I64>;
+  defm: MinMax_pats<A2_maxp,  A2_minp,  select,  setlt, i1, I64>;
+  defm: MinMax_pats<A2_maxp,  A2_minp,  select,  setle, i1, I64>;
+  defm: MinMax_pats<A2_minup, A2_maxup, select, setugt, i1, I64>;
+  defm: MinMax_pats<A2_minup, A2_maxup, select, setuge, i1, I64>;
+  defm: MinMax_pats<A2_maxup, A2_minup, select, setult, i1, I64>;
+  defm: MinMax_pats<A2_maxup, A2_minup, select, setule, i1, I64>;
 }
 
 let AddedComplexity = 100 in {
-  defm: SelMinMax_pats<setolt, F32, F2_sfmin, F2_sfmax>;
-  defm: SelMinMax_pats<setole, F32, F2_sfmin, F2_sfmax>;
-  defm: SelMinMax_pats<setogt, F32, F2_sfmax, F2_sfmin>;
-  defm: SelMinMax_pats<setoge, F32, F2_sfmax, F2_sfmin>;
-}
-
+  defm: MinMax_pats<F2_sfmin, F2_sfmax, select, setogt, i1, F32>;
+  defm: MinMax_pats<F2_sfmin, F2_sfmax, select, setoge, i1, F32>;
+  defm: MinMax_pats<F2_sfmax, F2_sfmin, select, setolt, i1, F32>;
+  defm: MinMax_pats<F2_sfmax, F2_sfmin, select, setole, i1, F32>;
+}
+
+defm: MinMax_pats<A2_vminb,  A2_vmaxb,  vselect,  setgt,  v8i1,  V8I8>;
+defm: MinMax_pats<A2_vminb,  A2_vmaxb,  vselect,  setge,  v8i1,  V8I8>;
+defm: MinMax_pats<A2_vminh,  A2_vmaxh,  vselect,  setgt,  v4i1, V4I16>;
+defm: MinMax_pats<A2_vminh,  A2_vmaxh,  vselect,  setge,  v4i1, V4I16>;
+defm: MinMax_pats<A2_vminw,  A2_vmaxw,  vselect,  setgt,  v2i1, V2I32>;
+defm: MinMax_pats<A2_vminw,  A2_vmaxw,  vselect,  setge,  v2i1, V2I32>;
+defm: MinMax_pats<A2_vminub, A2_vmaxub, vselect, setugt,  v8i1,  V8I8>;
+defm: MinMax_pats<A2_vminub, A2_vmaxub, vselect, setuge,  v8i1,  V8I8>;
+defm: MinMax_pats<A2_vminuh, A2_vmaxuh, vselect, setugt,  v4i1, V4I16>;
+defm: MinMax_pats<A2_vminuh, A2_vmaxuh, vselect, setuge,  v4i1, V4I16>;
+defm: MinMax_pats<A2_vminuw, A2_vmaxuw, vselect, setugt,  v2i1, V2I32>;
+defm: MinMax_pats<A2_vminuw, A2_vmaxuw, vselect, setuge,  v2i1, V2I32>;
 
 // --(7) Insert/extract --------------------------------------------------
 //
index 4f3d87263b5f303b7a63604def9a99ed5b80ae0f..32e2260de07c066fa700a57b31efea6a827ceba0 100644 (file)
@@ -1,5 +1,3 @@
-def SDTVecLeaf:
-  SDTypeProfile<1, 0, [SDTCisVec<0>]>;
 def SDTVecBinOp:
   SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1,2>]>;
 
@@ -259,28 +257,18 @@ class Vneg1<ValueType VecTy>
 class Vnot<ValueType VecTy>
   : PatFrag<(ops node:$Vs), (xor $Vs, Vneg1<VecTy>)>;
 
-multiclass VMinMax_pat<InstHexagon MinInst, InstHexagon MaxInst, PatFrag CmpOp,
-                       ValueType CmpType, PatFrag CmpPred> {
-  def: Pat<(vselect (CmpType (CmpOp CmpPred:$Vs, CmpPred:$Vt)),
-                             CmpPred:$Vt, CmpPred:$Vs),
-           (MinInst CmpPred:$Vs, CmpPred:$Vt)>;
-  def: Pat<(vselect (CmpType (CmpOp CmpPred:$Vs, CmpPred:$Vt)),
-                             CmpPred:$Vs, CmpPred:$Vt),
-           (MaxInst CmpPred:$Vs, CmpPred:$Vt)>;
-}
-
 let Predicates = [UseHVX] in {
   let AddedComplexity = 220 in {
-    defm: VMinMax_pat<V6_vminb,  V6_vmaxb,   setgt,  VecQ8,  HVI8>;
-    defm: VMinMax_pat<V6_vminb,  V6_vmaxb,   setge,  VecQ8,  HVI8>;
-    defm: VMinMax_pat<V6_vminub, V6_vmaxub, setugt,  VecQ8,  HVI8>;
-    defm: VMinMax_pat<V6_vminub, V6_vmaxub, setuge,  VecQ8,  HVI8>;
-    defm: VMinMax_pat<V6_vminh,  V6_vmaxh,   setgt, VecQ16, HVI16>;
-    defm: VMinMax_pat<V6_vminh,  V6_vmaxh,   setge, VecQ16, HVI16>;
-    defm: VMinMax_pat<V6_vminuh, V6_vmaxuh, setugt, VecQ16, HVI16>;
-    defm: VMinMax_pat<V6_vminuh, V6_vmaxuh, setuge, VecQ16, HVI16>;
-    defm: VMinMax_pat<V6_vminw,  V6_vmaxw,   setgt, VecQ32, HVI32>;
-    defm: VMinMax_pat<V6_vminw,  V6_vmaxw,   setge, VecQ32, HVI32>;
+    defm: MinMax_pats<V6_vminb,  V6_vmaxb,  vselect,  setgt,  VecQ8,  HVI8>;
+    defm: MinMax_pats<V6_vminb,  V6_vmaxb,  vselect,  setge,  VecQ8,  HVI8>;
+    defm: MinMax_pats<V6_vminub, V6_vmaxub, vselect, setugt,  VecQ8,  HVI8>;
+    defm: MinMax_pats<V6_vminub, V6_vmaxub, vselect, setuge,  VecQ8,  HVI8>;
+    defm: MinMax_pats<V6_vminh,  V6_vmaxh,  vselect,  setgt, VecQ16, HVI16>;
+    defm: MinMax_pats<V6_vminh,  V6_vmaxh,  vselect,  setge, VecQ16, HVI16>;
+    defm: MinMax_pats<V6_vminuh, V6_vmaxuh, vselect, setugt, VecQ16, HVI16>;
+    defm: MinMax_pats<V6_vminuh, V6_vmaxuh, vselect, setuge, VecQ16, HVI16>;
+    defm: MinMax_pats<V6_vminw,  V6_vmaxw,  vselect,  setgt, VecQ32, HVI32>;
+    defm: MinMax_pats<V6_vminw,  V6_vmaxw,  vselect,  setge, VecQ32, HVI32>;
   }
 }
 
diff --git a/test/CodeGen/Hexagon/isel-minmax-v64bit.ll b/test/CodeGen/Hexagon/isel-minmax-v64bit.ll
new file mode 100644 (file)
index 0000000..53dec51
--- /dev/null
@@ -0,0 +1,202 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+
+; min
+
+; CHECK-LABEL: test_00:
+; CHECK: r1:0 = vminb(r3:2,r1:0)
+define <8 x i8> @test_00(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp slt <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_01:
+; CHECK: r1:0 = vminb(r1:0,r3:2)
+define <8 x i8> @test_01(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp sle <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_02:
+; CHECK: r1:0 = vminh(r3:2,r1:0)
+define <4 x i16> @test_02(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp slt <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_03:
+; CHECK: r1:0 = vminh(r1:0,r3:2)
+define <4 x i16> @test_03(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp sle <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_04:
+; CHECK: r1:0 = vminw(r3:2,r1:0)
+define <2 x i32> @test_04(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp slt <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; CHECK-LABEL: test_05:
+; CHECK: r1:0 = vminw(r1:0,r3:2)
+define <2 x i32> @test_05(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp sle <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; minu
+
+; CHECK-LABEL: test_06:
+; CHECK: r1:0 = vminub(r3:2,r1:0)
+define <8 x i8> @test_06(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp ult <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_07:
+; CHECK: r1:0 = vminub(r1:0,r3:2)
+define <8 x i8> @test_07(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp ule <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_08:
+; CHECK: r1:0 = vminuh(r3:2,r1:0)
+define <4 x i16> @test_08(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp ult <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_09:
+; CHECK: r1:0 = vminuh(r1:0,r3:2)
+define <4 x i16> @test_09(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp ule <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_0a:
+; CHECK: r1:0 = vminuw(r3:2,r1:0)
+define <2 x i32> @test_0a(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp ult <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; CHECK-LABEL: test_0b:
+; CHECK: r1:0 = vminuw(r1:0,r3:2)
+define <2 x i32> @test_0b(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp ule <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; max
+
+; CHECK-LABEL: test_0c:
+; CHECK: r1:0 = vmaxb(r1:0,r3:2)
+define <8 x i8> @test_0c(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp sgt <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_0d:
+; CHECK: r1:0 = vmaxb(r3:2,r1:0)
+define <8 x i8> @test_0d(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp sge <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_0e:
+; CHECK: r1:0 = vmaxh(r1:0,r3:2)
+define <4 x i16> @test_0e(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp sgt <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_0f:
+; CHECK: r1:0 = vmaxh(r3:2,r1:0)
+define <4 x i16> @test_0f(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp sge <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_10:
+; CHECK: r1:0 = vmaxw(r1:0,r3:2)
+define <2 x i32> @test_10(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp sgt <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; CHECK-LABEL: test_11:
+; CHECK: r1:0 = vmaxw(r3:2,r1:0)
+define <2 x i32> @test_11(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp sge <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; maxu
+
+; CHECK-LABEL: test_12:
+; CHECK: r1:0 = vmaxub(r1:0,r3:2)
+define <8 x i8> @test_12(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp ugt <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_13:
+; CHECK: r1:0 = vmaxub(r3:2,r1:0)
+define <8 x i8> @test_13(<8 x i8> %a0, <8 x i8> %a1) #0 {
+  %v0 = icmp uge <8 x i8> %a0, %a1
+  %v1 = select <8 x i1> %v0, <8 x i8> %a0, <8 x i8> %a1
+  ret <8 x i8> %v1
+}
+
+; CHECK-LABEL: test_14:
+; CHECK: r1:0 = vmaxuh(r1:0,r3:2)
+define <4 x i16> @test_14(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp ugt <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_15:
+; CHECK: r1:0 = vmaxuh(r3:2,r1:0)
+define <4 x i16> @test_15(<4 x i16> %a0, <4 x i16> %a1) #0 {
+  %v0 = icmp uge <4 x i16> %a0, %a1
+  %v1 = select <4 x i1> %v0, <4 x i16> %a0, <4 x i16> %a1
+  ret <4 x i16> %v1
+}
+
+; CHECK-LABEL: test_16:
+; CHECK: r1:0 = vmaxuw(r1:0,r3:2)
+define <2 x i32> @test_16(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp ugt <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
+; CHECK-LABEL: test_17:
+; CHECK: r1:0 = vmaxuw(r3:2,r1:0)
+define <2 x i32> @test_17(<2 x i32> %a0, <2 x i32> %a1) #0 {
+  %v0 = icmp uge <2 x i32> %a0, %a1
+  %v1 = select <2 x i1> %v0, <2 x i32> %a0, <2 x i32> %a1
+  ret <2 x i32> %v1
+}
+
index 6e4c7b2e9563c2c339f09e566db3b239915078f4..d895f129efcd81dcd6121fcd86a8f1478c780542 100644 (file)
@@ -1,6 +1,6 @@
 ; RUN: llc -march=hexagon < %s | FileCheck %s
 ; This used to crash with "cannot select (v4i8 vselect ...)"
-; CHECK: vmux
+; CHECK: vtrunehb
 
 define <4 x i8> @f0(<4 x i8> %a0, <4 x i8> %a1) #0 {
   %v0 = icmp slt <4 x i8> %a0, %a1