[RISCV] Use ComplexPattern to reduce the number of patterns for XVentanaCondOps.
authorCraig Topper <craig.topper@sifive.com>
Fri, 24 Feb 2023 17:36:58 +0000 (09:36 -0800)
committerCraig Topper <craig.topper@sifive.com>
Fri, 24 Feb 2023 17:36:58 +0000 (09:36 -0800)
XVentanaCondOps check the condition operand for zero or non-zero.
We use this to optimize seteq/setne that would otherwise becomes
xor/xori/addi+snez/seqz. These patterns avoid the snez/seqz.

This patch adds two ComplexPatterns to match the varous cases and
emit the xor/xori/addi instruction.

These patterns can also be used by D144681.

Reviewed By: philipp.tomsich

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

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td

index 604ad1f..8516520 100644 (file)
@@ -2423,6 +2423,72 @@ bool RISCVDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth,
   return true;
 }
 
+/// Some instructions have a condition operand that is compared against zero.
+/// Since RISC-V doesn't have seteq/setne instructions, we can use this
+/// property to avoid a seqz or snez instruction after an xor/addi/xori.
+/// When \p Inverse is false, we match seteq or any unknown operation. When
+/// \p Inverse is true, we only match setne.
+bool RISCVDAGToDAGISel::selectCondOp(SDValue N, bool Inverse, SDValue &Val) {
+  // Start with this node as the output.
+  Val = N;
+
+  // If the node isn't a setcc, there's nothing we can do. Return success
+  // if we aren't looking for an inverse condition.
+  if (N->getOpcode() != ISD::SETCC)
+    return !Inverse;
+
+  // If it isn't an equality comparison, we also can't do anything.
+  ISD::CondCode CCVal = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  if (!isIntEqualitySetCC(CCVal))
+    return !Inverse;
+
+  // This ComplexPattern occurs in pairs with both polarities of Inverse.
+  // If this isn't the one we're looking for, let the other polarity match it.
+  if (isTrueWhenEqual(CCVal) != Inverse)
+    return false;
+
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+
+  // If the RHS side is 0, we don't need any extra instructions, return the LHS.
+  if (isNullConstant(RHS)) {
+    Val = LHS;
+    return true;
+  }
+
+  SDLoc DL(N);
+
+  if (auto *C = dyn_cast<ConstantSDNode>(RHS)) {
+    int64_t CVal = C->getSExtValue();
+    // If the RHS is -2048, we can use xori to produce 0 if the LHS is -2048 and
+    // non-zero otherwise.
+    if (CVal == -2048) {
+      Val =
+          SDValue(CurDAG->getMachineNode(
+                      RISCV::XORI, DL, N->getValueType(0), LHS,
+                      CurDAG->getTargetConstant(CVal, DL, N->getValueType(0))),
+                  0);
+      return true;
+    }
+    // If the RHS is [-2047,2048], we can use addi with -RHS to produce 0 if the
+    // LHS is equal to the RHS and non-zero otherwise.
+    if (isInt<12>(CVal) || CVal == 2048) {
+      Val =
+          SDValue(CurDAG->getMachineNode(
+                      RISCV::ADDI, DL, N->getValueType(0), LHS,
+                      CurDAG->getTargetConstant(-CVal, DL, N->getValueType(0))),
+                  0);
+      return true;
+    }
+  }
+
+  // If nothing else we can XOR the LHS and RHS to produce zero if they are
+  // equal and a non-zero value if they aren't.
+  Val = SDValue(
+      CurDAG->getMachineNode(RISCV::XOR, DL, N->getValueType(0), LHS, RHS), 0);
+  return true;
+}
+
 bool RISCVDAGToDAGISel::selectSExtBits(SDValue N, unsigned Bits, SDValue &Val) {
   if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
       cast<VTSDNode>(N.getOperand(1))->getVT().getSizeInBits() == Bits) {
index 3e023f4..df4671d 100644 (file)
@@ -86,6 +86,14 @@ public:
     return selectShiftMask(N, 32, ShAmt);
   }
 
+  bool selectCondOp(SDValue N, bool Inverse, SDValue &Val);
+  bool selectCondOp(SDValue N, SDValue &Val) {
+    return selectCondOp(N, /*Inverse*/ false, Val);
+  }
+  bool selectInverseCondOp(SDValue N, SDValue &Val) {
+    return selectCondOp(N, /*Inverse*/ true, Val);
+  }
+
   bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val);
   template <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) {
     return selectSExtBits(N, Bits, Val);
index 52d8a0e..e6a292d 100644 (file)
@@ -1870,6 +1870,15 @@ def : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)),
                  (AddiPairImmSmall AddiPair:$rs2))>;
 }
 
+// Some instructions have a condition operand that is compared against zero.
+// Since RISC-V doesn't have seteq/setne instructions, we can use this
+// property to avoid a seqz or snez instruction after an xor/addi/xori.
+// condop matches a setne or any unknown operation.
+// invcondop only matches a seteq.
+// This ComplexPatterns must be used in pairs.
+def condop    : ComplexPattern<XLenVT, 1, "selectCondOp">;
+def invcondop : ComplexPattern<XLenVT, 1, "selectInverseCondOp">;
+
 /// Empty pseudo for RISCVInitUndefPass
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 0, isCodeGenOnly = 1 in {
   def PseudoRVVInitUndefM1     :  Pseudo<(outs VR:$vd), (ins), [], "">;
index 68c3a21..73a06e0 100644 (file)
@@ -30,46 +30,14 @@ def VT_MASKCN : VTMaskedMove<0b111, "vt.maskcn">,
 
 let Predicates = [IsRV64, HasVendorXVentanaCondOps] in {
 // Directly use MASKC/MASKCN in case of any of the operands being 0.
-def : Pat<(select GPR:$rc, GPR:$rs1, (i64 0)),
-          (VT_MASKC $rs1, $rc)>;
-def : Pat<(select GPR:$rc, (i64 0), GPR:$rs1),
-          (VT_MASKCN $rs1, $rc)>;
-
-def : Pat<(select (i64 (setne GPR:$rc, (i64 0))), GPR:$rs1, (i64 0)),
-          (VT_MASKC GPR:$rs1, GPR:$rc)>;
-def : Pat<(select (i64 (seteq GPR:$rc, (i64 0))), GPR:$rs1, (i64 0)),
-          (VT_MASKCN GPR:$rs1, GPR:$rc)>;
-def : Pat<(select (i64 (setne GPR:$rc, (i64 0))), (i64 0), GPR:$rs1),
-          (VT_MASKCN GPR:$rs1, GPR:$rc)>;
-def : Pat<(select (i64 (seteq GPR:$rc, (i64 0))), (i64 0), GPR:$rs1),
-          (VT_MASKC GPR:$rs1, GPR:$rc)>;
-
-def : Pat<(select (i64 (setne GPR:$x, simm12_plus1:$y)), GPR:$rs1, (i64 0)),
-          (VT_MASKC GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>;
-def : Pat<(select (i64 (seteq GPR:$x, simm12_plus1:$y)), GPR:$rs1, (i64 0)),
-          (VT_MASKCN GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>;
-def : Pat<(select (i64 (setne GPR:$x, simm12_plus1:$y)), (i64 0), GPR:$rs1),
-          (VT_MASKCN GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>;
-def : Pat<(select (i64 (seteq GPR:$x, simm12_plus1:$y)), (i64 0), GPR:$rs1),
-          (VT_MASKC GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>;
-
-def : Pat<(select (i64 (setne GPR:$x, (i64 -2048))), GPR:$rs1, (i64 0)),
-          (VT_MASKC GPR:$rs1, (XORI GPR:$x, -2048))>;
-def : Pat<(select (i64 (seteq GPR:$x, (i64 -2048))), GPR:$rs1, (i64 0)),
-          (VT_MASKCN GPR:$rs1, (XORI GPR:$x, -2048))>;
-def : Pat<(select (i64 (setne GPR:$x, (i64 -2048))), (i64 0), GPR:$rs1),
-          (VT_MASKCN GPR:$rs1, (XORI GPR:$x, -2048))>;
-def : Pat<(select (i64 (seteq GPR:$x, (i64 -2048))), (i64 0), GPR:$rs1),
-          (VT_MASKC GPR:$rs1, (XORI GPR:$x, -2048))>;
-
-def : Pat<(select (i64 (setne GPR:$x, GPR:$y)), GPR:$rs1, (i64 0)),
-          (VT_MASKC GPR:$rs1, (XOR GPR:$x, GPR:$y))>;
-def : Pat<(select (i64 (seteq GPR:$x, GPR:$y)), GPR:$rs1, (i64 0)),
-          (VT_MASKCN GPR:$rs1, (XOR GPR:$x, GPR:$y))>;
-def : Pat<(select (i64 (setne GPR:$x, GPR:$y)), (i64 0), GPR:$rs1),
-          (VT_MASKCN GPR:$rs1, (XOR GPR:$x, GPR:$y))>;
-def : Pat<(select (i64 (seteq GPR:$x, GPR:$y)), (i64 0), GPR:$rs1),
-          (VT_MASKC GPR:$rs1, (XOR GPR:$x, GPR:$y))>;
+def : Pat<(select condop:$rc, GPR:$rs1, (i64 0)),
+          (VT_MASKC GPR:$rs1, condop:$rc)>;
+def : Pat<(select invcondop:$rc, GPR:$rs1, (i64 0)),
+          (VT_MASKCN GPR:$rs1, invcondop:$rc)>;
+def : Pat<(select condop:$rc, (i64 0), GPR:$rs1),
+          (VT_MASKCN GPR:$rs1, condop:$rc)>;
+def : Pat<(select invcondop:$rc, (i64 0), GPR:$rs1),
+          (VT_MASKC GPR:$rs1, invcondop:$rc)>;
 
 // Conditional AND operation patterns.
 def : Pat<(i64 (select GPR:$rc, (and GPR:$rs1, GPR:$rs2), GPR:$rs1)),