Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -4222,6 +4222,45 @@ return DAG.getNode(ISD::SUB, DL, VT, FalseV, CondV); } + // (select (and (x , 0x1) == 0), y, (z ^ y) ) -> (-(and (x , 0x1)) & z ) ^ y + // (select (and (x , 0x1) == 0), y, (z | y) ) -> (-(and (x , 0x1)) & z ) | y + if (isNullConstant(RHS) && CCVal == ISD::SETEQ && + LHS.getOpcode() == ISD::AND && isOneConstant(LHS.getOperand(1))) { + SDValue Src1, Src2; + // true if FalseV is XOR or OR operator and one of its operands + // is equal to Op1 + // ( a , a op b) || ( b , a op b) + auto isOrXorPattern = [&]() { + if ((FalseV.getOpcode() == ISD::XOR || FalseV.getOpcode() == ISD::OR) && + (FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV)) { + Src1 = + FalseV.getOperand(0) == TrueV ? FalseV.getOperand(1) : FalseV.getOperand(0); + Src2 = TrueV; + return true; + } + return false; + }; + + if (isOrXorPattern()) { + SDValue Neg; + unsigned int CmpSz = LHS.getSimpleValueType().getSizeInBits(); + // we need mask of all zeros or ones with same size of the other + // operands. + if (CmpSz > VT.getSizeInBits()) + Neg = DAG.getNode(ISD::TRUNCATE, DL, VT, LHS); + else if (CmpSz < VT.getSizeInBits()) + Neg = DAG.getNode(ISD::AND, DL, VT, + DAG.getNode(ISD::ANY_EXTEND, DL, VT, LHS), + DAG.getConstant(1, DL, VT)); + else + Neg = LHS; + SDValue Mask = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), + Neg); // -(and (x, 0x1)) + SDValue And = DAG.getNode(ISD::AND, DL, VT, Mask, Src1); // Mask & z + return DAG.getNode(FalseV.getOpcode(), DL, VT, And, Src2); // And Op y + } + } + translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG); // 1 < x ? x : 1 -> 0 < x ? x : 1 if (isOneConstant(LHS) && Index: llvm/test/CodeGen/RISCV/select.ll =================================================================== --- llvm/test/CodeGen/RISCV/select.ll +++ llvm/test/CodeGen/RISCV/select.ll @@ -1,16 +1,23 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s | FileCheck %s -; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s | FileCheck --check-prefixes=CHECK,RV32 %s +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s | FileCheck --check-prefixes=CHECK,RV64 %s define i16 @select_xor_1(i16 %A, i8 %cond) { -; CHECK-LABEL: select_xor_1: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: andi a1, a1, 1 -; CHECK-NEXT: beqz a1, .LBB0_2 -; CHECK-NEXT: # %bb.1: # %entry -; CHECK-NEXT: xori a0, a0, 43 -; CHECK-NEXT: .LBB0_2: # %entry -; CHECK-NEXT: ret +; RV32-LABEL: select_xor_1: +; RV32: # %bb.0: # %entry +; RV32-NEXT: andi a1, a1, 1 +; RV32-NEXT: neg a1, a1 +; RV32-NEXT: andi a1, a1, 43 +; RV32-NEXT: xor a0, a1, a0 +; RV32-NEXT: ret +; +; RV64-LABEL: select_xor_1: +; RV64: # %bb.0: # %entry +; RV64-NEXT: andi a1, a1, 1 +; RV64-NEXT: negw a1, a1 +; RV64-NEXT: andi a1, a1, 43 +; RV64-NEXT: xor a0, a1, a0 +; RV64-NEXT: ret entry: %and = and i8 %cond, 1 %cmp10 = icmp eq i8 %and, 0 @@ -42,10 +49,9 @@ ; CHECK-LABEL: select_xor_2: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: andi a2, a2, 1 -; CHECK-NEXT: beqz a2, .LBB2_2 -; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: neg a2, a2 +; CHECK-NEXT: and a1, a2, a1 ; CHECK-NEXT: xor a0, a1, a0 -; CHECK-NEXT: .LBB2_2: # %entry ; CHECK-NEXT: ret entry: %and = and i8 %cond, 1 @@ -78,10 +84,9 @@ ; CHECK-LABEL: select_or: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: andi a2, a2, 1 -; CHECK-NEXT: beqz a2, .LBB4_2 -; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: neg a2, a2 +; CHECK-NEXT: and a1, a2, a1 ; CHECK-NEXT: or a0, a1, a0 -; CHECK-NEXT: .LBB4_2: # %entry ; CHECK-NEXT: ret entry: %and = and i8 %cond, 1 @@ -114,10 +119,9 @@ ; CHECK-LABEL: select_or_1: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: andi a2, a2, 1 -; CHECK-NEXT: beqz a2, .LBB6_2 -; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: neg a2, a2 +; CHECK-NEXT: and a1, a2, a1 ; CHECK-NEXT: or a0, a1, a0 -; CHECK-NEXT: .LBB6_2: # %entry ; CHECK-NEXT: ret entry: %and = and i32 %cond, 1