From 37eb9c9632fb5e82827d1a0559f2279e9a9f1969 Mon Sep 17 00:00:00 2001 From: Zhijin Zeng Date: Sun, 28 Apr 2024 13:28:14 +0800 Subject: [PATCH] [RISC-V][ISel] Remove redundant czero.eqz like 'czero.eqz a0, a0, a0' (#90208) In RISC-V ISel, the instruction `czero.eqz a0, a0, a0` is meaningless. This patch does the following folds in ISel: ``` czero_eqz x, (setcc x, 0, ne) -> x czero_nez x, (setcc x, 0, eq) -> x ``` --------- Signed-off-by: Zhijin Zeng --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 22 ++-- llvm/test/CodeGen/RISCV/select.ll | 110 ++++++++++++++++++++ 2 files changed, 125 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 539aa35255450..3ab9e7d69105c 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16164,23 +16164,31 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, case ISD::SELECT: return performSELECTCombine(N, DAG, Subtarget); case RISCVISD::CZERO_EQZ: - case RISCVISD::CZERO_NEZ: + case RISCVISD::CZERO_NEZ: { + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); // czero_eq X, (xor Y, 1) -> czero_ne X, Y if Y is 0 or 1. // czero_ne X, (xor Y, 1) -> czero_eq X, Y if Y is 0 or 1. - if (N->getOperand(1).getOpcode() == ISD::XOR && - isOneConstant(N->getOperand(1).getOperand(1))) { - SDValue Cond = N->getOperand(1).getOperand(0); + if (RHS.getOpcode() == ISD::XOR && isOneConstant(RHS.getOperand(1))) { + SDValue Cond = RHS.getOperand(0); APInt Mask = APInt::getBitsSetFrom(Cond.getValueSizeInBits(), 1); if (DAG.MaskedValueIsZero(Cond, Mask)) { unsigned NewOpc = N->getOpcode() == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ; - return DAG.getNode(NewOpc, SDLoc(N), N->getValueType(0), - N->getOperand(0), Cond); + return DAG.getNode(NewOpc, SDLoc(N), N->getValueType(0), LHS, Cond); } } + // czero_eqz x, (setcc x, 0, ne) -> x + // czero_nez x, (setcc x, 0, eq) -> x + if (RHS.getOpcode() == ISD::SETCC && isNullConstant(RHS.getOperand(1)) && + cast(RHS.getOperand(2))->get() == + (N->getOpcode() == RISCVISD::CZERO_EQZ ? ISD::CondCode::SETNE + : ISD::CondCode::SETEQ) && + LHS == RHS.getOperand(0)) + return LHS; return SDValue(); - + } case RISCVISD::SELECT_CC: { // Transform SDValue LHS = N->getOperand(0); diff --git a/llvm/test/CodeGen/RISCV/select.ll b/llvm/test/CodeGen/RISCV/select.ll index e07e52091e9e7..ffbbe31412ed2 100644 --- a/llvm/test/CodeGen/RISCV/select.ll +++ b/llvm/test/CodeGen/RISCV/select.ll @@ -1858,3 +1858,113 @@ define i32 @select_cst6(i1 zeroext %cond) { %ret = select i1 %cond, i32 2049, i32 2047 ret i32 %ret } + +@select_redundant_czero_eqz_data = global i32 0, align 4 + +define void @select_redundant_czero_eqz1(ptr %0, ptr %1) { +; RV32IM-LABEL: select_redundant_czero_eqz1: +; RV32IM: # %bb.0: # %entry +; RV32IM-NEXT: bnez a0, .LBB49_2 +; RV32IM-NEXT: # %bb.1: +; RV32IM-NEXT: lui a0, %hi(select_redundant_czero_eqz_data) +; RV32IM-NEXT: addi a0, a0, %lo(select_redundant_czero_eqz_data) +; RV32IM-NEXT: .LBB49_2: # %entry +; RV32IM-NEXT: sw a0, 0(a1) +; RV32IM-NEXT: ret +; +; RV64IM-LABEL: select_redundant_czero_eqz1: +; RV64IM: # %bb.0: # %entry +; RV64IM-NEXT: bnez a0, .LBB49_2 +; RV64IM-NEXT: # %bb.1: +; RV64IM-NEXT: lui a0, %hi(select_redundant_czero_eqz_data) +; RV64IM-NEXT: addi a0, a0, %lo(select_redundant_czero_eqz_data) +; RV64IM-NEXT: .LBB49_2: # %entry +; RV64IM-NEXT: sd a0, 0(a1) +; RV64IM-NEXT: ret +; +; RV64IMXVTCONDOPS-LABEL: select_redundant_czero_eqz1: +; RV64IMXVTCONDOPS: # %bb.0: # %entry +; RV64IMXVTCONDOPS-NEXT: lui a2, %hi(select_redundant_czero_eqz_data) +; RV64IMXVTCONDOPS-NEXT: addi a2, a2, %lo(select_redundant_czero_eqz_data) +; RV64IMXVTCONDOPS-NEXT: vt.maskcn a2, a2, a0 +; RV64IMXVTCONDOPS-NEXT: or a0, a2, a0 +; RV64IMXVTCONDOPS-NEXT: sd a0, 0(a1) +; RV64IMXVTCONDOPS-NEXT: ret +; +; RV32IMZICOND-LABEL: select_redundant_czero_eqz1: +; RV32IMZICOND: # %bb.0: # %entry +; RV32IMZICOND-NEXT: lui a2, %hi(select_redundant_czero_eqz_data) +; RV32IMZICOND-NEXT: addi a2, a2, %lo(select_redundant_czero_eqz_data) +; RV32IMZICOND-NEXT: czero.nez a2, a2, a0 +; RV32IMZICOND-NEXT: or a0, a2, a0 +; RV32IMZICOND-NEXT: sw a0, 0(a1) +; RV32IMZICOND-NEXT: ret +; +; RV64IMZICOND-LABEL: select_redundant_czero_eqz1: +; RV64IMZICOND: # %bb.0: # %entry +; RV64IMZICOND-NEXT: lui a2, %hi(select_redundant_czero_eqz_data) +; RV64IMZICOND-NEXT: addi a2, a2, %lo(select_redundant_czero_eqz_data) +; RV64IMZICOND-NEXT: czero.nez a2, a2, a0 +; RV64IMZICOND-NEXT: or a0, a2, a0 +; RV64IMZICOND-NEXT: sd a0, 0(a1) +; RV64IMZICOND-NEXT: ret +entry: + %3 = icmp eq ptr %0, null + %4 = select i1 %3, ptr @select_redundant_czero_eqz_data, ptr %0 + store ptr %4, ptr %1, align 8 + ret void +} + +define void @select_redundant_czero_eqz2(ptr %0, ptr %1) { +; RV32IM-LABEL: select_redundant_czero_eqz2: +; RV32IM: # %bb.0: # %entry +; RV32IM-NEXT: bnez a0, .LBB50_2 +; RV32IM-NEXT: # %bb.1: # %entry +; RV32IM-NEXT: lui a0, %hi(select_redundant_czero_eqz_data) +; RV32IM-NEXT: addi a0, a0, %lo(select_redundant_czero_eqz_data) +; RV32IM-NEXT: .LBB50_2: # %entry +; RV32IM-NEXT: sw a0, 0(a1) +; RV32IM-NEXT: ret +; +; RV64IM-LABEL: select_redundant_czero_eqz2: +; RV64IM: # %bb.0: # %entry +; RV64IM-NEXT: bnez a0, .LBB50_2 +; RV64IM-NEXT: # %bb.1: # %entry +; RV64IM-NEXT: lui a0, %hi(select_redundant_czero_eqz_data) +; RV64IM-NEXT: addi a0, a0, %lo(select_redundant_czero_eqz_data) +; RV64IM-NEXT: .LBB50_2: # %entry +; RV64IM-NEXT: sd a0, 0(a1) +; RV64IM-NEXT: ret +; +; RV64IMXVTCONDOPS-LABEL: select_redundant_czero_eqz2: +; RV64IMXVTCONDOPS: # %bb.0: # %entry +; RV64IMXVTCONDOPS-NEXT: lui a2, %hi(select_redundant_czero_eqz_data) +; RV64IMXVTCONDOPS-NEXT: addi a2, a2, %lo(select_redundant_czero_eqz_data) +; RV64IMXVTCONDOPS-NEXT: vt.maskcn a2, a2, a0 +; RV64IMXVTCONDOPS-NEXT: or a0, a0, a2 +; RV64IMXVTCONDOPS-NEXT: sd a0, 0(a1) +; RV64IMXVTCONDOPS-NEXT: ret +; +; RV32IMZICOND-LABEL: select_redundant_czero_eqz2: +; RV32IMZICOND: # %bb.0: # %entry +; RV32IMZICOND-NEXT: lui a2, %hi(select_redundant_czero_eqz_data) +; RV32IMZICOND-NEXT: addi a2, a2, %lo(select_redundant_czero_eqz_data) +; RV32IMZICOND-NEXT: czero.nez a2, a2, a0 +; RV32IMZICOND-NEXT: or a0, a0, a2 +; RV32IMZICOND-NEXT: sw a0, 0(a1) +; RV32IMZICOND-NEXT: ret +; +; RV64IMZICOND-LABEL: select_redundant_czero_eqz2: +; RV64IMZICOND: # %bb.0: # %entry +; RV64IMZICOND-NEXT: lui a2, %hi(select_redundant_czero_eqz_data) +; RV64IMZICOND-NEXT: addi a2, a2, %lo(select_redundant_czero_eqz_data) +; RV64IMZICOND-NEXT: czero.nez a2, a2, a0 +; RV64IMZICOND-NEXT: or a0, a0, a2 +; RV64IMZICOND-NEXT: sd a0, 0(a1) +; RV64IMZICOND-NEXT: ret +entry: + %3 = icmp ne ptr %0, null + %4 = select i1 %3, ptr %0, ptr @select_redundant_czero_eqz_data + store ptr %4, ptr %1, align 8 + ret void +}