[RISCV] Generalize select (and (x , 0x1) == 0), y, (z ^ y) ) and select (and (x ...
authorPhilip Reames <preames@rivosinc.com>
Mon, 3 Oct 2022 19:54:38 +0000 (12:54 -0700)
committerPhilip Reames <listmail@philipreames.com>
Mon, 3 Oct 2022 20:57:38 +0000 (13:57 -0700)
These transforms were recently added (by me) in D134881. Looking at the code again, I realized we don't need the (and x, 0x1) portion of the pattern, we just need to know that the result of that sub-tree is either 0 or 1. Checking for this directly allows us to match slightly more broadly. The test changes are zext i1 arguments, but this could also kick in for e.g. shifts of high bits, or any other source of known bits.

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

llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/select-binop-identity.ll

index 3b36521..78eca13 100644 (file)
@@ -9022,12 +9022,13 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
     if (TrueV == FalseV)
       return TrueV;
 
-    // (select (and (x , 0x1) == 0), y, (z ^ y) ) -> (-(and (x , 0x1)) & z ) ^ y
-    // (select (and (x , 0x1) != 0), (z ^ y) ), y -> (-(and (x , 0x1)) & z ) ^ y
-    // (select (and (x , 0x1) == 0), y, (z | y) ) -> (-(and (x , 0x1)) & z ) | y
-    // (select (and (x , 0x1) != 0), (z | y) ), y -> (-(and (x , 0x1)) & z ) | y
+    // (select (x in [0,1] == 0), y, (z ^ y) ) -> (-x & z ) ^ y
+    // (select (x in [0,1] != 0), (z ^ y) ), y -> (-x & z ) ^ y
+    // (select (x in [0,1] == 0), y, (z | y) ) -> (-x & z ) | y
+    // (select (x in [0,1] != 0), (z | y) ), y -> (-x & z ) | y
+    APInt Mask = APInt::getBitsSetFrom(LHS.getValueSizeInBits(), 1);
     if (isNullConstant(RHS) && ISD::isIntEqualitySetCC(CCVal) &&
-        LHS.getOpcode() == ISD::AND && isOneConstant(LHS.getOperand(1))) {
+        DAG.MaskedValueIsZero(LHS, Mask)) {
       unsigned Opcode;
       SDValue Src1, Src2;
       // true if FalseV is XOR or OR operator and one of its operands
index 3449a33..b22988a 100644 (file)
@@ -61,20 +61,16 @@ define i64 @and_select_all_ones_i64(i1 zeroext %c, i64 %x, i64 %y) {
 define signext i32 @or_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32 signext %y) {
 ; RV32I-LABEL: or_select_all_zeros_i32:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    beqz a0, .LBB2_2
-; RV32I-NEXT:  # %bb.1:
-; RV32I-NEXT:    or a2, a2, a1
-; RV32I-NEXT:  .LBB2_2:
-; RV32I-NEXT:    mv a0, a2
+; RV32I-NEXT:    neg a0, a0
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    or a0, a0, a2
 ; RV32I-NEXT:    ret
 ;
 ; RV64I-LABEL: or_select_all_zeros_i32:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    beqz a0, .LBB2_2
-; RV64I-NEXT:  # %bb.1:
-; RV64I-NEXT:    or a2, a2, a1
-; RV64I-NEXT:  .LBB2_2:
-; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    neg a0, a0
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    or a0, a0, a2
 ; RV64I-NEXT:    ret
   %a = select i1 %c, i32 %x, i32 0
   %b = or i32 %y, %a
@@ -132,22 +128,18 @@ define signext i32 @xor_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32
 define i64 @xor_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) {
 ; RV32I-LABEL: xor_select_all_zeros_i64:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    beqz a0, .LBB5_2
-; RV32I-NEXT:  # %bb.1:
-; RV32I-NEXT:    xor a3, a3, a1
-; RV32I-NEXT:    xor a4, a4, a2
-; RV32I-NEXT:  .LBB5_2:
-; RV32I-NEXT:    mv a0, a3
-; RV32I-NEXT:    mv a1, a4
+; RV32I-NEXT:    neg a5, a0
+; RV32I-NEXT:    and a0, a5, a1
+; RV32I-NEXT:    xor a0, a0, a3
+; RV32I-NEXT:    and a1, a5, a2
+; RV32I-NEXT:    xor a1, a1, a4
 ; RV32I-NEXT:    ret
 ;
 ; RV64I-LABEL: xor_select_all_zeros_i64:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    beqz a0, .LBB5_2
-; RV64I-NEXT:  # %bb.1:
-; RV64I-NEXT:    xor a2, a2, a1
-; RV64I-NEXT:  .LBB5_2:
-; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    neg a0, a0
+; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    xor a0, a0, a2
 ; RV64I-NEXT:    ret
   %a = select i1 %c, i64 %x, i64 0
   %b = xor i64 %a, %y