[mips][msa] Added support for matching nor from normal IR (i.e. not intrinsics)



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191195 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 21c5edb..443653f 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -214,6 +214,7 @@
   case MipsISD::VANY_NONZERO:      return "MipsISD::VANY_NONZERO";
   case MipsISD::VSPLAT:            return "MipsISD::VSPLAT";
   case MipsISD::VSPLATD:           return "MipsISD::VSPLATD";
+  case MipsISD::VNOR:              return "MipsISD::VNOR";
   default:                         return NULL;
   }
 }
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index 57b5603..b56ac41 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -164,6 +164,9 @@
       // constant, and the operand fits in a signed 10-bits value.
       VSPLATD,
 
+      // Combined (XOR (OR $a, $b), -1)
+      VNOR,
+
       // Load/Store Left/Right nodes.
       LWL = ISD::FIRST_TARGET_MEMORY_OPCODE,
       LWR,
diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td
index b7bc357..9783256 100644
--- a/lib/Target/Mips/MipsMSAInstrInfo.td
+++ b/lib/Target/Mips/MipsMSAInstrInfo.td
@@ -20,6 +20,8 @@
 def MipsVAnyZero : SDNode<"MipsISD::VANY_ZERO", SDT_MipsVecCond>;
 def MipsVSplat  : SDNode<"MipsISD::VSPLAT", SDT_MipsSplat>;
 def MipsVSplatD : SDNode<"MipsISD::VSPLATD", SDT_MipsSplat>;
+def MipsVNOR : SDNode<"MipsISD::VNOR", SDTIntBinOp,
+                      [SDNPCommutative, SDNPAssociative]>;
 
 def vsplati8  : PatFrag<(ops node:$in), (v16i8 (MipsVSplat (i32 node:$in)))>;
 def vsplati16 : PatFrag<(ops node:$in), (v8i16 (MipsVSplat (i32 node:$in)))>;
@@ -1729,7 +1731,10 @@
 class NLZC_W_DESC : MSA_2R_DESC_BASE<"nlzc.w", ctlz, MSA128W>;
 class NLZC_D_DESC : MSA_2R_DESC_BASE<"nlzc.d", ctlz, MSA128D>;
 
-class NOR_V_DESC : MSA_VEC_DESC_BASE<"nor.v", int_mips_nor_v, MSA128B>;
+class NOR_V_DESC : MSA_VEC_DESC_BASE<"nor.v", MipsVNOR, MSA128B>;
+class NOR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128H>;
+class NOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128W>;
+class NOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128D>;
 
 class NORI_B_DESC : MSA_I8_DESC_BASE<"nori.b", int_mips_nori_b, MSA128B>;
 
@@ -2498,6 +2503,15 @@
 def NLZC_D : NLZC_D_ENC, NLZC_D_DESC;
 
 def NOR_V : NOR_V_ENC, NOR_V_DESC;
+def NOR_V_H_PSEUDO : NOR_V_H_PSEUDO_DESC,
+                     PseudoInstExpansion<(NOR_V MSA128B:$wd,
+                                                MSA128B:$ws, MSA128B:$wt)>;
+def NOR_V_W_PSEUDO : NOR_V_W_PSEUDO_DESC,
+                     PseudoInstExpansion<(NOR_V MSA128B:$wd,
+                                                MSA128B:$ws, MSA128B:$wt)>;
+def NOR_V_D_PSEUDO : NOR_V_D_PSEUDO_DESC,
+                     PseudoInstExpansion<(NOR_V MSA128B:$wd,
+                                                MSA128B:$ws, MSA128B:$wt)>;
 
 def NORI_B : NORI_B_ENC, NORI_B_DESC;
 
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index 9532c9d..ca3e06c 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -90,6 +90,8 @@
     addMSAFloatType(MVT::v8f16, &Mips::MSA128HRegClass);
     addMSAFloatType(MVT::v4f32, &Mips::MSA128WRegClass);
     addMSAFloatType(MVT::v2f64, &Mips::MSA128DRegClass);
+
+    setTargetDAGCombine(ISD::XOR);
   }
 
   if (!Subtarget->mipsSEUsesSoftFloat()) {
@@ -567,6 +569,44 @@
                      N->getOperand(2), SetCC.getOperand(2));
 }
 
+static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
+                                 const MipsSubtarget *Subtarget) {
+  EVT Ty = N->getValueType(0);
+
+  if (Subtarget->hasMSA() && Ty.is128BitVector() && Ty.isInteger()) {
+    // Try the following combines:
+    //   (xor (or $a, $b), (build_vector allones))
+    //   (xor (or $a, $b), (bitcast (build_vector allones)))
+    SDValue Op0 = N->getOperand(0);
+    SDValue Op1 = N->getOperand(1);
+    SDValue NotOp;
+    ConstantSDNode *Const;
+
+    if (ISD::isBuildVectorAllOnes(Op0.getNode()))
+      NotOp = Op1;
+    else if (ISD::isBuildVectorAllOnes(Op1.getNode()))
+      NotOp = Op0;
+    else if ((Op0->getOpcode() == MipsISD::VSPLAT ||
+              Op0->getOpcode() == MipsISD::VSPLATD) &&
+             (Const = dyn_cast<ConstantSDNode>(Op0->getOperand(0))) &&
+             Const->isAllOnesValue())
+      NotOp = Op1;
+    else if ((Op1->getOpcode() == MipsISD::VSPLAT ||
+              Op1->getOpcode() == MipsISD::VSPLATD) &&
+             (Const = dyn_cast<ConstantSDNode>(Op1->getOperand(0))) &&
+             Const->isAllOnesValue())
+      NotOp = Op0;
+    else
+      return SDValue();
+
+    if (NotOp->getOpcode() == ISD::OR)
+      return DAG.getNode(MipsISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0),
+                         NotOp->getOperand(1));
+  }
+
+  return SDValue();
+}
+
 SDValue
 MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
   SelectionDAG &DAG = DCI.DAG;
@@ -587,11 +627,13 @@
     return performSRLCombine(N, DAG, DCI, Subtarget);
   case ISD::VSELECT:
     return performVSELECTCombine(N, DAG);
-  case ISD::SETCC: {
+  case ISD::XOR:
+    Val = performXORCombine(N, DAG, Subtarget);
+    break;
+  case ISD::SETCC:
     Val = performSETCCCombine(N, DAG);
     break;
   }
-  }
 
   if (Val.getNode())
     return Val;
@@ -964,6 +1006,10 @@
   case Intrinsic::mips_nlzc_w:
   case Intrinsic::mips_nlzc_d:
     return lowerMSAUnaryIntr(Op, DAG, ISD::CTLZ);
+  case Intrinsic::mips_nor_v: {
+    SDValue Res = lowerMSABinaryIntr(Op, DAG, ISD::OR);
+    return DAG.getNOT(SDLoc(Op), Res, Res->getValueType(0));
+  }
   case Intrinsic::mips_or_v:
     return lowerMSABinaryIntr(Op, DAG, ISD::OR);
   case Intrinsic::mips_sll_b: