Skip to content

Commit 638865c

Browse files
committed
[RISCV][GlobalISel] Legalize multiplication
Legalize multiplication with the +m, +zmmul extensions and without extensions. With extensions, we test for (s7, s8, s16, s32, s48, s64, s96) on rv32 and (s8, s15, s32, s64, s72, s128, s192) on rv64. Without extensions, test (s7, s8, s16, s32) on rv32 and (s8, s15, s16, s32, s64) on rv64. Does not yet work for the type which is 2 times XLen without extensions. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D157416
1 parent 7026a0c commit 638865c

File tree

5 files changed

+710
-0
lines changed

5 files changed

+710
-0
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ using namespace llvm;
2222
RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
2323
const unsigned XLen = ST.getXLen();
2424
const LLT XLenLLT = LLT::scalar(XLen);
25+
const LLT DoubleXLenLLT = LLT::scalar(2 * XLen);
2526
const LLT p0 = LLT::pointer(0, XLen);
2627

2728
using namespace TargetOpcode;
@@ -92,5 +93,25 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
9293
getActionDefinitionsBuilder(G_GLOBAL_VALUE)
9394
.legalFor({p0});
9495

96+
if (ST.hasStdExtM() || ST.hasStdExtZmmul()) {
97+
getActionDefinitionsBuilder(G_MUL)
98+
.legalFor({XLenLLT})
99+
.widenScalarToNextPow2(0)
100+
.clampScalar(0, XLenLLT, XLenLLT);
101+
102+
// clang-format off
103+
getActionDefinitionsBuilder({G_SMULH, G_UMULH})
104+
.legalFor({XLenLLT})
105+
.lower();
106+
// clang-format on
107+
} else {
108+
getActionDefinitionsBuilder(G_MUL)
109+
.libcallFor({XLenLLT, DoubleXLenLLT})
110+
.widenScalarToNextPow2(0)
111+
.clampScalar(0, XLenLLT, DoubleXLenLLT);
112+
113+
getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({XLenLLT});
114+
}
115+
95116
getLegacyLegalizerInfo().computeTables();
96117
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -mattr=+m -mtriple=riscv32 -run-pass=legalizer %s -o - \
3+
# RUN: | FileCheck %s
4+
# RUN: llc -mattr=+zmmul -mtriple=riscv32 -run-pass=legalizer %s -o - \
5+
# RUN: | FileCheck %s
6+
---
7+
name: mul_i7
8+
body: |
9+
bb.0.entry:
10+
; CHECK-LABEL: name: mul_i7
11+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
12+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
13+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
14+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
15+
; CHECK-NEXT: PseudoRET implicit $x10
16+
%0:_(s32) = COPY $x10
17+
%1:_(s32) = COPY $x11
18+
%2:_(s7) = G_TRUNC %0(s32)
19+
%3:_(s7) = G_TRUNC %1(s32)
20+
%4:_(s7) = G_MUL %2, %3
21+
%5:_(s32) = G_ANYEXT %4(s7)
22+
$x10 = COPY %5(s32)
23+
PseudoRET implicit $x10
24+
25+
...
26+
---
27+
name: mul_i8
28+
body: |
29+
bb.0.entry:
30+
; CHECK-LABEL: name: mul_i8
31+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
32+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
33+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
34+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
35+
; CHECK-NEXT: PseudoRET implicit $x10
36+
%0:_(s32) = COPY $x10
37+
%1:_(s32) = COPY $x11
38+
%2:_(s8) = G_TRUNC %0(s32)
39+
%3:_(s8) = G_TRUNC %1(s32)
40+
%4:_(s8) = G_MUL %2, %3
41+
%5:_(s32) = G_ANYEXT %4(s8)
42+
$x10 = COPY %5(s32)
43+
PseudoRET implicit $x10
44+
45+
...
46+
---
47+
name: mul_i16
48+
body: |
49+
bb.0.entry:
50+
; CHECK-LABEL: name: mul_i16
51+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
52+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
53+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
54+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
55+
; CHECK-NEXT: PseudoRET implicit $x10
56+
%0:_(s32) = COPY $x10
57+
%1:_(s32) = COPY $x11
58+
%2:_(s16) = G_TRUNC %0(s32)
59+
%3:_(s16) = G_TRUNC %1(s32)
60+
%4:_(s16) = G_MUL %2, %3
61+
%5:_(s32) = G_ANYEXT %4(s16)
62+
$x10 = COPY %5(s32)
63+
PseudoRET implicit $x10
64+
65+
...
66+
---
67+
name: mul_i32
68+
body: |
69+
bb.0.entry:
70+
; CHECK-LABEL: name: mul_i32
71+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
72+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
73+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
74+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
75+
; CHECK-NEXT: PseudoRET implicit $x10
76+
%0:_(s32) = COPY $x10
77+
%1:_(s32) = COPY $x11
78+
%2:_(s32) = G_MUL %0, %1
79+
$x10 = COPY %2(s32)
80+
PseudoRET implicit $x10
81+
82+
...
83+
---
84+
name: mul_i48
85+
body: |
86+
bb.0.entry:
87+
; CHECK-LABEL: name: mul_i48
88+
; CHECK: %xhi:_(s32) = COPY $x10
89+
; CHECK-NEXT: %xlo:_(s32) = COPY $x11
90+
; CHECK-NEXT: %yhi:_(s32) = COPY $x12
91+
; CHECK-NEXT: %ylo:_(s32) = COPY $x13
92+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL %xhi, %yhi
93+
; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL %xlo, %yhi
94+
; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL %xhi, %ylo
95+
; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %xhi, %yhi
96+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]]
97+
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]]
98+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
99+
; CHECK-NEXT: $x11 = COPY [[ADD1]](s32)
100+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
101+
%xhi:_(s32) = COPY $x10
102+
%xlo:_(s32) = COPY $x11
103+
%yhi:_(s32) = COPY $x12
104+
%ylo:_(s32) = COPY $x13
105+
%x0:_(s64) = G_MERGE_VALUES %xhi(s32), %xlo(s32)
106+
%y0:_(s64) = G_MERGE_VALUES %yhi(s32), %ylo(s32)
107+
%x:_(s48) = G_TRUNC %x0(s64)
108+
%y:_(s48) = G_TRUNC %y0(s64)
109+
%z:_(s48) = G_MUL %x, %y
110+
%z0:_(s64) = G_ANYEXT %z(s48)
111+
%zhi:_(s32), %zlo:_(s32) = G_UNMERGE_VALUES %z0(s64)
112+
$x10 = COPY %zhi(s32)
113+
$x11 = COPY %zlo(s32)
114+
PseudoRET implicit $x10, implicit $x11
115+
116+
...
117+
---
118+
name: mul_i64
119+
body: |
120+
bb.0.entry:
121+
; CHECK-LABEL: name: mul_i64
122+
; CHECK: %hi1:_(s32) = COPY $x10
123+
; CHECK-NEXT: %lo1:_(s32) = COPY $x11
124+
; CHECK-NEXT: %hi2:_(s32) = COPY $x12
125+
; CHECK-NEXT: %lo2:_(s32) = COPY $x13
126+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL %hi1, %hi2
127+
; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL %lo1, %hi2
128+
; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL %hi1, %lo2
129+
; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %hi1, %hi2
130+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]]
131+
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]]
132+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
133+
; CHECK-NEXT: $x11 = COPY [[ADD1]](s32)
134+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
135+
%hi1:_(s32) = COPY $x10
136+
%lo1:_(s32) = COPY $x11
137+
%hi2:_(s32) = COPY $x12
138+
%lo2:_(s32) = COPY $x13
139+
%x1:_(s64) = G_MERGE_VALUES %hi1(s32), %lo1(s32)
140+
%x2:_(s64) = G_MERGE_VALUES %hi2(s32), %lo2(s32)
141+
%y:_(s64) = G_MUL %x1, %x2
142+
%hiy:_(s32), %loy:_(s32) = G_UNMERGE_VALUES %y(s64)
143+
$x10 = COPY %hiy(s32)
144+
$x11 = COPY %loy(s32)
145+
PseudoRET implicit $x10, implicit $x11
146+
147+
...
148+
---
149+
name: mul_i96
150+
body: |
151+
bb.0.entry:
152+
; CHECK-LABEL: name: mul_i96
153+
; CHECK: %hi1:_(s32) = COPY $x10
154+
; CHECK-NEXT: %mid1:_(s32) = COPY $x11
155+
; CHECK-NEXT: %lo1:_(s32) = COPY $x12
156+
; CHECK-NEXT: %hi2:_(s32) = COPY $x13
157+
; CHECK-NEXT: %mid2:_(s32) = COPY $x14
158+
; CHECK-NEXT: %lo2:_(s32) = COPY $x15
159+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL %hi1, %hi2
160+
; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL %mid1, %hi2
161+
; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL %hi1, %mid2
162+
; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %hi1, %hi2
163+
; CHECK-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s32) = G_UADDO [[MUL1]], [[MUL2]]
164+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
165+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[UADDO1]], [[C]]
166+
; CHECK-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s32) = G_UADDO [[UADDO]], [[UMULH]]
167+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
168+
; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[UADDO3]], [[C1]]
169+
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[AND]], [[AND1]]
170+
; CHECK-NEXT: [[MUL3:%[0-9]+]]:_(s32) = G_MUL %lo1, %hi2
171+
; CHECK-NEXT: [[MUL4:%[0-9]+]]:_(s32) = G_MUL %mid1, %mid2
172+
; CHECK-NEXT: [[MUL5:%[0-9]+]]:_(s32) = G_MUL %hi1, %lo2
173+
; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH %mid1, %hi2
174+
; CHECK-NEXT: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH %hi1, %mid2
175+
; CHECK-NEXT: [[UADDO4:%[0-9]+]]:_(s32), [[UADDO5:%[0-9]+]]:_(s32) = G_UADDO [[MUL3]], [[MUL4]]
176+
; CHECK-NEXT: [[UADDO6:%[0-9]+]]:_(s32), [[UADDO7:%[0-9]+]]:_(s32) = G_UADDO [[UADDO4]], [[MUL5]]
177+
; CHECK-NEXT: [[UADDO8:%[0-9]+]]:_(s32), [[UADDO9:%[0-9]+]]:_(s32) = G_UADDO [[UADDO6]], [[UMULH1]]
178+
; CHECK-NEXT: [[UADDO10:%[0-9]+]]:_(s32), [[UADDO11:%[0-9]+]]:_(s32) = G_UADDO [[UADDO8]], [[UMULH2]]
179+
; CHECK-NEXT: [[UADDO12:%[0-9]+]]:_(s32), [[UADDO13:%[0-9]+]]:_(s32) = G_UADDO [[UADDO10]], [[ADD]]
180+
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
181+
; CHECK-NEXT: $x11 = COPY [[UADDO2]](s32)
182+
; CHECK-NEXT: $x12 = COPY [[UADDO12]](s32)
183+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12
184+
%hi1:_(s32) = COPY $x10
185+
%mid1:_(s32) = COPY $x11
186+
%lo1:_(s32) = COPY $x12
187+
%hi2:_(s32) = COPY $x13
188+
%mid2:_(s32) = COPY $x14
189+
%lo2:_(s32) = COPY $x15
190+
%x1:_(s96) = G_MERGE_VALUES %hi1(s32), %mid1(s32), %lo1(s32)
191+
%x2:_(s96) = G_MERGE_VALUES %hi2(s32), %mid2(s32), %lo2(s32)
192+
%y:_(s96) = G_MUL %x1, %x2
193+
%hi:_(s32), %mid:_(s32), %lo:_(s32) = G_UNMERGE_VALUES %y(s96)
194+
$x10 = COPY %hi(s32)
195+
$x11 = COPY %mid(s32)
196+
$x12 = COPY %lo(s32)
197+
PseudoRET implicit $x10, implicit $x11, implicit $x12
198+
199+
...
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - \
3+
# RUN: | FileCheck %s
4+
---
5+
name: mul_i7
6+
body: |
7+
bb.0.entry:
8+
; CHECK-LABEL: name: mul_i7
9+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
10+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
11+
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
12+
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
13+
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
14+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
15+
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
16+
; CHECK-NEXT: PseudoRET implicit $x10
17+
%0:_(s32) = COPY $x10
18+
%1:_(s32) = COPY $x11
19+
%2:_(s7) = G_TRUNC %0(s32)
20+
%3:_(s7) = G_TRUNC %1(s32)
21+
%4:_(s7) = G_MUL %2, %3
22+
%5:_(s32) = G_ANYEXT %4(s7)
23+
$x10 = COPY %5(s32)
24+
PseudoRET implicit $x10
25+
26+
...
27+
---
28+
name: mul_i8
29+
body: |
30+
bb.0.entry:
31+
; CHECK-LABEL: name: mul_i8
32+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
33+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
34+
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
35+
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
36+
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
37+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
38+
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
39+
; CHECK-NEXT: PseudoRET implicit $x10
40+
%0:_(s32) = COPY $x10
41+
%1:_(s32) = COPY $x11
42+
%2:_(s8) = G_TRUNC %0(s32)
43+
%3:_(s8) = G_TRUNC %1(s32)
44+
%4:_(s8) = G_MUL %2, %3
45+
%5:_(s32) = G_ANYEXT %4(s8)
46+
$x10 = COPY %5(s32)
47+
PseudoRET implicit $x10
48+
49+
...
50+
---
51+
name: mul_i16
52+
body: |
53+
bb.0.entry:
54+
; CHECK-LABEL: name: mul_i16
55+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
56+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
57+
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
58+
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
59+
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
60+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
61+
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
62+
; CHECK-NEXT: PseudoRET implicit $x10
63+
%0:_(s32) = COPY $x10
64+
%1:_(s32) = COPY $x11
65+
%2:_(s16) = G_TRUNC %0(s32)
66+
%3:_(s16) = G_TRUNC %1(s32)
67+
%4:_(s16) = G_MUL %2, %3
68+
%5:_(s32) = G_ANYEXT %4(s16)
69+
$x10 = COPY %5(s32)
70+
PseudoRET implicit $x10
71+
72+
...
73+
---
74+
name: mul_i32
75+
body: |
76+
bb.0.entry:
77+
; CHECK-LABEL: name: mul_i32
78+
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
79+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
80+
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
81+
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
82+
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
83+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
84+
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
85+
; CHECK-NEXT: PseudoRET implicit $x10
86+
%0:_(s32) = COPY $x10
87+
%1:_(s32) = COPY $x11
88+
%2:_(s32) = G_MUL %0, %1
89+
$x10 = COPY %2(s32)
90+
PseudoRET implicit $x10
91+
92+
...
93+
---
94+
name: mul_i64
95+
body: |
96+
bb.0.entry:
97+
; CHECK-LABEL: name: mul_i64
98+
; CHECK: %hi1:_(s32) = COPY $x10
99+
; CHECK-NEXT: %lo1:_(s32) = COPY $x11
100+
; CHECK-NEXT: %hi2:_(s32) = COPY $x12
101+
; CHECK-NEXT: %lo2:_(s32) = COPY $x13
102+
; CHECK-NEXT: $x10 = COPY %hi1(s32)
103+
; CHECK-NEXT: $x11 = COPY %lo1(s32)
104+
; CHECK-NEXT: $x12 = COPY %hi2(s32)
105+
; CHECK-NEXT: $x13 = COPY %lo2(s32)
106+
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__muldi3, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit-def $x10, implicit-def $x11
107+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
108+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
109+
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
110+
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
111+
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
112+
%hi1:_(s32) = COPY $x10
113+
%lo1:_(s32) = COPY $x11
114+
%hi2:_(s32) = COPY $x12
115+
%lo2:_(s32) = COPY $x13
116+
%x1:_(s64) = G_MERGE_VALUES %hi1(s32), %lo1(s32)
117+
%x2:_(s64) = G_MERGE_VALUES %hi2(s32), %lo2(s32)
118+
%y:_(s64) = G_MUL %x1, %x2
119+
%hiy:_(s32), %loy:_(s32) = G_UNMERGE_VALUES %y(s64)
120+
$x10 = COPY %hiy(s32)
121+
$x11 = COPY %loy(s32)
122+
PseudoRET implicit $x10, implicit $x11
123+
124+
...

0 commit comments

Comments
 (0)