Skip to content

Commit f5031ab

Browse files
committed
[RISCV] Efficiently lower (select %cond, andn (f, x), f) using zicond extension
The following case is now optimized: (select c, (and f, ~x), f) -> (andn f, (czero_eqz x, c))
1 parent 463b3cb commit f5031ab

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9064,18 +9064,51 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
90649064
if (isNullConstant(TrueV))
90659065
return DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV);
90669066

9067+
// Check to see if a given operation is a 'NOT', if so return the negated
9068+
// operand
9069+
auto getNotOperand = [](const SDValue &Op) -> std::optional<const SDValue> {
9070+
using namespace llvm::SDPatternMatch;
9071+
SDValue Xor;
9072+
if (sd_match(Op, m_OneUse(m_Not(m_Value(Xor))))) {
9073+
return Xor;
9074+
}
9075+
return std::nullopt;
9076+
};
90679077
// (select c, (and f, x), f) -> (or (and f, x), (czero_nez f, c))
9078+
// (select c, (and f, ~x), f) -> (andn f, (czero_eqz x, c))
90689079
if (TrueV.getOpcode() == ISD::AND &&
9069-
(TrueV.getOperand(0) == FalseV || TrueV.getOperand(1) == FalseV))
9080+
(TrueV.getOperand(0) == FalseV || TrueV.getOperand(1) == FalseV)) {
9081+
auto NotOperand = (TrueV.getOperand(0) == FalseV)
9082+
? getNotOperand(TrueV.getOperand(1))
9083+
: getNotOperand(TrueV.getOperand(0));
9084+
if (NotOperand) {
9085+
SDValue CMOV =
9086+
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, *NotOperand, CondV);
9087+
SDValue NOT = DAG.getNOT(DL, CMOV, VT);
9088+
return DAG.getNode(ISD::AND, DL, VT, FalseV, NOT);
9089+
}
90709090
return DAG.getNode(
90719091
ISD::OR, DL, VT, TrueV,
90729092
DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV));
9093+
}
9094+
90739095
// (select c, t, (and t, x)) -> (or (czero_eqz t, c), (and t, x))
9096+
// (select c, t, (and t, ~x)) -> (andn t, (czero_nez x, c))
90749097
if (FalseV.getOpcode() == ISD::AND &&
9075-
(FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV))
9098+
(FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV)) {
9099+
auto NotOperand = (FalseV.getOperand(0) == TrueV)
9100+
? getNotOperand(FalseV.getOperand(1))
9101+
: getNotOperand(FalseV.getOperand(0));
9102+
if (NotOperand) {
9103+
SDValue CMOV =
9104+
DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, *NotOperand, CondV);
9105+
SDValue NOT = DAG.getNOT(DL, CMOV, VT);
9106+
return DAG.getNode(ISD::AND, DL, VT, TrueV, NOT);
9107+
}
90769108
return DAG.getNode(
90779109
ISD::OR, DL, VT, FalseV,
90789110
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV));
9111+
}
90799112

90809113
// Try some other optimizations before falling back to generic lowering.
90819114
if (SDValue V = combineSelectToBinOp(Op.getNode(), DAG, Subtarget))

llvm/test/CodeGen/RISCV/zicond-opts.ll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,8 @@ define i64 @test_inv_and_nez(i64 %f, i64 %x, i1 %cond) {
233233
; RV64ZICOND-LABEL: test_inv_and_nez:
234234
; RV64ZICOND: # %bb.0:
235235
; RV64ZICOND-NEXT: andi a2, a2, 1
236-
; RV64ZICOND-NEXT: andn a1, a0, a1
237-
; RV64ZICOND-NEXT: czero.nez a0, a0, a2
238-
; RV64ZICOND-NEXT: or a0, a1, a0
236+
; RV64ZICOND-NEXT: czero.eqz a1, a1, a2
237+
; RV64ZICOND-NEXT: andn a0, a0, a1
239238
; RV64ZICOND-NEXT: ret
240239
%5 = xor i64 %x, -1
241240
%6 = select i1 %cond, i64 %5, i64 -1
@@ -258,9 +257,8 @@ define i64 @test_inv_and_eqz(i64 %f, i64 %x, i1 %cond) {
258257
; RV64ZICOND-LABEL: test_inv_and_eqz:
259258
; RV64ZICOND: # %bb.0:
260259
; RV64ZICOND-NEXT: andi a2, a2, 1
261-
; RV64ZICOND-NEXT: andn a1, a0, a1
262-
; RV64ZICOND-NEXT: czero.eqz a0, a0, a2
263-
; RV64ZICOND-NEXT: or a0, a1, a0
260+
; RV64ZICOND-NEXT: czero.nez a1, a1, a2
261+
; RV64ZICOND-NEXT: andn a0, a0, a1
264262
; RV64ZICOND-NEXT: ret
265263
%5 = xor i64 %x, -1
266264
%6 = select i1 %cond, i64 -1, i64 %5

0 commit comments

Comments
 (0)