diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 8c3279517527e..a872f7112365e 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16726,10 +16726,6 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, DAG.getConstant(0, DL, XLenVT), CC); } -// Replace (seteq (i64 (and X, 0xffffffff)), C1) with -// (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from -// bit 31. Same for setne. C1' may be cheaper to materialize and the sext_inreg -// can become a sext.w instead of a shift pair. static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget) { @@ -16749,20 +16745,36 @@ static SDValue performSETCCCombine(SDNode *N, combineVectorSizedSetCCEquality(VT, N0, N1, Cond, dl, DAG, Subtarget)) return V; - // (X & -4096) == 0 -> (X >> 12) == 0 if the AND constant can't use ANDI. if (DCI.isAfterLegalizeDAG() && isNullConstant(N1) && N0.getOpcode() == ISD::AND && N0.hasOneUse() && isa(N0.getOperand(1))) { const APInt &AndRHSC = cast(N0.getOperand(1))->getAPIntValue(); + // (X & -(1 << C)) == 0 -> (X >> C) == 0 if the AND constant can't use ANDI. if (!isInt<12>(AndRHSC.getSExtValue()) && AndRHSC.isNegatedPowerOf2()) { unsigned ShiftBits = AndRHSC.countr_zero(); - SDValue Shift = DAG.getNode(ISD::SRL, dl, VT, N0.getOperand(0), - DAG.getConstant(ShiftBits, dl, VT)); + SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, N0.getOperand(0), + DAG.getConstant(ShiftBits, dl, OpVT)); + return DAG.getSetCC(dl, VT, Shift, N1, Cond); + } + + // Similar to above but handling the lower 32 bits by using srliw. + // FIXME: Handle the case where N1 is non-zero. + if (OpVT == MVT::i64 && AndRHSC.getZExtValue() <= 0xffffffff && + isPowerOf2_32(-uint32_t(AndRHSC.getZExtValue()))) { + unsigned ShiftBits = llvm::countr_zero(AndRHSC.getZExtValue()); + SDValue And = DAG.getNode(ISD::AND, dl, OpVT, N0.getOperand(0), + DAG.getConstant(0xffffffff, dl, OpVT)); + SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, And, + DAG.getConstant(ShiftBits, dl, OpVT)); return DAG.getSetCC(dl, VT, Shift, N1, Cond); } } + // Replace (seteq (i64 (and X, 0xffffffff)), C1) with + // (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from + // bit 31. Same for setne. C1' may be cheaper to materialize and the + // sext_inreg can become a sext.w instead of a shift pair. if (OpVT != MVT::i64 || !Subtarget.is64Bit()) return SDValue(); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 23f5a848137c4..4b6870554ab60 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1698,8 +1698,6 @@ let Predicates = [IsRV32] in { def : Pat<(i32 (setlt (i32 GPR:$rs1), 0)), (SRLI GPR:$rs1, 31)>; // compressible } let Predicates = [IsRV64] in { -def : Pat<(i64 (seteq (i64 (and GPR:$rs1, 0x0000000080000000)), 0)), - (XORI (i64 (SRLIW GPR:$rs1, 31)), 1)>; def : Pat<(i64 (setlt (i64 GPR:$rs1), 0)), (SRLI GPR:$rs1, 63)>; // compressible def : Pat<(i64 (setlt (sext_inreg GPR:$rs1, i32), 0)), (SRLIW GPR:$rs1, 31)>; } diff --git a/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll b/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll index b16672d3c4a16..c39aedc341acc 100644 --- a/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll +++ b/llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll @@ -64,3 +64,37 @@ define i1 @test4(i64 %x) { %b = icmp eq i64 %a, 0 ret i1 %b } + +define i1 @test5(i64 %x) { +; RV32-LABEL: test5: +; RV32: # %bb.0: +; RV32-NEXT: srli a0, a0, 29 +; RV32-NEXT: seqz a0, a0 +; RV32-NEXT: ret +; +; RV64-LABEL: test5: +; RV64: # %bb.0: +; RV64-NEXT: srliw a0, a0, 29 +; RV64-NEXT: seqz a0, a0 +; RV64-NEXT: ret + %a = and i64 %x, u0xE0000000 + %b = icmp eq i64 %a, 0 + ret i1 %b +} + +define i1 @test6(i64 %x) { +; RV32-LABEL: test6: +; RV32: # %bb.0: +; RV32-NEXT: srli a0, a0, 29 +; RV32-NEXT: snez a0, a0 +; RV32-NEXT: ret +; +; RV64-LABEL: test6: +; RV64: # %bb.0: +; RV64-NEXT: srliw a0, a0, 29 +; RV64-NEXT: snez a0, a0 +; RV64-NEXT: ret + %a = and i64 %x, u0xE0000000 + %b = icmp ne i64 %a, 0 + ret i1 %b +} diff --git a/llvm/test/CodeGen/RISCV/bittest.ll b/llvm/test/CodeGen/RISCV/bittest.ll index 40e3168d08b27..5d40d8f2d860d 100644 --- a/llvm/test/CodeGen/RISCV/bittest.ll +++ b/llvm/test/CodeGen/RISCV/bittest.ll @@ -188,13 +188,13 @@ define i64 @bittest_31_i64(i64 %a) nounwind { ; RV64ZBS-LABEL: bittest_31_i64: ; RV64ZBS: # %bb.0: ; RV64ZBS-NEXT: srliw a0, a0, 31 -; RV64ZBS-NEXT: xori a0, a0, 1 +; RV64ZBS-NEXT: seqz a0, a0 ; RV64ZBS-NEXT: ret ; ; RV64XTHEADBS-LABEL: bittest_31_i64: ; RV64XTHEADBS: # %bb.0: ; RV64XTHEADBS-NEXT: srliw a0, a0, 31 -; RV64XTHEADBS-NEXT: xori a0, a0, 1 +; RV64XTHEADBS-NEXT: seqz a0, a0 ; RV64XTHEADBS-NEXT: ret %shr = lshr i64 %a, 31 %not = xor i64 %shr, -1 @@ -3518,7 +3518,7 @@ define i32 @bittest_31_andeq0_i64(i64 %x) { ; RV64-LABEL: bittest_31_andeq0_i64: ; RV64: # %bb.0: ; RV64-NEXT: srliw a0, a0, 31 -; RV64-NEXT: xori a0, a0, 1 +; RV64-NEXT: seqz a0, a0 ; RV64-NEXT: ret %and = and i64 %x, 2147483648 %cmp = icmp eq i64 %and, 0