Skip to content

Commit 5b9a5e2

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) For the special case of c1 == -2048 (select c, -2048, t) -> (xor (czero_nez (xor t, -2048), c), -2048) (select c, t, -2048) -> (xor (czero_eqz (xor t, -2048), c), -2048)
1 parent 7d64e5c commit 5b9a5e2

File tree

3 files changed

+69
-34
lines changed

3 files changed

+69
-34
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9088,6 +9088,31 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
90889088
return DAG.getNode(ISD::ADD, DL, VT, CMOV, RHSVal);
90899089
}
90909090

9091+
// (select c, c1, t) -> (add (czero_nez t - c1, c), c1)
9092+
// (select c, t, c1) -> (add (czero_eqz t - c1, c), c1)
9093+
if (isa<ConstantSDNode>(TrueV) != isa<ConstantSDNode>(FalseV)) {
9094+
bool IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
9095+
SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9096+
SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9097+
int64_t RawConstVal = cast<ConstantSDNode>(ConstVal)->getSExtValue();
9098+
// Efficient only if the constant and its negation fit into `ADDI`
9099+
if (RawConstVal != INT64_MIN && std::abs(RawConstVal) < 0x800) {
9100+
SDValue SubOp = DAG.getNode(ISD::SUB, DL, VT, RegV, ConstVal);
9101+
SDValue CMOV =
9102+
DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9103+
DL, VT, SubOp, CondV);
9104+
return DAG.getNode(ISD::ADD, DL, VT, CMOV, ConstVal);
9105+
}
9106+
// Can use XORI if Const == -0x800
9107+
else if (RawConstVal == -0x800) {
9108+
SDValue XorOp = DAG.getNode(ISD::XOR, DL, VT, RegV, ConstVal);
9109+
SDValue CMOV =
9110+
DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9111+
DL, VT, XorOp, CondV);
9112+
return DAG.getNode(ISD::XOR, DL, VT, CMOV, ConstVal);
9113+
}
9114+
}
9115+
90919116
// (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
90929117
// Unless we have the short forward branch optimization.
90939118
if (!Subtarget.hasConditionalMoveFusion())

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: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,19 @@ define i64 @select_imm_reg(i64 %0, i64 %1) {
104104
; RV32ZICOND-LABEL: select_imm_reg:
105105
; RV32ZICOND: # %bb.0:
106106
; RV32ZICOND-NEXT: xori a0, a0, 2
107-
; RV32ZICOND-NEXT: or a1, a0, a1
108-
; RV32ZICOND-NEXT: li a0, 3
109-
; RV32ZICOND-NEXT: czero.eqz a2, a2, a1
110-
; RV32ZICOND-NEXT: czero.nez a0, a0, a1
111-
; RV32ZICOND-NEXT: or a0, a0, a2
112-
; RV32ZICOND-NEXT: czero.eqz a1, a3, a1
107+
; RV32ZICOND-NEXT: addi a2, a2, -3
108+
; RV32ZICOND-NEXT: or a0, a0, a1
109+
; RV32ZICOND-NEXT: czero.eqz a1, a3, a0
110+
; RV32ZICOND-NEXT: czero.eqz a0, a2, a0
111+
; RV32ZICOND-NEXT: addi a0, a0, 3
113112
; RV32ZICOND-NEXT: ret
114113
;
115114
; RV64ZICOND-LABEL: select_imm_reg:
116115
; RV64ZICOND: # %bb.0:
117116
; RV64ZICOND-NEXT: addi a0, a0, -2
118-
; RV64ZICOND-NEXT: li a2, 3
119-
; RV64ZICOND-NEXT: czero.eqz a1, a1, a0
120-
; RV64ZICOND-NEXT: czero.nez a0, a2, a0
121-
; RV64ZICOND-NEXT: or a0, a0, a1
117+
; RV64ZICOND-NEXT: addi a1, a1, -3
118+
; RV64ZICOND-NEXT: czero.eqz a0, a1, a0
119+
; RV64ZICOND-NEXT: addi a0, a0, 3
122120
; RV64ZICOND-NEXT: ret
123121
%3 = icmp eq i64 %0, 2
124122
%4 = select i1 %3, i64 3, i64 %1
@@ -130,23 +128,21 @@ define i64 @select_imm_reg_2048(i64 %0, i64 %1) {
130128
; RV32ZICOND-LABEL: select_imm_reg_2048:
131129
; RV32ZICOND: # %bb.0:
132130
; RV32ZICOND-NEXT: xori a0, a0, 2
133-
; RV32ZICOND-NEXT: li a4, -2048
131+
; RV32ZICOND-NEXT: xori a2, a2, -2048
134132
; RV32ZICOND-NEXT: or a0, a0, a1
135133
; RV32ZICOND-NEXT: seqz a1, a0
136-
; RV32ZICOND-NEXT: czero.eqz a2, a2, a0
137-
; RV32ZICOND-NEXT: czero.nez a0, a4, a0
138-
; RV32ZICOND-NEXT: or a0, a0, a2
134+
; RV32ZICOND-NEXT: czero.eqz a0, a2, a0
139135
; RV32ZICOND-NEXT: neg a1, a1
140136
; RV32ZICOND-NEXT: or a1, a1, a3
137+
; RV32ZICOND-NEXT: xori a0, a0, -2048
141138
; RV32ZICOND-NEXT: ret
142139
;
143140
; RV64ZICOND-LABEL: select_imm_reg_2048:
144141
; RV64ZICOND: # %bb.0:
145142
; RV64ZICOND-NEXT: addi a0, a0, -2
146-
; RV64ZICOND-NEXT: li a2, -2048
147-
; RV64ZICOND-NEXT: czero.eqz a1, a1, a0
148-
; RV64ZICOND-NEXT: czero.nez a0, a2, a0
149-
; RV64ZICOND-NEXT: or a0, a0, a1
143+
; RV64ZICOND-NEXT: xori a1, a1, -2048
144+
; RV64ZICOND-NEXT: czero.eqz a0, a1, a0
145+
; RV64ZICOND-NEXT: xori a0, a0, -2048
150146
; RV64ZICOND-NEXT: ret
151147
%3 = icmp eq i64 %0, 2
152148
%4 = select i1 %3, i64 -2048, i64 %1

0 commit comments

Comments
 (0)