Skip to content

Commit 31c5ca9

Browse files
bababuckRyan Buchner
authored andcommitted
[RISCV] Efficiently lower select %cond, %constant, %variable using zicond extension
Provides the following lowerings, which reduces instruction count by 1 for rv64: (select c, c1, t) -> (add (czero_nez t - c1, c), c1) (select c, t, c1) -> (add (czero_eqz t - c1, c), c1)
1 parent 2a23721 commit 31c5ca9

File tree

3 files changed

+77
-43
lines changed

3 files changed

+77
-43
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9043,15 +9043,20 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
90439043

90449044
// (select c, c1, c2) -> (add (czero_nez c2 - c1, c), c1)
90459045
// (select c, c1, c2) -> (add (czero_eqz c1 - c2, c), c2)
9046-
if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
9047-
const APInt &TrueVal = TrueV->getAsAPIntVal();
9048-
const APInt &FalseVal = FalseV->getAsAPIntVal();
9046+
// (select c, c1, t) -> (add (czero_nez t - c1, c), c1)
9047+
// (select c, t, c1) -> (add (czero_eqz t - c1, c), c1)
9048+
if (isa<ConstantSDNode>(TrueV) || isa<ConstantSDNode>(FalseV)) {
9049+
bool BothAreConstant =
9050+
isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV);
90499051

90509052
// Prefer these over Zicond to avoid materializing an immediate:
90519053
// (select (x < 0), y, z) -> x >> (XLEN - 1) & (y - z) + z
90529054
// (select (x > -1), z, y) -> x >> (XLEN - 1) & (y - z) + z
90539055
if (CondV.getOpcode() == ISD::SETCC &&
9054-
CondV.getOperand(0).getValueType() == VT && CondV.hasOneUse()) {
9056+
CondV.getOperand(0).getValueType() == VT && CondV.hasOneUse() &&
9057+
BothAreConstant) {
9058+
const APInt &TrueVal = TrueV->getAsAPIntVal();
9059+
const APInt &FalseVal = FalseV->getAsAPIntVal();
90559060
ISD::CondCode CCVal = cast<CondCodeSDNode>(CondV.getOperand(2))->get();
90569061
if ((CCVal == ISD::SETLT && isNullConstant(CondV.getOperand(1))) ||
90579062
(CCVal == ISD::SETGT && isAllOnesConstant(CondV.getOperand(1)))) {
@@ -9073,19 +9078,36 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
90739078
}
90749079
}
90759080

9076-
const int TrueValCost = RISCVMatInt::getIntMatCost(
9077-
TrueVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
9078-
const int FalseValCost = RISCVMatInt::getIntMatCost(
9079-
FalseVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
9080-
bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
9081-
SDValue LHSVal = DAG.getConstant(
9082-
IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal, DL, VT);
9083-
SDValue RHSVal =
9084-
DAG.getConstant(IsCZERO_NEZ ? TrueVal : FalseVal, DL, VT);
9085-
SDValue CMOV =
9086-
DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9087-
DL, VT, LHSVal, CondV);
9088-
return DAG.getNode(ISD::ADD, DL, VT, CMOV, RHSVal);
9081+
bool IsCZERO_NEZ;
9082+
SDValue ConstVal, SubOp;
9083+
if (BothAreConstant) {
9084+
const APInt &TrueVal = TrueV->getAsAPIntVal();
9085+
const APInt &FalseVal = FalseV->getAsAPIntVal();
9086+
const int TrueValCost = RISCVMatInt::getIntMatCost(
9087+
TrueVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
9088+
const int FalseValCost = RISCVMatInt::getIntMatCost(
9089+
FalseVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
9090+
IsCZERO_NEZ = TrueValCost <= FalseValCost;
9091+
9092+
SubOp = DAG.getConstant(
9093+
IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal, DL, VT);
9094+
ConstVal = DAG.getConstant(IsCZERO_NEZ ? TrueVal : FalseVal, DL, VT);
9095+
} else {
9096+
IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
9097+
ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9098+
9099+
SDValue &RegV = IsCZERO_NEZ ? FalseV : TrueV;
9100+
SubOp = DAG.getNode(ISD::SUB, DL, VT, RegV, ConstVal);
9101+
}
9102+
// The one constant case is only efficient is the constant fits into
9103+
// `ADDI`
9104+
if (BothAreConstant ||
9105+
isInt<12>(dyn_cast<ConstantSDNode>(ConstVal)->getSExtValue())) {
9106+
SDValue CMOV =
9107+
DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9108+
DL, VT, SubOp, CondV);
9109+
return DAG.getNode(ISD::ADD, DL, VT, CMOV, ConstVal);
9110+
}
90899111
}
90909112

90919113
// (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))

llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,21 @@ define signext i32 @test6(i32 signext %x, i32 signext %z) {
173173
; NOSFB-NEXT: or a0, a0, a1
174174
; NOSFB-NEXT: ret
175175
;
176-
; SFB-LABEL: test6:
177-
; SFB: # %bb.0:
178-
; SFB-NEXT: li a2, -1
179-
; SFB-NEXT: beqz a1, .LBB5_2
180-
; SFB-NEXT: # %bb.1:
181-
; SFB-NEXT: mv a0, a2
182-
; SFB-NEXT: .LBB5_2:
183-
; SFB-NEXT: ret
176+
; NOZICOND-LABEL: test6:
177+
; NOZICOND: # %bb.0:
178+
; NOZICOND-NEXT: li a2, -1
179+
; NOZICOND-NEXT: beqz a1, .LBB5_2
180+
; NOZICOND-NEXT: # %bb.1:
181+
; NOZICOND-NEXT: mv a0, a2
182+
; NOZICOND-NEXT: .LBB5_2:
183+
; NOZICOND-NEXT: ret
184+
;
185+
; ZICOND-LABEL: test6:
186+
; ZICOND: # %bb.0:
187+
; ZICOND-NEXT: addi a0, a0, 1
188+
; ZICOND-NEXT: czero.nez a0, a0, a1
189+
; ZICOND-NEXT: addi a0, a0, -1
190+
; ZICOND-NEXT: ret
184191
%c = icmp eq i32 %z, 0
185192
%b = select i1 %c, i32 %x, i32 -1
186193
ret i32 %b
@@ -195,14 +202,21 @@ define signext i32 @test7(i32 signext %x, i32 signext %z) {
195202
; NOSFB-NEXT: or a0, a0, a1
196203
; NOSFB-NEXT: ret
197204
;
198-
; SFB-LABEL: test7:
199-
; SFB: # %bb.0:
200-
; SFB-NEXT: li a2, -1
201-
; SFB-NEXT: bnez a1, .LBB6_2
202-
; SFB-NEXT: # %bb.1:
203-
; SFB-NEXT: mv a0, a2
204-
; SFB-NEXT: .LBB6_2:
205-
; SFB-NEXT: ret
205+
; NOZICOND-LABEL: test7:
206+
; NOZICOND: # %bb.0:
207+
; NOZICOND-NEXT: li a2, -1
208+
; NOZICOND-NEXT: bnez a1, .LBB6_2
209+
; NOZICOND-NEXT: # %bb.1:
210+
; NOZICOND-NEXT: mv a0, a2
211+
; NOZICOND-NEXT: .LBB6_2:
212+
; NOZICOND-NEXT: ret
213+
;
214+
; ZICOND-LABEL: test7:
215+
; ZICOND: # %bb.0:
216+
; ZICOND-NEXT: addi a0, a0, 1
217+
; ZICOND-NEXT: czero.eqz a0, a0, a1
218+
; ZICOND-NEXT: addi a0, a0, -1
219+
; ZICOND-NEXT: ret
206220
%c = icmp eq i32 %z, 0
207221
%b = select i1 %c, i32 -1, i32 %x
208222
ret i32 %b

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,19 @@ define dso_local noundef i64 @select_imm_reg(i64 noundef %0, i64 noundef %1) loc
100100
; RV32ZICOND-LABEL: select_imm_reg:
101101
; RV32ZICOND: # %bb.0:
102102
; RV32ZICOND-NEXT: xori a0, a0, 2
103-
; RV32ZICOND-NEXT: or a1, a0, a1
104-
; RV32ZICOND-NEXT: li a0, 3
105-
; RV32ZICOND-NEXT: czero.eqz a2, a2, a1
106-
; RV32ZICOND-NEXT: czero.nez a0, a0, a1
107-
; RV32ZICOND-NEXT: or a0, a0, a2
108-
; RV32ZICOND-NEXT: czero.eqz a1, a3, a1
103+
; RV32ZICOND-NEXT: addi a2, a2, -3
104+
; RV32ZICOND-NEXT: or a0, a0, a1
105+
; RV32ZICOND-NEXT: czero.eqz a1, a3, a0
106+
; RV32ZICOND-NEXT: czero.eqz a0, a2, a0
107+
; RV32ZICOND-NEXT: addi a0, a0, 3
109108
; RV32ZICOND-NEXT: ret
110109
;
111110
; RV64ZICOND-LABEL: select_imm_reg:
112111
; RV64ZICOND: # %bb.0:
113112
; RV64ZICOND-NEXT: addi a0, a0, -2
114-
; RV64ZICOND-NEXT: li a2, 3
115-
; RV64ZICOND-NEXT: czero.eqz a1, a1, a0
116-
; RV64ZICOND-NEXT: czero.nez a0, a2, a0
117-
; RV64ZICOND-NEXT: or a0, a0, a1
113+
; RV64ZICOND-NEXT: addi a1, a1, -3
114+
; RV64ZICOND-NEXT: czero.eqz a0, a1, a0
115+
; RV64ZICOND-NEXT: addi a0, a0, 3
118116
; RV64ZICOND-NEXT: ret
119117
%3 = icmp eq i64 %0, 2
120118
%4 = select i1 %3, i64 3, i64 %1

0 commit comments

Comments
 (0)