Skip to content

Commit 7e7aaa5

Browse files
authored
[RISCV][GISel] Support G_ABS with Zbb. (#72939)
We can use neg+max or negw+max.
1 parent 171cac9 commit 7e7aaa5

File tree

4 files changed

+356
-96
lines changed

4 files changed

+356
-96
lines changed

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
242242
.widenScalarToNextPow2(0);
243243
}
244244

245-
getActionDefinitionsBuilder(G_ABS).lower();
245+
auto &AbsActions = getActionDefinitionsBuilder(G_ABS);
246+
if (ST.hasStdExtZbb())
247+
AbsActions.customFor({s32, sXLen}).minScalar(0, sXLen);
248+
AbsActions.lower();
246249

247250
auto &MinMaxActions =
248251
getActionDefinitionsBuilder({G_UMAX, G_UMIN, G_SMAX, G_SMIN});
@@ -356,6 +359,8 @@ bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
356359
default:
357360
// No idea what to do.
358361
return false;
362+
case TargetOpcode::G_ABS:
363+
return Helper.lowerAbsToMaxNeg(MI);
359364
case TargetOpcode::G_SHL:
360365
case TargetOpcode::G_ASHR:
361366
case TargetOpcode::G_LSHR:
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv32 -global-isel -verify-machineinstrs < %s \
3+
; RUN: | FileCheck %s --check-prefix=RV32I
4+
; RUN: llc -mtriple=riscv32 -global-isel -mattr=+zbb -verify-machineinstrs < %s \
5+
; RUN: | FileCheck %s --check-prefix=RV32ZBB
6+
; RUN: llc -mtriple=riscv64 -global-isel -verify-machineinstrs < %s \
7+
; RUN: | FileCheck %s --check-prefix=RV64I
8+
; RUN: llc -mtriple=riscv64 -global-isel -mattr=+zbb -verify-machineinstrs < %s \
9+
; RUN: | FileCheck %s --check-prefix=RV64ZBB
10+
11+
declare i8 @llvm.abs.i8(i8, i1 immarg)
12+
declare i16 @llvm.abs.i16(i16, i1 immarg)
13+
declare i32 @llvm.abs.i32(i32, i1 immarg)
14+
declare i64 @llvm.abs.i64(i64, i1 immarg)
15+
16+
define i8 @abs8(i8 %x) {
17+
; RV32I-LABEL: abs8:
18+
; RV32I: # %bb.0:
19+
; RV32I-NEXT: slli a1, a0, 24
20+
; RV32I-NEXT: srai a1, a1, 24
21+
; RV32I-NEXT: srai a1, a1, 7
22+
; RV32I-NEXT: add a0, a0, a1
23+
; RV32I-NEXT: xor a0, a0, a1
24+
; RV32I-NEXT: ret
25+
;
26+
; RV32ZBB-LABEL: abs8:
27+
; RV32ZBB: # %bb.0:
28+
; RV32ZBB-NEXT: slli a0, a0, 24
29+
; RV32ZBB-NEXT: srai a0, a0, 24
30+
; RV32ZBB-NEXT: neg a1, a0
31+
; RV32ZBB-NEXT: max a0, a0, a1
32+
; RV32ZBB-NEXT: ret
33+
;
34+
; RV64I-LABEL: abs8:
35+
; RV64I: # %bb.0:
36+
; RV64I-NEXT: slli a1, a0, 24
37+
; RV64I-NEXT: sraiw a1, a1, 24
38+
; RV64I-NEXT: sraiw a1, a1, 7
39+
; RV64I-NEXT: addw a0, a0, a1
40+
; RV64I-NEXT: xor a0, a0, a1
41+
; RV64I-NEXT: ret
42+
;
43+
; RV64ZBB-LABEL: abs8:
44+
; RV64ZBB: # %bb.0:
45+
; RV64ZBB-NEXT: slli a0, a0, 56
46+
; RV64ZBB-NEXT: srai a0, a0, 56
47+
; RV64ZBB-NEXT: neg a1, a0
48+
; RV64ZBB-NEXT: max a0, a0, a1
49+
; RV64ZBB-NEXT: ret
50+
%abs = tail call i8 @llvm.abs.i8(i8 %x, i1 true)
51+
ret i8 %abs
52+
}
53+
54+
define i16 @abs16(i16 %x) {
55+
; RV32I-LABEL: abs16:
56+
; RV32I: # %bb.0:
57+
; RV32I-NEXT: slli a1, a0, 16
58+
; RV32I-NEXT: srai a1, a1, 16
59+
; RV32I-NEXT: srai a1, a1, 15
60+
; RV32I-NEXT: add a0, a0, a1
61+
; RV32I-NEXT: xor a0, a0, a1
62+
; RV32I-NEXT: ret
63+
;
64+
; RV32ZBB-LABEL: abs16:
65+
; RV32ZBB: # %bb.0:
66+
; RV32ZBB-NEXT: slli a0, a0, 16
67+
; RV32ZBB-NEXT: srai a0, a0, 16
68+
; RV32ZBB-NEXT: neg a1, a0
69+
; RV32ZBB-NEXT: max a0, a0, a1
70+
; RV32ZBB-NEXT: ret
71+
;
72+
; RV64I-LABEL: abs16:
73+
; RV64I: # %bb.0:
74+
; RV64I-NEXT: slli a1, a0, 16
75+
; RV64I-NEXT: sraiw a1, a1, 16
76+
; RV64I-NEXT: sraiw a1, a1, 15
77+
; RV64I-NEXT: addw a0, a0, a1
78+
; RV64I-NEXT: xor a0, a0, a1
79+
; RV64I-NEXT: ret
80+
;
81+
; RV64ZBB-LABEL: abs16:
82+
; RV64ZBB: # %bb.0:
83+
; RV64ZBB-NEXT: slli a0, a0, 48
84+
; RV64ZBB-NEXT: srai a0, a0, 48
85+
; RV64ZBB-NEXT: neg a1, a0
86+
; RV64ZBB-NEXT: max a0, a0, a1
87+
; RV64ZBB-NEXT: ret
88+
%abs = tail call i16 @llvm.abs.i16(i16 %x, i1 true)
89+
ret i16 %abs
90+
}
91+
92+
define i32 @abs32(i32 %x) {
93+
; RV32I-LABEL: abs32:
94+
; RV32I: # %bb.0:
95+
; RV32I-NEXT: srai a1, a0, 31
96+
; RV32I-NEXT: add a0, a0, a1
97+
; RV32I-NEXT: xor a0, a0, a1
98+
; RV32I-NEXT: ret
99+
;
100+
; RV32ZBB-LABEL: abs32:
101+
; RV32ZBB: # %bb.0:
102+
; RV32ZBB-NEXT: neg a1, a0
103+
; RV32ZBB-NEXT: max a0, a0, a1
104+
; RV32ZBB-NEXT: ret
105+
;
106+
; RV64I-LABEL: abs32:
107+
; RV64I: # %bb.0:
108+
; RV64I-NEXT: sraiw a1, a0, 31
109+
; RV64I-NEXT: addw a0, a0, a1
110+
; RV64I-NEXT: xor a0, a0, a1
111+
; RV64I-NEXT: ret
112+
;
113+
; RV64ZBB-LABEL: abs32:
114+
; RV64ZBB: # %bb.0:
115+
; RV64ZBB-NEXT: negw a1, a0
116+
; RV64ZBB-NEXT: sext.w a0, a0
117+
; RV64ZBB-NEXT: max a0, a0, a1
118+
; RV64ZBB-NEXT: ret
119+
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
120+
ret i32 %abs
121+
}
122+
123+
define i64 @abs64(i64 %x) {
124+
; RV32I-LABEL: abs64:
125+
; RV32I: # %bb.0:
126+
; RV32I-NEXT: srai a2, a1, 31
127+
; RV32I-NEXT: add a0, a0, a2
128+
; RV32I-NEXT: sltu a3, a0, a2
129+
; RV32I-NEXT: add a1, a1, a2
130+
; RV32I-NEXT: add a1, a1, a3
131+
; RV32I-NEXT: xor a0, a0, a2
132+
; RV32I-NEXT: xor a1, a1, a2
133+
; RV32I-NEXT: ret
134+
;
135+
; RV32ZBB-LABEL: abs64:
136+
; RV32ZBB: # %bb.0:
137+
; RV32ZBB-NEXT: srai a2, a1, 31
138+
; RV32ZBB-NEXT: add a0, a0, a2
139+
; RV32ZBB-NEXT: sltu a3, a0, a2
140+
; RV32ZBB-NEXT: add a1, a1, a2
141+
; RV32ZBB-NEXT: add a1, a1, a3
142+
; RV32ZBB-NEXT: xor a0, a0, a2
143+
; RV32ZBB-NEXT: xor a1, a1, a2
144+
; RV32ZBB-NEXT: ret
145+
;
146+
; RV64I-LABEL: abs64:
147+
; RV64I: # %bb.0:
148+
; RV64I-NEXT: srai a1, a0, 63
149+
; RV64I-NEXT: add a0, a0, a1
150+
; RV64I-NEXT: xor a0, a0, a1
151+
; RV64I-NEXT: ret
152+
;
153+
; RV64ZBB-LABEL: abs64:
154+
; RV64ZBB: # %bb.0:
155+
; RV64ZBB-NEXT: neg a1, a0
156+
; RV64ZBB-NEXT: max a0, a0, a1
157+
; RV64ZBB-NEXT: ret
158+
%abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
159+
ret i64 %abs
160+
}

llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-abs-rv32.mir

Lines changed: 79 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2-
# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - | FileCheck %s
2+
# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - \
3+
# RUN: | FileCheck %s --check-prefix=RV32I
4+
# RUN: llc -mtriple=riscv32 -mattr=+zbb -run-pass=legalizer %s -o -\
5+
# RUN: | FileCheck %s --check-prefix=RV32ZBB
6+
37
---
48
name: abs_i8
59
body: |
610
bb.0.entry:
7-
; CHECK-LABEL: name: abs_i8
8-
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
9-
; CHECK-NEXT: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 8
10-
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
11-
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
12-
; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ASSERT_ZEXT]], [[C1]](s32)
13-
; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32)
14-
; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[C]](s32)
15-
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASSERT_ZEXT]], [[ASHR1]]
16-
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR1]]
17-
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
18-
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C2]]
19-
; CHECK-NEXT: $x10 = COPY [[AND]](s32)
20-
; CHECK-NEXT: PseudoRET implicit $x10
11+
; RV32I-LABEL: name: abs_i8
12+
; RV32I: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
13+
; RV32I-NEXT: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 8
14+
; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
15+
; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
16+
; RV32I-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ASSERT_ZEXT]], [[C1]](s32)
17+
; RV32I-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32)
18+
; RV32I-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[C]](s32)
19+
; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASSERT_ZEXT]], [[ASHR1]]
20+
; RV32I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR1]]
21+
; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
22+
; RV32I-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C2]]
23+
; RV32I-NEXT: $x10 = COPY [[AND]](s32)
24+
; RV32I-NEXT: PseudoRET implicit $x10
25+
;
26+
; RV32ZBB-LABEL: name: abs_i8
27+
; RV32ZBB: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
28+
; RV32ZBB-NEXT: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 8
29+
; RV32ZBB-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
30+
; RV32ZBB-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ASSERT_ZEXT]], [[C]](s32)
31+
; RV32ZBB-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
32+
; RV32ZBB-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
33+
; RV32ZBB-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C1]], [[ASHR]]
34+
; RV32ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[SUB]]
35+
; RV32ZBB-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
36+
; RV32ZBB-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[SMAX]], [[C2]]
37+
; RV32ZBB-NEXT: $x10 = COPY [[AND]](s32)
38+
; RV32ZBB-NEXT: PseudoRET implicit $x10
2139
%1:_(s32) = COPY $x10
2240
%2:_(s32) = G_ASSERT_ZEXT %1, 8
2341
%0:_(s8) = G_TRUNC %2(s32)
@@ -30,21 +48,36 @@ body: |
3048
name: abs_i16
3149
body: |
3250
bb.0.entry:
33-
; CHECK-LABEL: name: abs_i16
34-
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
35-
; CHECK-NEXT: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 16
36-
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
37-
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
38-
; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ASSERT_SEXT]], [[C1]](s32)
39-
; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32)
40-
; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[C]](s32)
41-
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASSERT_SEXT]], [[ASHR1]]
42-
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR1]]
43-
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
44-
; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[XOR]], [[C2]](s32)
45-
; CHECK-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C2]](s32)
46-
; CHECK-NEXT: $x10 = COPY [[ASHR2]](s32)
47-
; CHECK-NEXT: PseudoRET implicit $x10
51+
; RV32I-LABEL: name: abs_i16
52+
; RV32I: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
53+
; RV32I-NEXT: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 16
54+
; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
55+
; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
56+
; RV32I-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ASSERT_SEXT]], [[C1]](s32)
57+
; RV32I-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32)
58+
; RV32I-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[C]](s32)
59+
; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASSERT_SEXT]], [[ASHR1]]
60+
; RV32I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR1]]
61+
; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
62+
; RV32I-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[XOR]], [[C2]](s32)
63+
; RV32I-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C2]](s32)
64+
; RV32I-NEXT: $x10 = COPY [[ASHR2]](s32)
65+
; RV32I-NEXT: PseudoRET implicit $x10
66+
;
67+
; RV32ZBB-LABEL: name: abs_i16
68+
; RV32ZBB: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
69+
; RV32ZBB-NEXT: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 16
70+
; RV32ZBB-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
71+
; RV32ZBB-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ASSERT_SEXT]], [[C]](s32)
72+
; RV32ZBB-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
73+
; RV32ZBB-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
74+
; RV32ZBB-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C1]], [[ASHR]]
75+
; RV32ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[SUB]]
76+
; RV32ZBB-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
77+
; RV32ZBB-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[SMAX]], [[C2]](s32)
78+
; RV32ZBB-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C2]](s32)
79+
; RV32ZBB-NEXT: $x10 = COPY [[ASHR1]](s32)
80+
; RV32ZBB-NEXT: PseudoRET implicit $x10
4881
%1:_(s32) = COPY $x10
4982
%2:_(s32) = G_ASSERT_SEXT %1, 16
5083
%0:_(s16) = G_TRUNC %2(s32)
@@ -57,14 +90,22 @@ body: |
5790
name: abs_i32
5891
body: |
5992
bb.0.entry:
60-
; CHECK-LABEL: name: abs_i32
61-
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
62-
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
63-
; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C]](s32)
64-
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[ASHR]]
65-
; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR]]
66-
; CHECK-NEXT: $x10 = COPY [[XOR]](s32)
67-
; CHECK-NEXT: PseudoRET implicit $x10
93+
; RV32I-LABEL: name: abs_i32
94+
; RV32I: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
95+
; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
96+
; RV32I-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C]](s32)
97+
; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[ASHR]]
98+
; RV32I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR]]
99+
; RV32I-NEXT: $x10 = COPY [[XOR]](s32)
100+
; RV32I-NEXT: PseudoRET implicit $x10
101+
;
102+
; RV32ZBB-LABEL: name: abs_i32
103+
; RV32ZBB: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
104+
; RV32ZBB-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
105+
; RV32ZBB-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[COPY]]
106+
; RV32ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[COPY]], [[SUB]]
107+
; RV32ZBB-NEXT: $x10 = COPY [[SMAX]](s32)
108+
; RV32ZBB-NEXT: PseudoRET implicit $x10
68109
%0:_(s32) = COPY $x10
69110
%1:_(s32) = G_ABS %0
70111
$x10 = COPY %1(s32)

0 commit comments

Comments
 (0)