[llvm] [GlobalISel][AArch64] Add lowering for G_UMULFIX (PR #197018)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Tue May 12 00:29:45 PDT 2026


https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/197018

>From 7c33f4dd8a8dbaa4005d16062ab47391908fc9f0 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Mon, 11 May 2026 16:30:49 +0200
Subject: [PATCH 1/3] [GlobalISel][AArch64] Add lowering for G_UMULFIX

---
 .../llvm/CodeGen/GlobalISel/LegalizerHelper.h |   2 +-
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    |  28 ++-
 .../AArch64/GISel/AArch64LegalizerInfo.cpp    |   2 +-
 .../AArch64/GlobalISel/legalize-smulfix.mir   |  24 +--
 .../AArch64/GlobalISel/legalize-umulfix.mir   | 179 ++++++++++++++++++
 .../GlobalISel/legalizer-info-validation.mir  |   5 +-
 llvm/test/CodeGen/AArch64/umul_fix.ll         | 169 +++++++++++------
 7 files changed, 330 insertions(+), 79 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 9858f5e92de7a..3377ec71c8f0a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -576,7 +576,7 @@ class LegalizerHelper {
   LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI,
                                             unsigned MaxLen = 0);
   LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI);
-  LLVM_ABI LegalizeResult lowerSmulfix(MachineInstr &MI);
+  LLVM_ABI LegalizeResult lowerMulfix(MachineInstr &MI);
 };
 
 } // End namespace llvm.
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 070d7ec4b963e..4b8276f9b77e0 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -37,6 +37,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
+#include <cassert>
 #include <numeric>
 #include <optional>
 
@@ -4969,7 +4970,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
     return Legalized;
   }
   case G_SMULFIX:
-    return lowerSmulfix(MI);
+  case G_UMULFIX:
+    return lowerMulfix(MI);
   }
 }
 
@@ -10656,8 +10658,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerVAArg(MachineInstr &MI) {
   return Legalized;
 }
 
-LegalizerHelper::LegalizeResult
-LegalizerHelper::lowerSmulfix(MachineInstr &MI) {
+LegalizerHelper::LegalizeResult LegalizerHelper::lowerMulfix(MachineInstr &MI) {
+  unsigned OpCode = MI.getOpcode();
+  assert(OpCode == TargetOpcode::G_SMULFIX ||
+         OpCode == TargetOpcode::G_UMULFIX &&
+             "Operator must be either G_SMULFIX or G_UMULFIX!");
   auto [Dst, LHS, RHS] = MI.getFirst3Regs();
   LLT Ty = MRI.getType(Dst);
   unsigned Scale = MI.getOperand(3).getImm();
@@ -10669,12 +10674,19 @@ LegalizerHelper::lowerSmulfix(MachineInstr &MI) {
   }
 
   LLT WideTy = Ty.changeElementSize(Ty.getScalarSizeInBits() * 2);
-  auto SExtLHS = MIRBuilder.buildSExt(WideTy, LHS);
-  auto SExtRHS = MIRBuilder.buildSExt(WideTy, RHS);
-  auto Mul = MIRBuilder.buildMul(WideTy, SExtLHS, SExtRHS);
   auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Scale);
-  auto Shifted = MIRBuilder.buildAShr(WideTy, Mul, ShiftAmt);
-  MIRBuilder.buildTrunc(Dst, Shifted);
+  MachineInstrBuilder ExtLHS{}, ExtRHS{};
+  if (MI.getOpcode() == TargetOpcode::G_SMULFIX) {
+    ExtLHS = MIRBuilder.buildSExt(WideTy, LHS);
+    ExtRHS = MIRBuilder.buildSExt(WideTy, RHS);
+  } else {
+    ExtLHS = MIRBuilder.buildZExt(WideTy, LHS);
+    ExtRHS = MIRBuilder.buildZExt(WideTy, RHS);
+  }
+
+  auto Mul = MIRBuilder.buildMul(WideTy, ExtLHS, ExtRHS);
+  auto Shift = MIRBuilder.buildAShr(WideTy, Mul, ShiftAmt);
+  MIRBuilder.buildTrunc(Dst, Shift);
 
   MI.eraseFromParent();
   return Legalized;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 4c7abbfb871af..e2bff9f74360c 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -297,7 +297,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
       .legalFor({i64, v16i8, v8i16, v4i32})
       .lower();
 
-  getActionDefinitionsBuilder(G_SMULFIX).lower();
+  getActionDefinitionsBuilder({G_SMULFIX, G_UMULFIX}).lower();
 
   getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
       .legalFor({v8i8, v16i8, v4i16, v8i16, v2i32, v4i32})
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-smulfix.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-smulfix.mir
index 2b660e5064b03..2bc0c420461be 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-smulfix.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-smulfix.mir
@@ -31,10 +31,10 @@ body:             |
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $w0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
     ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(i64) = G_SEXT [[COPY]](i32)
     ; CHECK-NEXT: [[SEXT1:%[0-9]+]]:_(i64) = G_SEXT [[COPY1]](i32)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i64) = G_MUL [[SEXT]], [[SEXT1]]
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
     ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(i64) = G_ASHR [[MUL]], [[C]](i64)
     ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i32) = G_TRUNC [[ASHR]](i64)
     ; CHECK-NEXT: $w0 = COPY [[TRUNC]](i32)
@@ -56,17 +56,17 @@ body:             |
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i64) = COPY $x0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i64) = COPY $x1
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 63
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(i64) = G_ASHR [[COPY]], [[C]](i64)
-    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(i64) = G_ASHR [[COPY1]], [[C]](i64)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(i64) = G_CONSTANT i64 63
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(i64) = G_ASHR [[COPY]], [[C1]](i64)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(i64) = G_ASHR [[COPY1]], [[C1]](i64)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i64) = G_MUL [[COPY]], [[COPY1]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(i64) = G_MUL [[ASHR]], [[COPY1]]
     ; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(i64) = G_MUL [[COPY]], [[ASHR1]]
     ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(i64) = G_UMULH [[COPY]], [[COPY1]]
     ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(i64) = G_ADD [[MUL1]], [[MUL2]]
     ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(i64) = G_ADD [[ADD]], [[UMULH]]
-    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
-    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(i64) = G_LSHR [[MUL]], [[C1]](i64)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(i64) = G_LSHR [[MUL]], [[C]](i64)
     ; CHECK-NEXT: [[C2:%[0-9]+]]:_(i64) = G_CONSTANT i64 49
     ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(i64) = G_SHL [[ADD1]], [[C2]](i64)
     ; CHECK-NEXT: [[OR:%[0-9]+]]:_(i64) = G_OR [[LSHR]], [[SHL]]
@@ -89,6 +89,8 @@ body:             |
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x i32>) = COPY $q0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x i32>) = COPY $q1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 2
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
     ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x i32>), [[UV1:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY]](<4 x i32>)
     ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV]](<2 x i32>)
     ; CHECK-NEXT: [[SEXT1:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV1]](<2 x i32>)
@@ -97,8 +99,6 @@ body:             |
     ; CHECK-NEXT: [[SEXT3:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV3]](<2 x i32>)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[SEXT]], [[SEXT2]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[SEXT1]], [[SEXT3]]
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 2
-    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
     ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
     ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
     ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
@@ -123,6 +123,8 @@ body:             |
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x i32>) = COPY $q0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x i32>) = COPY $q1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
     ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x i32>), [[UV1:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY]](<4 x i32>)
     ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV]](<2 x i32>)
     ; CHECK-NEXT: [[SEXT1:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV1]](<2 x i32>)
@@ -131,8 +133,6 @@ body:             |
     ; CHECK-NEXT: [[SEXT3:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV3]](<2 x i32>)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[SEXT]], [[SEXT2]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[SEXT1]], [[SEXT3]]
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
-    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
     ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
     ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
     ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
@@ -156,6 +156,8 @@ body:             |
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x i32>) = COPY $q0
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x i32>) = COPY $q1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 31
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
     ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x i32>), [[UV1:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY]](<4 x i32>)
     ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV]](<2 x i32>)
     ; CHECK-NEXT: [[SEXT1:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV1]](<2 x i32>)
@@ -164,8 +166,6 @@ body:             |
     ; CHECK-NEXT: [[SEXT3:%[0-9]+]]:_(<2 x i64>) = G_SEXT [[UV3]](<2 x i32>)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[SEXT]], [[SEXT2]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[SEXT1]], [[SEXT3]]
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 31
-    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
     ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
     ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
     ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
new file mode 100644
index 0000000000000..1ad22728793b8
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
@@ -0,0 +1,179 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -global-isel -mtriple=aarch64 -run-pass=legalizer %s -o - | FileCheck %s
+---
+name:            smulfix_i32_scale_0
+body:             |
+  bb.1:
+    liveins: $w0, $w1
+
+    ; CHECK-LABEL: name: smulfix_i32_scale_0
+    ; CHECK: liveins: $w0, $w1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i32) = G_MUL [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: $w0 = COPY [[MUL]](i32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(i32) = COPY $w0
+    %1:_(i32) = COPY $w1
+    %2:_(i32) = G_UMULFIX %0, %1, 0
+    $w0 = COPY %2(i32)
+    RET_ReallyLR implicit $w0
+...
+---
+name:            smulfix_i32
+body:             |
+  bb.1:
+    liveins: $w0, $w1
+
+    ; CHECK-LABEL: name: smulfix_i32
+    ; CHECK: liveins: $w0, $w1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[COPY]](i32)
+    ; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(i64) = G_ZEXT [[COPY1]](i32)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i64) = G_MUL [[ZEXT]], [[ZEXT1]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(i64) = G_ASHR [[MUL]], [[C]](i64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i32) = G_TRUNC [[ASHR]](i64)
+    ; CHECK-NEXT: $w0 = COPY [[TRUNC]](i32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(i32) = COPY $w0
+    %1:_(i32) = COPY $w1
+    %2:_(i32) = G_UMULFIX %0, %1, 15
+    $w0 = COPY %2(i32)
+    RET_ReallyLR implicit $w0
+...
+---
+name:            smulfix_i64
+body:             |
+  bb.1:
+    liveins: $x0, $x1
+
+    ; CHECK-LABEL: name: smulfix_i64
+    ; CHECK: liveins: $x0, $x1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i64) = COPY $x0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i64) = COPY $x1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(i64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i64) = G_MUL [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(i64) = G_MUL [[C1]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(i64) = G_MUL [[COPY]], [[C1]]
+    ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(i64) = G_UMULH [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(i64) = G_ADD [[MUL1]], [[MUL2]]
+    ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(i64) = G_ADD [[ADD]], [[UMULH]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(i64) = G_LSHR [[MUL]], [[C]](i64)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(i64) = G_CONSTANT i64 49
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(i64) = G_SHL [[ADD1]], [[C2]](i64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(i64) = G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: $x0 = COPY [[OR]](i64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %0:_(i64) = COPY $x0
+    %1:_(i64) = COPY $x1
+    %2:_(i64) = G_UMULFIX %0, %1, 15
+    $x0 = COPY %2(i64)
+    RET_ReallyLR implicit $x0
+...
+---
+name:            smulfix_4xi32
+body:             |
+  bb.1:
+    liveins: $q0, $q1
+
+    ; CHECK-LABEL: name: smulfix_4xi32
+    ; CHECK: liveins: $q0, $q1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x i32>) = COPY $q0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x i32>) = COPY $q1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 2
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
+    ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x i32>), [[UV1:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY]](<4 x i32>)
+    ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV]](<2 x i32>)
+    ; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV1]](<2 x i32>)
+    ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(<2 x i32>), [[UV3:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY1]](<4 x i32>)
+    ; CHECK-NEXT: [[ZEXT2:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV2]](<2 x i32>)
+    ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV3]](<2 x i32>)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT]], [[ZEXT2]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT1]], [[ZEXT3]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR1]](<2 x i64>)
+    ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x i32>) = G_CONCAT_VECTORS [[TRUNC]](<2 x i32>), [[TRUNC1]](<2 x i32>)
+    ; CHECK-NEXT: $q0 = COPY [[CONCAT_VECTORS]](<4 x i32>)
+    ; CHECK-NEXT: RET_ReallyLR implicit $q0
+    %0:_(<4 x i32>) = COPY $q0
+    %1:_(<4 x i32>) = COPY $q1
+    %2:_(<4 x i32>) = G_UMULFIX %0, %1, 2
+    $q0 = COPY %2(<4 x i32>)
+    RET_ReallyLR implicit $q0
+...
+---
+name:            smulfix_4xi32_15
+body:             |
+  bb.1:
+    liveins: $q0, $q1
+
+    ; CHECK-LABEL: name: smulfix_4xi32_15
+    ; CHECK: liveins: $q0, $q1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x i32>) = COPY $q0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x i32>) = COPY $q1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
+    ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x i32>), [[UV1:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY]](<4 x i32>)
+    ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV]](<2 x i32>)
+    ; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV1]](<2 x i32>)
+    ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(<2 x i32>), [[UV3:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY1]](<4 x i32>)
+    ; CHECK-NEXT: [[ZEXT2:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV2]](<2 x i32>)
+    ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV3]](<2 x i32>)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT]], [[ZEXT2]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT1]], [[ZEXT3]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR1]](<2 x i64>)
+    ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x i32>) = G_CONCAT_VECTORS [[TRUNC]](<2 x i32>), [[TRUNC1]](<2 x i32>)
+    ; CHECK-NEXT: $q0 = COPY [[CONCAT_VECTORS]](<4 x i32>)
+    ; CHECK-NEXT: RET_ReallyLR implicit $q0
+    %0:_(<4 x i32>) = COPY $q0
+    %1:_(<4 x i32>) = COPY $q1
+    %2:_(<4 x i32>) = G_UMULFIX %0, %1, 15
+    $q0 = COPY %2(<4 x i32>)
+    RET_ReallyLR implicit $q0
+...
+---
+name:            smulfix_4xi32_31
+body:             |
+  bb.1:
+    liveins: $q0, $q1
+    ; CHECK-LABEL: name: smulfix_4xi32_31
+    ; CHECK: liveins: $q0, $q1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x i32>) = COPY $q0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x i32>) = COPY $q1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 31
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
+    ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x i32>), [[UV1:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY]](<4 x i32>)
+    ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV]](<2 x i32>)
+    ; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV1]](<2 x i32>)
+    ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(<2 x i32>), [[UV3:%[0-9]+]]:_(<2 x i32>) = G_UNMERGE_VALUES [[COPY1]](<4 x i32>)
+    ; CHECK-NEXT: [[ZEXT2:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV2]](<2 x i32>)
+    ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV3]](<2 x i32>)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT]], [[ZEXT2]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT1]], [[ZEXT3]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR1]](<2 x i64>)
+    ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x i32>) = G_CONCAT_VECTORS [[TRUNC]](<2 x i32>), [[TRUNC1]](<2 x i32>)
+    ; CHECK-NEXT: $q0 = COPY [[CONCAT_VECTORS]](<4 x i32>)
+    ; CHECK-NEXT: RET_ReallyLR implicit $q0
+    %0:_(<4 x i32>) = COPY $q0
+    %1:_(<4 x i32>) = COPY $q1
+    %2:_(<4 x i32>) = G_UMULFIX %0, %1, 31
+    $q0 = COPY %2(<4 x i32>)
+    RET_ReallyLR implicit $q0
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 70dbeb7d49f65..cdf28d74e82c4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -495,8 +495,9 @@
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: G_UMULFIX (opcode {{[0-9]+}}): 1 type index, 1 imm index
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: G_SMULFIXSAT (opcode {{[0-9]+}}): 1 type index, 1 imm index
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
diff --git a/llvm/test/CodeGen/AArch64/umul_fix.ll b/llvm/test/CodeGen/AArch64/umul_fix.ll
index 823f4bdecbad6..29862369b8a08 100644
--- a/llvm/test/CodeGen/AArch64/umul_fix.ll
+++ b/llvm/test/CodeGen/AArch64/umul_fix.ll
@@ -1,13 +1,21 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc < %s -mtriple=aarch64-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define i32 @func(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: func:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    umull x8, w0, w1
-; CHECK-NEXT:    lsr x9, x8, #32
-; CHECK-NEXT:    extr w0, w9, w8, #2
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: func:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    umull x8, w0, w1
+; CHECK-SD-NEXT:    lsr x9, x8, #32
+; CHECK-SD-NEXT:    extr w0, w9, w8, #2
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: func:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    umull x8, w0, w1
+; CHECK-GI-NEXT:    asr x0, x8, #2
+; CHECK-GI-NEXT:    // kill: def $w0 killed $w0 killed $x0
+; CHECK-GI-NEXT:    ret
   %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 2)
   ret i32 %tmp
 }
@@ -24,13 +32,21 @@ define i64 @func2(i64 %x, i64 %y) nounwind {
 }
 
 define i4 @func3(i4 %x, i4 %y) nounwind {
-; CHECK-LABEL: func3:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    and w8, w1, #0xf
-; CHECK-NEXT:    and w9, w0, #0xf
-; CHECK-NEXT:    mul w8, w9, w8
-; CHECK-NEXT:    lsr w0, w8, #2
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: func3:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    and w8, w1, #0xf
+; CHECK-SD-NEXT:    and w9, w0, #0xf
+; CHECK-SD-NEXT:    mul w8, w9, w8
+; CHECK-SD-NEXT:    lsr w0, w8, #2
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: func3:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    and w8, w0, #0xf
+; CHECK-GI-NEXT:    and w9, w1, #0xf
+; CHECK-GI-NEXT:    mul w8, w8, w9
+; CHECK-GI-NEXT:    sbfx w0, w8, #2, #6
+; CHECK-GI-NEXT:    ret
   %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 2)
   ret i4 %tmp
 }
@@ -55,12 +71,17 @@ define i64 @func5(i64 %x, i64 %y) nounwind {
 }
 
 define i4 @func6(i4 %x, i4 %y) nounwind {
-; CHECK-LABEL: func6:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    and w8, w1, #0xf
-; CHECK-NEXT:    and w9, w0, #0xf
-; CHECK-NEXT:    mul w0, w9, w8
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: func6:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    and w8, w1, #0xf
+; CHECK-SD-NEXT:    and w9, w0, #0xf
+; CHECK-SD-NEXT:    mul w0, w9, w8
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: func6:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mul w0, w0, w1
+; CHECK-GI-NEXT:    ret
   %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 0)
   ret i4 %tmp
 }
@@ -115,46 +136,84 @@ define <4 x i32> @vec2(<4 x i32> %x, <4 x i32> %y) nounwind {
 }
 
 define <4 x i64> @vec3(<4 x i64> %x, <4 x i64> %y) nounwind {
-; CHECK-LABEL: vec3:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov x8, v2.d[1]
-; CHECK-NEXT:    mov x9, v0.d[1]
-; CHECK-NEXT:    fmov x10, d2
-; CHECK-NEXT:    fmov x11, d0
-; CHECK-NEXT:    mov x14, v3.d[1]
-; CHECK-NEXT:    mov x15, v1.d[1]
-; CHECK-NEXT:    mul x12, x11, x10
-; CHECK-NEXT:    mul x13, x9, x8
-; CHECK-NEXT:    umulh x8, x9, x8
-; CHECK-NEXT:    umulh x9, x11, x10
-; CHECK-NEXT:    fmov x10, d3
-; CHECK-NEXT:    fmov x11, d1
-; CHECK-NEXT:    mul x16, x11, x10
-; CHECK-NEXT:    extr x8, x8, x13, #32
-; CHECK-NEXT:    umulh x10, x11, x10
-; CHECK-NEXT:    extr x9, x9, x12, #32
-; CHECK-NEXT:    mul x11, x15, x14
-; CHECK-NEXT:    fmov d0, x9
-; CHECK-NEXT:    umulh x14, x15, x14
-; CHECK-NEXT:    extr x10, x10, x16, #32
-; CHECK-NEXT:    mov v0.d[1], x8
-; CHECK-NEXT:    fmov d1, x10
-; CHECK-NEXT:    extr x11, x14, x11, #32
-; CHECK-NEXT:    mov v1.d[1], x11
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vec3:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov x8, v2.d[1]
+; CHECK-SD-NEXT:    mov x9, v0.d[1]
+; CHECK-SD-NEXT:    fmov x10, d2
+; CHECK-SD-NEXT:    fmov x11, d0
+; CHECK-SD-NEXT:    mov x14, v3.d[1]
+; CHECK-SD-NEXT:    mov x15, v1.d[1]
+; CHECK-SD-NEXT:    mul x12, x11, x10
+; CHECK-SD-NEXT:    mul x13, x9, x8
+; CHECK-SD-NEXT:    umulh x8, x9, x8
+; CHECK-SD-NEXT:    umulh x9, x11, x10
+; CHECK-SD-NEXT:    fmov x10, d3
+; CHECK-SD-NEXT:    fmov x11, d1
+; CHECK-SD-NEXT:    mul x16, x11, x10
+; CHECK-SD-NEXT:    extr x8, x8, x13, #32
+; CHECK-SD-NEXT:    umulh x10, x11, x10
+; CHECK-SD-NEXT:    extr x9, x9, x12, #32
+; CHECK-SD-NEXT:    mul x11, x15, x14
+; CHECK-SD-NEXT:    fmov d0, x9
+; CHECK-SD-NEXT:    umulh x14, x15, x14
+; CHECK-SD-NEXT:    extr x10, x10, x16, #32
+; CHECK-SD-NEXT:    mov v0.d[1], x8
+; CHECK-SD-NEXT:    fmov d1, x10
+; CHECK-SD-NEXT:    extr x11, x14, x11, #32
+; CHECK-SD-NEXT:    mov v1.d[1], x11
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vec3:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mov d4, v0.d[1]
+; CHECK-GI-NEXT:    mov d5, v2.d[1]
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d2
+; CHECK-GI-NEXT:    mov d0, v1.d[1]
+; CHECK-GI-NEXT:    mov d2, v3.d[1]
+; CHECK-GI-NEXT:    fmov x13, d3
+; CHECK-GI-NEXT:    mul x10, x8, x9
+; CHECK-GI-NEXT:    fmov x11, d5
+; CHECK-GI-NEXT:    fmov x15, d2
+; CHECK-GI-NEXT:    umulh x8, x8, x9
+; CHECK-GI-NEXT:    fmov x9, d4
+; CHECK-GI-NEXT:    mul x12, x9, x11
+; CHECK-GI-NEXT:    umulh x9, x9, x11
+; CHECK-GI-NEXT:    fmov x11, d1
+; CHECK-GI-NEXT:    extr x8, x8, x10, #32
+; CHECK-GI-NEXT:    mul x14, x11, x13
+; CHECK-GI-NEXT:    umulh x11, x11, x13
+; CHECK-GI-NEXT:    fmov x13, d0
+; CHECK-GI-NEXT:    fmov d0, x8
+; CHECK-GI-NEXT:    extr x9, x9, x12, #32
+; CHECK-GI-NEXT:    mul x16, x13, x15
+; CHECK-GI-NEXT:    mov v0.d[1], x9
+; CHECK-GI-NEXT:    umulh x13, x13, x15
+; CHECK-GI-NEXT:    extr x10, x11, x14, #32
+; CHECK-GI-NEXT:    fmov d1, x10
+; CHECK-GI-NEXT:    extr x11, x13, x16, #32
+; CHECK-GI-NEXT:    mov v1.d[1], x11
+; CHECK-GI-NEXT:    ret
   %tmp = call <4 x i64> @llvm.umul.fix.v4i64(<4 x i64> %x, <4 x i64> %y, i32 32)
   ret <4 x i64> %tmp
 }
 
 define <4 x i16> @widemul(<4 x i16> %x, <4 x i16> %y) nounwind {
-; CHECK-LABEL: widemul:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    umull v0.4s, v0.4h, v1.4h
-; CHECK-NEXT:    shrn v1.4h, v0.4s, #16
-; CHECK-NEXT:    xtn v2.4h, v0.4s
-; CHECK-NEXT:    shl v0.4h, v1.4h, #12
-; CHECK-NEXT:    usra v0.4h, v2.4h, #4
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: widemul:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    umull v0.4s, v0.4h, v1.4h
+; CHECK-SD-NEXT:    shrn v1.4h, v0.4s, #16
+; CHECK-SD-NEXT:    xtn v2.4h, v0.4s
+; CHECK-SD-NEXT:    shl v0.4h, v1.4h, #12
+; CHECK-SD-NEXT:    usra v0.4h, v2.4h, #4
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: widemul:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    umull v0.4s, v0.4h, v1.4h
+; CHECK-GI-NEXT:    shrn v0.4h, v0.4s, #4
+; CHECK-GI-NEXT:    ret
   %tmp = call <4 x i16> @llvm.umul.fix.v4i16(<4 x i16> %x, <4 x i16> %y, i32 4)
   ret <4 x i16> %tmp
 }

>From 3650f40129c6edbe3d84e00217e77a90380a007e Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Mon, 11 May 2026 23:01:56 +0200
Subject: [PATCH 2/3] Test flags

---
 llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir | 2 +-
 llvm/test/CodeGen/AArch64/umul_fix.ll                     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
index 1ad22728793b8..d27fba2cc4091 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
@@ -1,5 +1,5 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -global-isel -mtriple=aarch64 -run-pass=legalizer %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64 -run-pass=legalizer %s -o - | FileCheck %s
 ---
 name:            smulfix_i32_scale_0
 body:             |
diff --git a/llvm/test/CodeGen/AArch64/umul_fix.ll b/llvm/test/CodeGen/AArch64/umul_fix.ll
index 29862369b8a08..986dc40a744fe 100644
--- a/llvm/test/CodeGen/AArch64/umul_fix.ll
+++ b/llvm/test/CodeGen/AArch64/umul_fix.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc < %s -mtriple=aarch64-linux-gnu -global-isel=0 | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc < %s -mtriple=aarch64-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define i32 @func(i32 %x, i32 %y) nounwind {

>From 6bf548bac521b1c861f7dc1e114bae393b8fcc26 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 12 May 2026 09:29:28 +0200
Subject: [PATCH 3/3] Use logical shift right for unsigned case

---
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    |  8 ++++--
 .../AArch64/GlobalISel/legalize-umulfix.mir   | 28 +++++++++----------
 llvm/test/CodeGen/AArch64/umul_fix.ll         |  4 +--
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 4b8276f9b77e0..e6e385b81fa7a 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -10675,7 +10675,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMulfix(MachineInstr &MI) {
 
   LLT WideTy = Ty.changeElementSize(Ty.getScalarSizeInBits() * 2);
   auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Scale);
-  MachineInstrBuilder ExtLHS{}, ExtRHS{};
+  MachineInstrBuilder ExtLHS{}, ExtRHS{}, Shift{};
   if (MI.getOpcode() == TargetOpcode::G_SMULFIX) {
     ExtLHS = MIRBuilder.buildSExt(WideTy, LHS);
     ExtRHS = MIRBuilder.buildSExt(WideTy, RHS);
@@ -10685,7 +10685,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMulfix(MachineInstr &MI) {
   }
 
   auto Mul = MIRBuilder.buildMul(WideTy, ExtLHS, ExtRHS);
-  auto Shift = MIRBuilder.buildAShr(WideTy, Mul, ShiftAmt);
+  if (MI.getOpcode() == TargetOpcode::G_SMULFIX)
+    Shift = MIRBuilder.buildAShr(WideTy, Mul, ShiftAmt);
+  else
+    Shift = MIRBuilder.buildLShr(WideTy, Mul, ShiftAmt);
+
   MIRBuilder.buildTrunc(Dst, Shift);
 
   MI.eraseFromParent();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
index d27fba2cc4091..5d57177816db1 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-umulfix.mir
@@ -35,8 +35,8 @@ body:             |
     ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[COPY]](i32)
     ; CHECK-NEXT: [[ZEXT1:%[0-9]+]]:_(i64) = G_ZEXT [[COPY1]](i32)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i64) = G_MUL [[ZEXT]], [[ZEXT1]]
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(i64) = G_ASHR [[MUL]], [[C]](i64)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i32) = G_TRUNC [[ASHR]](i64)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(i64) = G_LSHR [[MUL]], [[C]](i64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i32) = G_TRUNC [[LSHR]](i64)
     ; CHECK-NEXT: $w0 = COPY [[TRUNC]](i32)
     ; CHECK-NEXT: RET_ReallyLR implicit $w0
     %0:_(i32) = COPY $w0
@@ -97,10 +97,10 @@ body:             |
     ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV3]](<2 x i32>)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT]], [[ZEXT2]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT1]], [[ZEXT3]]
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
-    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
-    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR1]](<2 x i64>)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<2 x i64>) = G_LSHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<2 x i64>) = G_LSHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[LSHR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[LSHR1]](<2 x i64>)
     ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x i32>) = G_CONCAT_VECTORS [[TRUNC]](<2 x i32>), [[TRUNC1]](<2 x i32>)
     ; CHECK-NEXT: $q0 = COPY [[CONCAT_VECTORS]](<4 x i32>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
@@ -131,10 +131,10 @@ body:             |
     ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV3]](<2 x i32>)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT]], [[ZEXT2]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT1]], [[ZEXT3]]
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
-    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
-    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR1]](<2 x i64>)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<2 x i64>) = G_LSHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<2 x i64>) = G_LSHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[LSHR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[LSHR1]](<2 x i64>)
     ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x i32>) = G_CONCAT_VECTORS [[TRUNC]](<2 x i32>), [[TRUNC1]](<2 x i32>)
     ; CHECK-NEXT: $q0 = COPY [[CONCAT_VECTORS]](<4 x i32>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
@@ -164,10 +164,10 @@ body:             |
     ; CHECK-NEXT: [[ZEXT3:%[0-9]+]]:_(<2 x i64>) = G_ZEXT [[UV3]](<2 x i32>)
     ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT]], [[ZEXT2]]
     ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<2 x i64>) = G_MUL [[ZEXT1]], [[ZEXT3]]
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
-    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(<2 x i64>) = G_ASHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR]](<2 x i64>)
-    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[ASHR1]](<2 x i64>)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<2 x i64>) = G_LSHR [[MUL]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<2 x i64>) = G_LSHR [[MUL1]], [[BUILD_VECTOR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[LSHR]](<2 x i64>)
+    ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<2 x i32>) = G_TRUNC [[LSHR1]](<2 x i64>)
     ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x i32>) = G_CONCAT_VECTORS [[TRUNC]](<2 x i32>), [[TRUNC1]](<2 x i32>)
     ; CHECK-NEXT: $q0 = COPY [[CONCAT_VECTORS]](<4 x i32>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
diff --git a/llvm/test/CodeGen/AArch64/umul_fix.ll b/llvm/test/CodeGen/AArch64/umul_fix.ll
index 986dc40a744fe..0656f5e17b30e 100644
--- a/llvm/test/CodeGen/AArch64/umul_fix.ll
+++ b/llvm/test/CodeGen/AArch64/umul_fix.ll
@@ -13,7 +13,7 @@ define i32 @func(i32 %x, i32 %y) nounwind {
 ; CHECK-GI-LABEL: func:
 ; CHECK-GI:       // %bb.0:
 ; CHECK-GI-NEXT:    umull x8, w0, w1
-; CHECK-GI-NEXT:    asr x0, x8, #2
+; CHECK-GI-NEXT:    lsr x0, x8, #2
 ; CHECK-GI-NEXT:    // kill: def $w0 killed $w0 killed $x0
 ; CHECK-GI-NEXT:    ret
   %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 2)
@@ -45,7 +45,7 @@ define i4 @func3(i4 %x, i4 %y) nounwind {
 ; CHECK-GI-NEXT:    and w8, w0, #0xf
 ; CHECK-GI-NEXT:    and w9, w1, #0xf
 ; CHECK-GI-NEXT:    mul w8, w8, w9
-; CHECK-GI-NEXT:    sbfx w0, w8, #2, #6
+; CHECK-GI-NEXT:    lsr w0, w8, #2
 ; CHECK-GI-NEXT:    ret
   %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 2)
   ret i4 %tmp



More information about the llvm-commits mailing list