Skip to content

Commit a59e4ac

Browse files
authored
[RISCV] Lower SELECT's with one constant more efficiently using Zicond (#143581)
See #143580 for MR with the test commit. Performs the following transformations: (select c, c1, t) -> (add (czero_nez t - c1, c), c1) (select c, t, c1) -> (add (czero_eqz t - c1, c), c1) @mgudim
1 parent 4f8187c commit a59e4ac

File tree

3 files changed

+72
-38
lines changed

3 files changed

+72
-38
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9096,6 +9096,32 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
90969096
return DAG.getNode(ISD::ADD, DL, VT, CMOV, RHSVal);
90979097
}
90989098

9099+
// (select c, c1, t) -> (add (czero_nez t - c1, c), c1)
9100+
// (select c, t, c1) -> (add (czero_eqz t - c1, c), c1)
9101+
if (isa<ConstantSDNode>(TrueV) != isa<ConstantSDNode>(FalseV)) {
9102+
bool IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
9103+
SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9104+
SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9105+
int64_t RawConstVal = cast<ConstantSDNode>(ConstVal)->getSExtValue();
9106+
// Fall back to XORI if Const == -0x800
9107+
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+
// Efficient only if the constant and its negation fit into `ADDI`
9115+
// Prefer Add/Sub over Xor since can be compressed for small immediates
9116+
if (isInt<12>(RawConstVal)) {
9117+
SDValue SubOp = DAG.getNode(ISD::SUB, DL, VT, RegV, ConstVal);
9118+
SDValue CMOV =
9119+
DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9120+
DL, VT, SubOp, CondV);
9121+
return DAG.getNode(ISD::ADD, DL, VT, CMOV, ConstVal);
9122+
}
9123+
}
9124+
90999125
// (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
91009126
// Unless we have the short forward branch optimization.
91019127
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: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,18 @@ define i64 @select_imm_reg(i64 %t, i1 %cond) {
146146
; RV32ZICOND-LABEL: select_imm_reg:
147147
; RV32ZICOND: # %bb.0:
148148
; RV32ZICOND-NEXT: andi a2, a2, 1
149-
; RV32ZICOND-NEXT: li a3, 3
150-
; RV32ZICOND-NEXT: czero.nez a0, a0, a2
151-
; RV32ZICOND-NEXT: czero.eqz a3, a3, a2
152-
; RV32ZICOND-NEXT: or a0, a3, a0
149+
; RV32ZICOND-NEXT: addi a0, a0, -3
153150
; RV32ZICOND-NEXT: czero.nez a1, a1, a2
151+
; RV32ZICOND-NEXT: czero.nez a0, a0, a2
152+
; RV32ZICOND-NEXT: addi a0, a0, 3
154153
; RV32ZICOND-NEXT: ret
155154
;
156155
; RV64ZICOND-LABEL: select_imm_reg:
157156
; RV64ZICOND: # %bb.0:
158157
; RV64ZICOND-NEXT: andi a1, a1, 1
159-
; RV64ZICOND-NEXT: li a2, 3
158+
; RV64ZICOND-NEXT: addi a0, a0, -3
160159
; RV64ZICOND-NEXT: czero.nez a0, a0, a1
161-
; RV64ZICOND-NEXT: czero.eqz a1, a2, a1
162-
; RV64ZICOND-NEXT: or a0, a1, a0
160+
; RV64ZICOND-NEXT: addi a0, a0, 3
163161
; RV64ZICOND-NEXT: ret
164162
%4 = select i1 %cond, i64 3, i64 %t
165163
ret i64 %4
@@ -170,20 +168,18 @@ define i64 @select_reg_imm(i64 %t, i1 %cond) {
170168
; RV32ZICOND-LABEL: select_reg_imm:
171169
; RV32ZICOND: # %bb.0:
172170
; RV32ZICOND-NEXT: andi a2, a2, 1
173-
; RV32ZICOND-NEXT: li a3, 3
174-
; RV32ZICOND-NEXT: czero.nez a3, a3, a2
175-
; RV32ZICOND-NEXT: czero.eqz a0, a0, a2
176-
; RV32ZICOND-NEXT: or a0, a0, a3
171+
; RV32ZICOND-NEXT: addi a0, a0, -3
177172
; RV32ZICOND-NEXT: czero.eqz a1, a1, a2
173+
; RV32ZICOND-NEXT: czero.eqz a0, a0, a2
174+
; RV32ZICOND-NEXT: addi a0, a0, 3
178175
; RV32ZICOND-NEXT: ret
179176
;
180177
; RV64ZICOND-LABEL: select_reg_imm:
181178
; RV64ZICOND: # %bb.0:
182179
; RV64ZICOND-NEXT: andi a1, a1, 1
183-
; RV64ZICOND-NEXT: li a2, 3
184-
; RV64ZICOND-NEXT: czero.nez a2, a2, a1
180+
; RV64ZICOND-NEXT: addi a0, a0, -3
185181
; RV64ZICOND-NEXT: czero.eqz a0, a0, a1
186-
; RV64ZICOND-NEXT: or a0, a0, a2
182+
; RV64ZICOND-NEXT: addi a0, a0, 3
187183
; RV64ZICOND-NEXT: ret
188184
%4 = select i1 %cond, i64 %t, i64 3
189185
ret i64 %4
@@ -194,21 +190,19 @@ define i64 @select_imm_reg_neg_2048(i64 %t, i1 %cond) {
194190
; RV32ZICOND-LABEL: select_imm_reg_neg_2048:
195191
; RV32ZICOND: # %bb.0:
196192
; RV32ZICOND-NEXT: andi a2, a2, 1
197-
; RV32ZICOND-NEXT: li a3, -2048
193+
; RV32ZICOND-NEXT: xori a0, a0, -2048
194+
; RV32ZICOND-NEXT: neg a3, a2
198195
; RV32ZICOND-NEXT: czero.nez a0, a0, a2
199-
; RV32ZICOND-NEXT: czero.eqz a3, a3, a2
200-
; RV32ZICOND-NEXT: neg a2, a2
201-
; RV32ZICOND-NEXT: or a0, a3, a0
202-
; RV32ZICOND-NEXT: or a1, a2, a1
196+
; RV32ZICOND-NEXT: or a1, a3, a1
197+
; RV32ZICOND-NEXT: xori a0, a0, -2048
203198
; RV32ZICOND-NEXT: ret
204199
;
205200
; RV64ZICOND-LABEL: select_imm_reg_neg_2048:
206201
; RV64ZICOND: # %bb.0:
207202
; RV64ZICOND-NEXT: andi a1, a1, 1
208-
; RV64ZICOND-NEXT: li a2, -2048
203+
; RV64ZICOND-NEXT: xori a0, a0, -2048
209204
; RV64ZICOND-NEXT: czero.nez a0, a0, a1
210-
; RV64ZICOND-NEXT: czero.eqz a1, a2, a1
211-
; RV64ZICOND-NEXT: or a0, a1, a0
205+
; RV64ZICOND-NEXT: xori a0, a0, -2048
212206
; RV64ZICOND-NEXT: ret
213207
%4 = select i1 %cond, i64 -2048, i64 %t
214208
ret i64 %4

0 commit comments

Comments
 (0)