Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV][GISel] Legalize G_SMULO/G_UMULO #67635

Merged
merged 5 commits into from
Oct 14, 2023
Merged

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Sep 28, 2023

I'm unhappy with the XLen case when we need to make a libcall. We get two libcalls.

I'm unhappy with the XLen case when we need to make a libcall. We
get two libcalls.
@llvmbot
Copy link

llvmbot commented Sep 28, 2023

@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-llvm-globalisel

Changes

I'm unhappy with the XLen case when we need to make a libcall. We get two libcalls.


Patch is 37.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/67635.diff

3 Files Affected:

  • (modified) llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp (+8)
  • (added) llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-mulo.mir (+340)
  • (added) llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-mulo.mir (+442)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 313a8221ab1bd4a..a9d6f61541253f7 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -145,6 +145,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
         .legalFor({XLenLLT})
         .lower();
     // clang-format on
+
+    getActionDefinitionsBuilder({G_SMULO, G_UMULO})
+        .minScalar(0, XLenLLT)
+        .lower();
   } else {
     getActionDefinitionsBuilder(G_MUL)
         .libcallFor({XLenLLT, DoubleXLenLLT})
@@ -152,6 +156,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
         .clampScalar(0, XLenLLT, DoubleXLenLLT);
 
     getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({XLenLLT});
+
+    getActionDefinitionsBuilder({G_SMULO, G_UMULO})
+        .minScalar(0, XLenLLT)
+        .lower();
   }
 
   if (ST.hasStdExtM()) {
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-mulo.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-mulo.mir
new file mode 100644
index 000000000000000..35bea08f426a3a3
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-mulo.mir
@@ -0,0 +1,340 @@
+# 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
+# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s --check-prefix=LIBCALL
+
+---
+name:            smulo_i8
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: smulo_i8
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32)
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C1]](s32)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[ASHR1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; CHECK-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[MUL]], [[C2]](s32)
+    ; CHECK-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]](s32)
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[MUL]](s32), [[ASHR2]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: smulo_i8
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; LIBCALL-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32)
+    ; LIBCALL-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; LIBCALL-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C1]](s32)
+    ; LIBCALL-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; LIBCALL-NEXT: $x10 = COPY [[ASHR]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ASHR1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; LIBCALL-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C2]](s32)
+    ; LIBCALL-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]](s32)
+    ; LIBCALL-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY2]](s32), [[ASHR2]]
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY2]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; LIBCALL-NEXT: PseudoRET implicit $x10, implicit $x11
+    %2:_(s32) = COPY $x10
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = COPY $x11
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8), %5:_(s1) = G_SMULO %0, %1
+    %6:_(s32) = G_ANYEXT %4(s8)
+    %7:_(s32) = G_ANYEXT %5(s1)
+    $x10 = COPY %6(s32)
+    $x11 = COPY %7(s32)
+    PseudoRET implicit $x10, implicit $x11
+
+...
+---
+name:            smulo_i16
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: smulo_i16
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32)
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C1]](s32)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[ASHR1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; CHECK-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[MUL]], [[C2]](s32)
+    ; CHECK-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]](s32)
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[MUL]](s32), [[ASHR2]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: smulo_i16
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; LIBCALL-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32)
+    ; LIBCALL-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; LIBCALL-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY1]], [[C1]](s32)
+    ; LIBCALL-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; LIBCALL-NEXT: $x10 = COPY [[ASHR]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ASHR1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; LIBCALL-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C2]](s32)
+    ; LIBCALL-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C2]](s32)
+    ; LIBCALL-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY2]](s32), [[ASHR2]]
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY2]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; LIBCALL-NEXT: PseudoRET implicit $x10, implicit $x11
+    %2:_(s32) = COPY $x10
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:_(s32) = COPY $x11
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16), %5:_(s1) = G_SMULO %0, %1
+    %6:_(s32) = G_ANYEXT %4(s16)
+    %7:_(s32) = G_ANYEXT %5(s1)
+    $x10 = COPY %6(s32)
+    $x11 = COPY %7(s32)
+    PseudoRET implicit $x10, implicit $x11
+
+...
+---
+name:            smulo_i32
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: smulo_i32
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[MUL]], [[C]](s32)
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[SMULH]](s32), [[ASHR]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: smulo_i32
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; LIBCALL-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C]](s32)
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; LIBCALL-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[COPY1]], [[C1]](s32)
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ASHR]](s32)
+    ; LIBCALL-NEXT: $x12 = COPY [[COPY1]](s32)
+    ; LIBCALL-NEXT: $x13 = COPY [[ASHR1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__muldi3, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit-def $x10, implicit-def $x11
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[COPY1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; LIBCALL-NEXT: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[COPY3]], [[C2]](s32)
+    ; LIBCALL-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY2]](s32), [[ASHR2]]
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY3]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; LIBCALL-NEXT: PseudoRET implicit $x10, implicit $x11
+    %0:_(s32) = COPY $x10
+    %1:_(s32) = COPY $x11
+    %2:_(s32), %3:_(s1) = G_SMULO %0, %1
+    %4:_(s32) = G_ANYEXT %3(s1)
+    $x10 = COPY %2(s32)
+    $x11 = COPY %4(s32)
+    PseudoRET implicit $x10, implicit $x11
+
+...
+---
+name:            umulo_i8
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: umulo_i8
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]]
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND]], [[AND1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C2]]
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[MUL]](s32), [[AND2]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: umulo_i8
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; LIBCALL-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]]
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; LIBCALL-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]]
+    ; LIBCALL-NEXT: $x10 = COPY [[AND]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[AND1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; LIBCALL-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C2]]
+    ; LIBCALL-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY2]](s32), [[AND2]]
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY2]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; LIBCALL-NEXT: PseudoRET implicit $x10, implicit $x11
+    %2:_(s32) = COPY $x10
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = COPY $x11
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8), %5:_(s1) = G_UMULO %0, %1
+    %6:_(s32) = G_ANYEXT %4(s8)
+    %7:_(s32) = G_ANYEXT %5(s1)
+    $x10 = COPY %6(s32)
+    $x11 = COPY %7(s32)
+    PseudoRET implicit $x10, implicit $x11
+
+...
+---
+name:            umulo_i16
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: umulo_i16
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]]
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND]], [[AND1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C2]]
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[MUL]](s32), [[AND2]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: umulo_i16
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; LIBCALL-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]]
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; LIBCALL-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]]
+    ; LIBCALL-NEXT: $x10 = COPY [[AND]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[AND1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; LIBCALL-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C2]]
+    ; LIBCALL-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY2]](s32), [[AND2]]
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY2]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; LIBCALL-NEXT: PseudoRET implicit $x10, implicit $x11
+    %2:_(s32) = COPY $x10
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:_(s32) = COPY $x11
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16), %5:_(s1) = G_UMULO %0, %1
+    %6:_(s32) = G_ANYEXT %4(s16)
+    %7:_(s32) = G_ANYEXT %5(s1)
+    $x10 = COPY %6(s32)
+    $x11 = COPY %7(s32)
+    PseudoRET implicit $x10, implicit $x11
+
+...
+---
+name:            umulo_i32
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: umulo_i32
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[UMULH]](s32), [[C]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: umulo_i32
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[C]](s32)
+    ; LIBCALL-NEXT: $x12 = COPY [[COPY1]](s32)
+    ; LIBCALL-NEXT: $x13 = COPY [[C1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__muldi3, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit-def $x10, implicit-def $x11
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[COPY1]](s32)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__mulsi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x10
+    ; LIBCALL-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[COPY2]](s32), [[C2]]
+    ; LIBCALL-NEXT: $x10 = COPY [[COPY3]](s32)
+    ; LIBCALL-NEXT: $x11 = COPY [[ICMP]](s32)
+    ; LIBCALL-NEXT: PseudoRET implicit $x10, implicit $x11
+    %0:_(s32) = COPY $x10
+    %1:_(s32) = COPY $x11
+    %2:_(s32), %3:_(s1) = G_UMULO %0, %1
+    %4:_(s32) = G_ANYEXT %3(s1)
+    $x10 = COPY %2(s32)
+    $x11 = COPY %4(s32)
+    PseudoRET implicit $x10, implicit $x11
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-mulo.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-mulo.mir
new file mode 100644
index 000000000000000..219635914efdd1d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-mulo.mir
@@ -0,0 +1,442 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mattr=+m -mtriple=riscv64 -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+# RUN: llc -mattr=+zmmul -mtriple=riscv64 -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+# RUN: llc -mtriple=riscv64 -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s --check-prefix=LIBCALL
+
+---
+name:            smulo_i8
+body:             |
+  bb.1:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: smulo_i8
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY]], [[C]](s64)
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s64) = G_SHL [[COPY1]], [[C1]](s64)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[SHL1]], [[C1]](s64)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[ASHR]], [[ASHR1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; CHECK-NEXT: [[SHL2:%[0-9]+]]:_(s64) = G_SHL [[MUL]], [[C2]](s64)
+    ; CHECK-NEXT: [[ASHR2:%[0-9]+]]:_(s64) = G_ASHR [[SHL2]], [[C2]](s64)
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ne), [[MUL]](s64), [[ASHR2]]
+    ; CHECK-NEXT: $x10 = COPY [[MUL]](s64)
+    ; CHECK-NEXT: $x11 = COPY [[ICMP]](s64)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    ;
+    ; LIBCALL-LABEL: name: smulo_i8
+    ; LIBCALL: liveins: $x10, $x11
+    ; LIBCALL-NEXT: {{  $}}
+    ; LIBCALL-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+    ; LIBCALL-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+    ; LIBCALL-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; LIBCALL-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY]], [[C]](s64)
+    ; LIBCALL-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; LIBCALL-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; LIBCALL-NEXT: [[SHL1:%[0-9]+]]:_(s64) = G_SHL [[COPY1]], [[C1]](s64)
+    ; LIBCALL-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[SHL1]], [[C1]](s64)
+    ; LIBCALL-NEXT: $x10 = COPY [[ASHR]](s64)
+    ; LIBCALL-NEXT: $x11 = COPY [[ASHR1]](s64)
+    ; LIBCALL-NEXT: PseudoCALL target-flags(riscv-call) &__muldi3, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10
+    ; LIBCALL-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $x10
+    ; LIBCALL-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; LIBCALL-NEXT: [[SHL2:%[0-9]+...
[truncated]

@@ -145,13 +145,21 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
.legalFor({XLenLLT})
.lower();
// clang-format on

getActionDefinitionsBuilder({G_SMULO, G_UMULO})
Copy link
Member

@tschuett tschuett Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am maybe blind, but could you hoist them above the if? They look similar.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah they're the same. They were briefly different while I tried and failed to fix the 2 libcall issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a feeling that you are going for coverage and not performance. Could you instead do a custom legalization, i.e. RISC-V specific and not generic lower?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The widening of small types creates an XLenLLT sized G_SMULO even though that can't overflow if the small type was half of XLen or less. I don't know how to distinquish that G_SMULO from the original. So I ended up with a double XLen libcall no matter what which is not really what I wanted.

I guess I could write custom legalization for everything, but didn't seem ideal.

@github-actions
Copy link

github-actions bot commented Sep 29, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@topperc
Copy link
Collaborator Author

topperc commented Oct 13, 2023

Ping

Copy link
Contributor

@aemerson aemerson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

// the low bits for the mul result and high bits to do the overflow
// check.
.widenScalarIf(
[=, &ST](const LegalityQuery &Query) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for ST?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Copy and pasted from elsewhere. Will remove.

@topperc topperc merged commit 3750558 into llvm:main Oct 14, 2023
2 of 3 checks passed
@topperc topperc deleted the pr/gisel-mulo branch October 14, 2023 03:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants