Skip to content

Commit 70c4709

Browse files
pfusiktopperc
andcommitted
[RISCV] Select and/or/xor with some constants to Zbb ANDN/ORN/XNOR
(and X, (C<<12|0xfff)) -> (ANDN X, ~C<<12) (or X, (C<<12|0xfff)) -> (ORN X, ~C<<12) (xor X, (C<<12|0xfff)) -> (XNOR X, ~C<<12) Saves an `ADDI HI, -1` instruction. Co-authored-by: Craig Topper <[email protected]>
1 parent 7fe62f2 commit 70c4709

File tree

5 files changed

+79
-110
lines changed

5 files changed

+79
-110
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,6 +3236,18 @@ bool RISCVDAGToDAGISel::selectSHXADD_UWOp(SDValue N, unsigned ShAmt,
32363236
return false;
32373237
}
32383238

3239+
bool RISCVDAGToDAGISel::selectSImm32fff(SDValue N, SDValue &Val) {
3240+
if (!isa<ConstantSDNode>(N))
3241+
return false;
3242+
3243+
int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
3244+
if (!(isInt<32>(Imm) && (Imm & 0xfff) == 0xfff && Imm != -1))
3245+
return false;
3246+
3247+
Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), ~Imm, *Subtarget);
3248+
return true;
3249+
}
3250+
32393251
static bool vectorPseudoHasAllNBitUsers(SDNode *User, unsigned UserOpNo,
32403252
unsigned Bits,
32413253
const TargetInstrInfo *TII) {

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
119119
return selectSHXADD_UWOp(N, ShAmt, Val);
120120
}
121121

122+
bool selectSImm32fff(SDValue N, SDValue &Val);
123+
122124
bool hasAllNBitUsers(SDNode *Node, unsigned Bits,
123125
const unsigned Depth = 0) const;
124126
bool hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 8); }

llvm/lib/Target/RISCV/RISCVInstrInfoZb.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,10 +475,16 @@ def : InstAlias<"zext.h $rd, $rs", (PACKW GPR:$rd, GPR:$rs, X0)>;
475475
// Codegen patterns
476476
//===----------------------------------------------------------------------===//
477477

478+
def simm32fff : ComplexPattern<XLenVT, 1, "selectSImm32fff", [], [], 0>;
479+
478480
let Predicates = [HasStdExtZbbOrZbkb] in {
479481
def : Pat<(XLenVT (and GPR:$rs1, (not GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
480482
def : Pat<(XLenVT (or GPR:$rs1, (not GPR:$rs2))), (ORN GPR:$rs1, GPR:$rs2)>;
481483
def : Pat<(XLenVT (xor GPR:$rs1, (not GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
484+
485+
def : Pat<(XLenVT (and GPR:$rs1, simm32fff:$rs2)), (ANDN GPR:$rs1, simm32fff:$rs2)>;
486+
def : Pat<(XLenVT (or GPR:$rs1, simm32fff:$rs2)), (ORN GPR:$rs1, simm32fff:$rs2)>;
487+
def : Pat<(XLenVT (xor GPR:$rs1, simm32fff:$rs2)), (XNOR GPR:$rs1, simm32fff:$rs2)>;
482488
} // Predicates = [HasStdExtZbbOrZbkb]
483489

484490
let Predicates = [HasStdExtZbbOrZbkb] in {

llvm/test/CodeGen/RISCV/pr84653_pr85190.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ define i1 @pr84653(i32 %x) {
2121
; CHECK-ZBB: # %bb.0:
2222
; CHECK-ZBB-NEXT: sext.w a1, a0
2323
; CHECK-ZBB-NEXT: lui a2, 524288
24-
; CHECK-ZBB-NEXT: addi a2, a2, -1
25-
; CHECK-ZBB-NEXT: xor a0, a0, a2
24+
; CHECK-ZBB-NEXT: xnor a0, a0, a2
2625
; CHECK-ZBB-NEXT: sext.w a0, a0
2726
; CHECK-ZBB-NEXT: max a0, a0, zero
2827
; CHECK-ZBB-NEXT: slt a0, a0, a1
@@ -82,8 +81,7 @@ define i1 @select_to_or(i32 %x) {
8281
; CHECK-ZBB: # %bb.0:
8382
; CHECK-ZBB-NEXT: sext.w a1, a0
8483
; CHECK-ZBB-NEXT: lui a2, 524288
85-
; CHECK-ZBB-NEXT: addi a2, a2, -1
86-
; CHECK-ZBB-NEXT: xor a0, a0, a2
84+
; CHECK-ZBB-NEXT: xnor a0, a0, a2
8785
; CHECK-ZBB-NEXT: sext.w a0, a0
8886
; CHECK-ZBB-NEXT: min a0, a0, zero
8987
; CHECK-ZBB-NEXT: slt a0, a0, a1

llvm/test/CodeGen/RISCV/zbb-logic-neg-imm.ll

Lines changed: 57 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -5,109 +5,77 @@
55
; RUN: | FileCheck %s --check-prefixes=CHECK,RV64
66

77
define i32 @and0xabcdefff(i32 %x) {
8-
; RV32-LABEL: and0xabcdefff:
9-
; RV32: # %bb.0:
10-
; RV32-NEXT: lui a1, 703711
11-
; RV32-NEXT: addi a1, a1, -1
12-
; RV32-NEXT: and a0, a0, a1
13-
; RV32-NEXT: ret
14-
;
15-
; RV64-LABEL: and0xabcdefff:
16-
; RV64: # %bb.0:
17-
; RV64-NEXT: lui a1, 703711
18-
; RV64-NEXT: addiw a1, a1, -1
19-
; RV64-NEXT: and a0, a0, a1
20-
; RV64-NEXT: ret
8+
; CHECK-LABEL: and0xabcdefff:
9+
; CHECK: # %bb.0:
10+
; CHECK-NEXT: lui a1, 344865
11+
; CHECK-NEXT: andn a0, a0, a1
12+
; CHECK-NEXT: ret
2113
%and = and i32 %x, -1412567041
2214
ret i32 %and
2315
}
2416

2517
define i32 @orlow13(i32 %x) {
26-
; RV32-LABEL: orlow13:
27-
; RV32: # %bb.0:
28-
; RV32-NEXT: lui a1, 2
29-
; RV32-NEXT: addi a1, a1, -1
30-
; RV32-NEXT: or a0, a0, a1
31-
; RV32-NEXT: ret
32-
;
33-
; RV64-LABEL: orlow13:
34-
; RV64: # %bb.0:
35-
; RV64-NEXT: lui a1, 2
36-
; RV64-NEXT: addiw a1, a1, -1
37-
; RV64-NEXT: or a0, a0, a1
38-
; RV64-NEXT: ret
18+
; CHECK-LABEL: orlow13:
19+
; CHECK: # %bb.0:
20+
; CHECK-NEXT: lui a1, 1048574
21+
; CHECK-NEXT: orn a0, a0, a1
22+
; CHECK-NEXT: ret
3923
%or = or i32 %x, 8191
4024
ret i32 %or
4125
}
4226

4327
define i64 @orlow24(i64 %x) {
4428
; RV32-LABEL: orlow24:
4529
; RV32: # %bb.0:
46-
; RV32-NEXT: lui a2, 4096
47-
; RV32-NEXT: addi a2, a2, -1
48-
; RV32-NEXT: or a0, a0, a2
30+
; RV32-NEXT: lui a2, 1044480
31+
; RV32-NEXT: orn a0, a0, a2
4932
; RV32-NEXT: ret
5033
;
5134
; RV64-LABEL: orlow24:
5235
; RV64: # %bb.0:
53-
; RV64-NEXT: lui a1, 4096
54-
; RV64-NEXT: addiw a1, a1, -1
55-
; RV64-NEXT: or a0, a0, a1
36+
; RV64-NEXT: lui a1, 1044480
37+
; RV64-NEXT: orn a0, a0, a1
5638
; RV64-NEXT: ret
5739
%or = or i64 %x, 16777215
5840
ret i64 %or
5941
}
6042

6143
define i32 @xorlow16(i32 %x) {
62-
; RV32-LABEL: xorlow16:
63-
; RV32: # %bb.0:
64-
; RV32-NEXT: lui a1, 16
65-
; RV32-NEXT: addi a1, a1, -1
66-
; RV32-NEXT: xor a0, a0, a1
67-
; RV32-NEXT: ret
68-
;
69-
; RV64-LABEL: xorlow16:
70-
; RV64: # %bb.0:
71-
; RV64-NEXT: lui a1, 16
72-
; RV64-NEXT: addiw a1, a1, -1
73-
; RV64-NEXT: xor a0, a0, a1
74-
; RV64-NEXT: ret
44+
; CHECK-LABEL: xorlow16:
45+
; CHECK: # %bb.0:
46+
; CHECK-NEXT: lui a1, 1048560
47+
; CHECK-NEXT: xnor a0, a0, a1
48+
; CHECK-NEXT: ret
7549
%xor = xor i32 %x, 65535
7650
ret i32 %xor
7751
}
7852

7953
define i32 @xorlow31(i32 %x) {
80-
; RV32-LABEL: xorlow31:
81-
; RV32: # %bb.0:
82-
; RV32-NEXT: lui a1, 524288
83-
; RV32-NEXT: addi a1, a1, -1
84-
; RV32-NEXT: xor a0, a0, a1
85-
; RV32-NEXT: ret
86-
;
87-
; RV64-LABEL: xorlow31:
88-
; RV64: # %bb.0:
89-
; RV64-NEXT: lui a1, 524288
90-
; RV64-NEXT: addiw a1, a1, -1
91-
; RV64-NEXT: xor a0, a0, a1
92-
; RV64-NEXT: ret
54+
; CHECK-LABEL: xorlow31:
55+
; CHECK: # %bb.0:
56+
; CHECK-NEXT: lui a1, 524288
57+
; CHECK-NEXT: xnor a0, a0, a1
58+
; CHECK-NEXT: ret
9359
%xor = xor i32 %x, 2147483647
9460
ret i32 %xor
9561
}
9662

9763
define i32 @oraddlow16(i32 %x) {
9864
; RV32-LABEL: oraddlow16:
9965
; RV32: # %bb.0:
66+
; RV32-NEXT: lui a1, 1048560
67+
; RV32-NEXT: orn a0, a0, a1
10068
; RV32-NEXT: lui a1, 16
10169
; RV32-NEXT: addi a1, a1, -1
102-
; RV32-NEXT: or a0, a0, a1
10370
; RV32-NEXT: add a0, a0, a1
10471
; RV32-NEXT: ret
10572
;
10673
; RV64-LABEL: oraddlow16:
10774
; RV64: # %bb.0:
75+
; RV64-NEXT: lui a1, 1048560
76+
; RV64-NEXT: orn a0, a0, a1
10877
; RV64-NEXT: lui a1, 16
10978
; RV64-NEXT: addi a1, a1, -1
110-
; RV64-NEXT: or a0, a0, a1
11179
; RV64-NEXT: addw a0, a0, a1
11280
; RV64-NEXT: ret
11381
%or = or i32 %x, 65535
@@ -121,15 +89,17 @@ define i32 @addorlow16(i32 %x) {
12189
; RV32-NEXT: lui a1, 16
12290
; RV32-NEXT: addi a1, a1, -1
12391
; RV32-NEXT: add a0, a0, a1
124-
; RV32-NEXT: or a0, a0, a1
92+
; RV32-NEXT: lui a1, 1048560
93+
; RV32-NEXT: orn a0, a0, a1
12594
; RV32-NEXT: ret
12695
;
12796
; RV64-LABEL: addorlow16:
12897
; RV64: # %bb.0:
12998
; RV64-NEXT: lui a1, 16
130-
; RV64-NEXT: addiw a1, a1, -1
99+
; RV64-NEXT: addi a1, a1, -1
131100
; RV64-NEXT: addw a0, a0, a1
132-
; RV64-NEXT: or a0, a0, a1
101+
; RV64-NEXT: lui a1, 1048560
102+
; RV64-NEXT: orn a0, a0, a1
133103
; RV64-NEXT: ret
134104
%add = add nsw i32 %x, 65535
135105
%or = or i32 %add, 65535
@@ -160,8 +130,7 @@ define void @orarray100(ptr %a) {
160130
; RV32: # %bb.0: # %entry
161131
; RV32-NEXT: li a1, 0
162132
; RV32-NEXT: li a2, 0
163-
; RV32-NEXT: lui a3, 16
164-
; RV32-NEXT: addi a3, a3, -1
133+
; RV32-NEXT: lui a3, 1048560
165134
; RV32-NEXT: .LBB8_1: # %for.body
166135
; RV32-NEXT: # =>This Inner Loop Header: Depth=1
167136
; RV32-NEXT: slli a4, a1, 2
@@ -171,7 +140,7 @@ define void @orarray100(ptr %a) {
171140
; RV32-NEXT: seqz a6, a1
172141
; RV32-NEXT: add a2, a2, a6
173142
; RV32-NEXT: xori a6, a1, 100
174-
; RV32-NEXT: or a5, a5, a3
143+
; RV32-NEXT: orn a5, a5, a3
175144
; RV32-NEXT: or a6, a6, a2
176145
; RV32-NEXT: sw a5, 0(a4)
177146
; RV32-NEXT: bnez a6, .LBB8_1
@@ -181,12 +150,11 @@ define void @orarray100(ptr %a) {
181150
; RV64-LABEL: orarray100:
182151
; RV64: # %bb.0: # %entry
183152
; RV64-NEXT: addi a1, a0, 400
184-
; RV64-NEXT: lui a2, 16
185-
; RV64-NEXT: addi a2, a2, -1
153+
; RV64-NEXT: lui a2, 1048560
186154
; RV64-NEXT: .LBB8_1: # %for.body
187155
; RV64-NEXT: # =>This Inner Loop Header: Depth=1
188156
; RV64-NEXT: lw a3, 0(a0)
189-
; RV64-NEXT: or a3, a3, a2
157+
; RV64-NEXT: orn a3, a3, a2
190158
; RV64-NEXT: sw a3, 0(a0)
191159
; RV64-NEXT: addi a0, a0, 4
192160
; RV64-NEXT: bne a0, a1, .LBB8_1
@@ -212,17 +180,16 @@ for.body:
212180
define void @orarray3(ptr %a) {
213181
; CHECK-LABEL: orarray3:
214182
; CHECK: # %bb.0:
215-
; CHECK-NEXT: lui a1, 16
216-
; CHECK-NEXT: lw a2, 0(a0)
217-
; CHECK-NEXT: lw a3, 4(a0)
218-
; CHECK-NEXT: lw a4, 8(a0)
219-
; CHECK-NEXT: addi a1, a1, -1
220-
; CHECK-NEXT: or a2, a2, a1
221-
; CHECK-NEXT: or a3, a3, a1
222-
; CHECK-NEXT: or a1, a4, a1
223-
; CHECK-NEXT: sw a2, 0(a0)
224-
; CHECK-NEXT: sw a3, 4(a0)
225-
; CHECK-NEXT: sw a1, 8(a0)
183+
; CHECK-NEXT: lw a1, 0(a0)
184+
; CHECK-NEXT: lw a2, 4(a0)
185+
; CHECK-NEXT: lw a3, 8(a0)
186+
; CHECK-NEXT: lui a4, 1048560
187+
; CHECK-NEXT: orn a1, a1, a4
188+
; CHECK-NEXT: orn a2, a2, a4
189+
; CHECK-NEXT: orn a3, a3, a4
190+
; CHECK-NEXT: sw a1, 0(a0)
191+
; CHECK-NEXT: sw a2, 4(a0)
192+
; CHECK-NEXT: sw a3, 8(a0)
226193
; CHECK-NEXT: ret
227194
%1 = load i32, ptr %a, align 4
228195
%or = or i32 %1, 65535
@@ -273,37 +240,21 @@ define i32 @compl(i32 %x) {
273240
}
274241

275242
define i32 @orlow12(i32 %x) {
276-
; RV32-LABEL: orlow12:
277-
; RV32: # %bb.0:
278-
; RV32-NEXT: lui a1, 1
279-
; RV32-NEXT: addi a1, a1, -1
280-
; RV32-NEXT: or a0, a0, a1
281-
; RV32-NEXT: ret
282-
;
283-
; RV64-LABEL: orlow12:
284-
; RV64: # %bb.0:
285-
; RV64-NEXT: lui a1, 1
286-
; RV64-NEXT: addiw a1, a1, -1
287-
; RV64-NEXT: or a0, a0, a1
288-
; RV64-NEXT: ret
243+
; CHECK-LABEL: orlow12:
244+
; CHECK: # %bb.0:
245+
; CHECK-NEXT: lui a1, 1048575
246+
; CHECK-NEXT: orn a0, a0, a1
247+
; CHECK-NEXT: ret
289248
%or = or i32 %x, 4095
290249
ret i32 %or
291250
}
292251

293252
define i32 @xorlow12(i32 %x) {
294-
; RV32-LABEL: xorlow12:
295-
; RV32: # %bb.0:
296-
; RV32-NEXT: lui a1, 1
297-
; RV32-NEXT: addi a1, a1, -1
298-
; RV32-NEXT: xor a0, a0, a1
299-
; RV32-NEXT: ret
300-
;
301-
; RV64-LABEL: xorlow12:
302-
; RV64: # %bb.0:
303-
; RV64-NEXT: lui a1, 1
304-
; RV64-NEXT: addiw a1, a1, -1
305-
; RV64-NEXT: xor a0, a0, a1
306-
; RV64-NEXT: ret
253+
; CHECK-LABEL: xorlow12:
254+
; CHECK: # %bb.0:
255+
; CHECK-NEXT: lui a1, 1048575
256+
; CHECK-NEXT: xnor a0, a0, a1
257+
; CHECK-NEXT: ret
307258
%xor = xor i32 %x, 4095
308259
ret i32 %xor
309260
}

0 commit comments

Comments
 (0)