Skip to content

Commit 8905b1c

Browse files
authored
[RISCV] Efficiently lower (select %cond, andn (f, x), f) using zicond (#147369)
The following case is now optimized: (select c, (and f, ~x), f) -> (andn f, (czero_eqz x, c))
1 parent bed9fe7 commit 8905b1c

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
@@ -9075,18 +9075,51 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
90759075
if (isNullConstant(TrueV))
90769076
return DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV);
90779077

9078+
// Check to see if a given operation is a 'NOT', if so return the negated
9079+
// operand
9080+
auto getNotOperand = [](const SDValue &Op) -> std::optional<const SDValue> {
9081+
using namespace llvm::SDPatternMatch;
9082+
SDValue Xor;
9083+
if (sd_match(Op, m_OneUse(m_Not(m_Value(Xor))))) {
9084+
return Xor;
9085+
}
9086+
return std::nullopt;
9087+
};
90789088
// (select c, (and f, x), f) -> (or (and f, x), (czero_nez f, c))
9089+
// (select c, (and f, ~x), f) -> (andn f, (czero_eqz x, c))
90799090
if (TrueV.getOpcode() == ISD::AND &&
9080-
(TrueV.getOperand(0) == FalseV || TrueV.getOperand(1) == FalseV))
9091+
(TrueV.getOperand(0) == FalseV || TrueV.getOperand(1) == FalseV)) {
9092+
auto NotOperand = (TrueV.getOperand(0) == FalseV)
9093+
? getNotOperand(TrueV.getOperand(1))
9094+
: getNotOperand(TrueV.getOperand(0));
9095+
if (NotOperand) {
9096+
SDValue CMOV =
9097+
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, *NotOperand, CondV);
9098+
SDValue NOT = DAG.getNOT(DL, CMOV, VT);
9099+
return DAG.getNode(ISD::AND, DL, VT, FalseV, NOT);
9100+
}
90819101
return DAG.getNode(
90829102
ISD::OR, DL, VT, TrueV,
90839103
DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV));
9104+
}
9105+
90849106
// (select c, t, (and t, x)) -> (or (czero_eqz t, c), (and t, x))
9107+
// (select c, t, (and t, ~x)) -> (andn t, (czero_nez x, c))
90859108
if (FalseV.getOpcode() == ISD::AND &&
9086-
(FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV))
9109+
(FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV)) {
9110+
auto NotOperand = (FalseV.getOperand(0) == TrueV)
9111+
? getNotOperand(FalseV.getOperand(1))
9112+
: getNotOperand(FalseV.getOperand(0));
9113+
if (NotOperand) {
9114+
SDValue CMOV =
9115+
DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, *NotOperand, CondV);
9116+
SDValue NOT = DAG.getNOT(DL, CMOV, VT);
9117+
return DAG.getNode(ISD::AND, DL, VT, TrueV, NOT);
9118+
}
90879119
return DAG.getNode(
90889120
ISD::OR, DL, VT, FalseV,
90899121
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV));
9122+
}
90909123

90919124
// Try some other optimizations before falling back to generic lowering.
90929125
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)