Skip to content

Commit

Permalink
[RISCV][GlobalISel] Legalize multiplication
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nitinjohnraj committed Aug 17, 2023
1 parent 7026a0c commit 638865c
Show file tree
Hide file tree
Showing 5 changed files with 710 additions and 0 deletions.
21 changes: 21 additions & 0 deletions llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using namespace llvm;
RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
const unsigned XLen = ST.getXLen();
const LLT XLenLLT = LLT::scalar(XLen);
const LLT DoubleXLenLLT = LLT::scalar(2 * XLen);
const LLT p0 = LLT::pointer(0, XLen);

using namespace TargetOpcode;
Expand Down Expand Up @@ -92,5 +93,25 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
getActionDefinitionsBuilder(G_GLOBAL_VALUE)
.legalFor({p0});

if (ST.hasStdExtM() || ST.hasStdExtZmmul()) {
getActionDefinitionsBuilder(G_MUL)
.legalFor({XLenLLT})
.widenScalarToNextPow2(0)
.clampScalar(0, XLenLLT, XLenLLT);

// clang-format off
getActionDefinitionsBuilder({G_SMULH, G_UMULH})
.legalFor({XLenLLT})
.lower();
// clang-format on
} else {
getActionDefinitionsBuilder(G_MUL)
.libcallFor({XLenLLT, DoubleXLenLLT})
.widenScalarToNextPow2(0)
.clampScalar(0, XLenLLT, DoubleXLenLLT);

getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({XLenLLT});
}

getLegacyLegalizerInfo().computeTables();
}
199 changes: 199 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-mul-ext.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mattr=+m -mtriple=riscv32 -run-pass=legalizer %s -o - \
# RUN: | FileCheck %s
# RUN: llc -mattr=+zmmul -mtriple=riscv32 -run-pass=legalizer %s -o - \
# RUN: | FileCheck %s
---
name: mul_i7
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i7
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s7) = G_TRUNC %0(s32)
%3:_(s7) = G_TRUNC %1(s32)
%4:_(s7) = G_MUL %2, %3
%5:_(s32) = G_ANYEXT %4(s7)
$x10 = COPY %5(s32)
PseudoRET implicit $x10
...
---
name: mul_i8
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i8
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s8) = G_TRUNC %0(s32)
%3:_(s8) = G_TRUNC %1(s32)
%4:_(s8) = G_MUL %2, %3
%5:_(s32) = G_ANYEXT %4(s8)
$x10 = COPY %5(s32)
PseudoRET implicit $x10
...
---
name: mul_i16
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i16
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s16) = G_TRUNC %0(s32)
%3:_(s16) = G_TRUNC %1(s32)
%4:_(s16) = G_MUL %2, %3
%5:_(s32) = G_ANYEXT %4(s16)
$x10 = COPY %5(s32)
PseudoRET implicit $x10
...
---
name: mul_i32
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i32
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s32) = G_MUL %0, %1
$x10 = COPY %2(s32)
PseudoRET implicit $x10
...
---
name: mul_i48
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i48
; CHECK: %xhi:_(s32) = COPY $x10
; CHECK-NEXT: %xlo:_(s32) = COPY $x11
; CHECK-NEXT: %yhi:_(s32) = COPY $x12
; CHECK-NEXT: %ylo:_(s32) = COPY $x13
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL %xhi, %yhi
; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL %xlo, %yhi
; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL %xhi, %ylo
; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %xhi, %yhi
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]]
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: $x11 = COPY [[ADD1]](s32)
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
%xhi:_(s32) = COPY $x10
%xlo:_(s32) = COPY $x11
%yhi:_(s32) = COPY $x12
%ylo:_(s32) = COPY $x13
%x0:_(s64) = G_MERGE_VALUES %xhi(s32), %xlo(s32)
%y0:_(s64) = G_MERGE_VALUES %yhi(s32), %ylo(s32)
%x:_(s48) = G_TRUNC %x0(s64)
%y:_(s48) = G_TRUNC %y0(s64)
%z:_(s48) = G_MUL %x, %y
%z0:_(s64) = G_ANYEXT %z(s48)
%zhi:_(s32), %zlo:_(s32) = G_UNMERGE_VALUES %z0(s64)
$x10 = COPY %zhi(s32)
$x11 = COPY %zlo(s32)
PseudoRET implicit $x10, implicit $x11
...
---
name: mul_i64
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i64
; CHECK: %hi1:_(s32) = COPY $x10
; CHECK-NEXT: %lo1:_(s32) = COPY $x11
; CHECK-NEXT: %hi2:_(s32) = COPY $x12
; CHECK-NEXT: %lo2:_(s32) = COPY $x13
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL %hi1, %hi2
; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL %lo1, %hi2
; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL %hi1, %lo2
; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %hi1, %hi2
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]]
; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: $x11 = COPY [[ADD1]](s32)
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
%hi1:_(s32) = COPY $x10
%lo1:_(s32) = COPY $x11
%hi2:_(s32) = COPY $x12
%lo2:_(s32) = COPY $x13
%x1:_(s64) = G_MERGE_VALUES %hi1(s32), %lo1(s32)
%x2:_(s64) = G_MERGE_VALUES %hi2(s32), %lo2(s32)
%y:_(s64) = G_MUL %x1, %x2
%hiy:_(s32), %loy:_(s32) = G_UNMERGE_VALUES %y(s64)
$x10 = COPY %hiy(s32)
$x11 = COPY %loy(s32)
PseudoRET implicit $x10, implicit $x11
...
---
name: mul_i96
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i96
; CHECK: %hi1:_(s32) = COPY $x10
; CHECK-NEXT: %mid1:_(s32) = COPY $x11
; CHECK-NEXT: %lo1:_(s32) = COPY $x12
; CHECK-NEXT: %hi2:_(s32) = COPY $x13
; CHECK-NEXT: %mid2:_(s32) = COPY $x14
; CHECK-NEXT: %lo2:_(s32) = COPY $x15
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL %hi1, %hi2
; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL %mid1, %hi2
; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL %hi1, %mid2
; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %hi1, %hi2
; CHECK-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s32) = G_UADDO [[MUL1]], [[MUL2]]
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[UADDO1]], [[C]]
; CHECK-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s32) = G_UADDO [[UADDO]], [[UMULH]]
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[UADDO3]], [[C1]]
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[AND]], [[AND1]]
; CHECK-NEXT: [[MUL3:%[0-9]+]]:_(s32) = G_MUL %lo1, %hi2
; CHECK-NEXT: [[MUL4:%[0-9]+]]:_(s32) = G_MUL %mid1, %mid2
; CHECK-NEXT: [[MUL5:%[0-9]+]]:_(s32) = G_MUL %hi1, %lo2
; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH %mid1, %hi2
; CHECK-NEXT: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH %hi1, %mid2
; CHECK-NEXT: [[UADDO4:%[0-9]+]]:_(s32), [[UADDO5:%[0-9]+]]:_(s32) = G_UADDO [[MUL3]], [[MUL4]]
; CHECK-NEXT: [[UADDO6:%[0-9]+]]:_(s32), [[UADDO7:%[0-9]+]]:_(s32) = G_UADDO [[UADDO4]], [[MUL5]]
; CHECK-NEXT: [[UADDO8:%[0-9]+]]:_(s32), [[UADDO9:%[0-9]+]]:_(s32) = G_UADDO [[UADDO6]], [[UMULH1]]
; CHECK-NEXT: [[UADDO10:%[0-9]+]]:_(s32), [[UADDO11:%[0-9]+]]:_(s32) = G_UADDO [[UADDO8]], [[UMULH2]]
; CHECK-NEXT: [[UADDO12:%[0-9]+]]:_(s32), [[UADDO13:%[0-9]+]]:_(s32) = G_UADDO [[UADDO10]], [[ADD]]
; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
; CHECK-NEXT: $x11 = COPY [[UADDO2]](s32)
; CHECK-NEXT: $x12 = COPY [[UADDO12]](s32)
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12
%hi1:_(s32) = COPY $x10
%mid1:_(s32) = COPY $x11
%lo1:_(s32) = COPY $x12
%hi2:_(s32) = COPY $x13
%mid2:_(s32) = COPY $x14
%lo2:_(s32) = COPY $x15
%x1:_(s96) = G_MERGE_VALUES %hi1(s32), %mid1(s32), %lo1(s32)
%x2:_(s96) = G_MERGE_VALUES %hi2(s32), %mid2(s32), %lo2(s32)
%y:_(s96) = G_MUL %x1, %x2
%hi:_(s32), %mid:_(s32), %lo:_(s32) = G_UNMERGE_VALUES %y(s96)
$x10 = COPY %hi(s32)
$x11 = COPY %mid(s32)
$x12 = COPY %lo(s32)
PseudoRET implicit $x10, implicit $x11, implicit $x12
...
124 changes: 124 additions & 0 deletions llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-mul.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - \
# RUN: | FileCheck %s
---
name: mul_i7
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i7
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s7) = G_TRUNC %0(s32)
%3:_(s7) = G_TRUNC %1(s32)
%4:_(s7) = G_MUL %2, %3
%5:_(s32) = G_ANYEXT %4(s7)
$x10 = COPY %5(s32)
PseudoRET implicit $x10
...
---
name: mul_i8
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i8
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s8) = G_TRUNC %0(s32)
%3:_(s8) = G_TRUNC %1(s32)
%4:_(s8) = G_MUL %2, %3
%5:_(s32) = G_ANYEXT %4(s8)
$x10 = COPY %5(s32)
PseudoRET implicit $x10
...
---
name: mul_i16
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i16
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s16) = G_TRUNC %0(s32)
%3:_(s16) = G_TRUNC %1(s32)
%4:_(s16) = G_MUL %2, %3
%5:_(s32) = G_ANYEXT %4(s16)
$x10 = COPY %5(s32)
PseudoRET implicit $x10
...
---
name: mul_i32
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i32
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: $x10 = COPY [[COPY2]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $x10
%1:_(s32) = COPY $x11
%2:_(s32) = G_MUL %0, %1
$x10 = COPY %2(s32)
PseudoRET implicit $x10
...
---
name: mul_i64
body: |
bb.0.entry:
; CHECK-LABEL: name: mul_i64
; CHECK: %hi1:_(s32) = COPY $x10
; CHECK-NEXT: %lo1:_(s32) = COPY $x11
; CHECK-NEXT: %hi2:_(s32) = COPY $x12
; CHECK-NEXT: %lo2:_(s32) = COPY $x13
; CHECK-NEXT: $x10 = COPY %hi1(s32)
; CHECK-NEXT: $x11 = COPY %lo1(s32)
; CHECK-NEXT: $x12 = COPY %hi2(s32)
; CHECK-NEXT: $x13 = COPY %lo2(s32)
; 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
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
; CHECK-NEXT: $x11 = COPY [[COPY1]](s32)
; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
%hi1:_(s32) = COPY $x10
%lo1:_(s32) = COPY $x11
%hi2:_(s32) = COPY $x12
%lo2:_(s32) = COPY $x13
%x1:_(s64) = G_MERGE_VALUES %hi1(s32), %lo1(s32)
%x2:_(s64) = G_MERGE_VALUES %hi2(s32), %lo2(s32)
%y:_(s64) = G_MUL %x1, %x2
%hiy:_(s32), %loy:_(s32) = G_UNMERGE_VALUES %y(s64)
$x10 = COPY %hiy(s32)
$x11 = COPY %loy(s32)
PseudoRET implicit $x10, implicit $x11
...

0 comments on commit 638865c

Please sign in to comment.