[llvm] UMULH example (PR #161224)

David Green via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 29 09:24:13 PDT 2025


https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/161224

None

>From 29db710b583cebb82756389d1142ce722f52908a Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 29 Sep 2025 17:22:56 +0100
Subject: [PATCH] UMULH test

---
 llvm/lib/Transforms/Vectorize/VPlan.h             |  2 ++
 llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp   |  1 +
 llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h |  6 ++++++
 llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp    | 15 +++++++++++++++
 llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp | 15 +++++++++++++++
 5 files changed, 39 insertions(+)

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 0822511150e9e..6b50e286d5f1b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1063,6 +1063,8 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
     ResumeForEpilogue,
     /// Returns the value for vscale.
     VScale,
+    /// mulh
+    UMulh,
   };
 
   /// Returns true if this VPInstruction generates scalar values for all lanes.
diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
index 07bfe7a896d86..d083cc6a6d102 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
@@ -75,6 +75,7 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) {
   case Instruction::Freeze:
   case VPInstruction::ReductionStartVector:
   case VPInstruction::ResumeForEpilogue:
+  case VPInstruction::UMulh:
     return inferScalarType(R->getOperand(0));
   case Instruction::Select: {
     Type *ResTy = inferScalarType(R->getOperand(1));
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index 555efea1ea840..3ab6429218f91 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -449,6 +449,12 @@ inline AllRecipe_match<Instruction::Mul, Op0_t, Op1_t> m_Mul(const Op0_t &Op0,
   return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
 }
 
+template <typename Op0_t, typename Op1_t>
+inline AllRecipe_match<Instruction::LShr, Op0_t, Op1_t>
+m_LShr(const Op0_t &Op0, const Op1_t &Op1) {
+  return m_Binary<Instruction::LShr, Op0_t, Op1_t>(Op0, Op1);
+}
+
 template <typename Op0_t, typename Op1_t>
 inline AllRecipe_commutative_match<Instruction::Mul, Op0_t, Op1_t>
 m_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index b5e30cb1fa655..53f97f232d11e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -510,6 +510,7 @@ unsigned VPInstruction::getNumOperandsForOpcode(unsigned Opcode) {
   case Instruction::ICmp:
   case Instruction::FCmp:
   case Instruction::Store:
+  case VPInstruction::UMulh:
   case VPInstruction::BranchOnCount:
   case VPInstruction::ComputeReductionResult:
   case VPInstruction::FirstOrderRecurrenceSplice:
@@ -892,6 +893,17 @@ Value *VPInstruction::generate(VPTransformState &State) {
     Value *B = State.get(getOperand(1));
     return Builder.CreateLogicalAnd(A, B, Name);
   }
+  case VPInstruction::UMulh: {
+    Value *A = State.get(getOperand(0));
+    Value *B = State.get(getOperand(1));
+    Type *DblTy = A->getType()->getWithNewBitWidth(A->getType()->getScalarSizeInBits()*2);
+    return Builder.CreateTrunc(
+        Builder.CreateLShr(
+            Builder.CreateMul(Builder.CreateZExt(A, DblTy),
+                              Builder.CreateZExt(B, DblTy), Name),
+            ConstantInt::get(DblTy, A->getType()->getScalarSizeInBits())),
+        A->getType());
+  }
   case VPInstruction::PtrAdd: {
     assert(vputils::onlyFirstLaneUsed(this) &&
            "can only generate first lane for PtrAdd");
@@ -1400,6 +1412,9 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent,
   case VPInstruction::ResumeForEpilogue:
     O << "resume-for-epilogue";
     break;
+  case VPInstruction::UMulh:
+    O << "umulh";
+    break;
   default:
     O << Instruction::getOpcodeName(getOpcode());
   }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 5252e1f928294..9302ea68c95e8 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -3630,6 +3630,21 @@ void VPlanTransforms::convertToAbstractRecipes(VPlan &Plan, VPCostContext &Ctx,
     for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
       if (auto *Red = dyn_cast<VPReductionRecipe>(&R))
         tryToCreateAbstractReductionRecipe(Red, Ctx, Range);
+
+      if (auto *VP = dyn_cast<VPWidenCastRecipe>(&R)) {
+        VPValue *A, *B;
+        Type *Ty = Ctx.Types.inferScalarType(VP);
+        if (match(VP, m_Trunc(m_LShr(
+                          m_Mul(m_ZExt(m_VPValue(A)), m_ZExt(m_VPValue(B))),
+                          m_SpecificInt(Ty->getScalarSizeInBits())))) &&
+            Ctx.Types.inferScalarType(A) == Ctx.Types.inferScalarType(B) &&
+            Ctx.Types.inferScalarType(A) == Ty) {
+          dbgs() << "UMulh Matched\n";
+          auto Mulh = new VPInstruction(VPInstruction::UMulh, {A, B});
+          Mulh->insertBefore(*VPBB, R.getIterator());
+          VP->replaceAllUsesWith(Mulh);
+        }
+      }
     }
   }
 }



More information about the llvm-commits mailing list