Skip to content

Conversation

AMS21
Copy link
Contributor

@AMS21 AMS21 commented Oct 8, 2025

Upstreaming the LLVMBuildMinNum and LLVMBuildMaxNum functions to create calls to the minnum and maxnum intrinsics.

@AMS21 AMS21 requested a review from nikic as a code owner October 8, 2025 15:41
@llvmbot llvmbot added the llvm:ir label Oct 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-llvm-ir

Author: None (AMS21)

Changes

Upstreaming the LLVMBuildMinNum and LLVMBuildMaxNum functions to create calls to the minnum and maxnum intrinsics.


Full diff: https://github.com/llvm/llvm-project/pull/162500.diff

4 Files Affected:

  • (modified) llvm/docs/ReleaseNotes.md (+1)
  • (modified) llvm/include/llvm-c/Core.h (+20)
  • (modified) llvm/lib/IR/Core.cpp (+10)
  • (modified) llvm/unittests/IR/InstructionsTest.cpp (+23)
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 79d93d08b8398..15c9aaf3b129b 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -147,6 +147,7 @@ Changes to the C API
 --------------------
 
 * Add `LLVMGetOrInsertFunction` to get or insert a function, replacing the combination of `LLVMGetNamedFunction` and `LLVMAddFunction`.
+* Add `LLVMBuildMinNum` and `LLVMBuildMaxNum` to create calls to the `minnum` and `maxnum` intrinsics.
 
 Changes to the CodeGen infrastructure
 -------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 3d22f85911e78..2d66050b5acfa 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -4626,6 +4626,26 @@ LLVM_C_ABI LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V,
 LLVM_C_ABI LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V,
                                      const char *Name);
 
+/**
+ * Creates and inserts a minnum intrinsic intruction.
+ *
+ * Returns the minimum of the two floating point values.
+ *
+ * @see llvm::IRBuilder::CreateMinNum()
+ */
+LLVM_C_ABI LLVMValueRef LLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS,
+                                        LLVMValueRef RHS);
+
+/**
+ * Creates and inserts a maxnum intrinsic intruction.
+ *
+ * Returns the maximum of the two floating point values.
+ *
+ * @see llvm::IRBuilder::CreateMaxNum()
+ */
+LLVM_C_ABI LLVMValueRef LLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS,
+                                        LLVMValueRef RHS);
+
 LLVM_C_ABI LLVMBool LLVMGetNUW(LLVMValueRef ArithInst);
 LLVM_C_ABI void LLVMSetNUW(LLVMValueRef ArithInst, LLVMBool HasNUW);
 LLVM_C_ABI LLVMBool LLVMGetNSW(LLVMValueRef ArithInst);
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 3f1cc1e4e6d0e..d0285fb4516fa 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -3804,6 +3804,16 @@ LLVMValueRef LLVMBuildNot(LLVMBuilderRef B, LLVMValueRef V, const char *Name) {
   return wrap(unwrap(B)->CreateNot(unwrap(V), Name));
 }
 
+LLVMValueRef LLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS,
+                             LLVMValueRef RHS) {
+  return wrap(unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS)));
+}
+
+LLVMValueRef LLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS,
+                             LLVMValueRef RHS) {
+  return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS)));
+}
+
 LLVMBool LLVMGetNUW(LLVMValueRef ArithInst) {
   Value *P = unwrap<Value>(ArithInst);
   return cast<Instruction>(P)->hasNoUnsignedWrap();
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index fe9e7e8228490..cb79a14d0ee7f 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -1933,5 +1933,28 @@ TEST(InstructionsTest, StripAndAccumulateConstantOffset) {
   EXPECT_TRUE(Offset.isZero());
 }
 
+TEST(InstructionsTest, LLVMBuildMinMaxNum) {
+  LLVMContext Ctx;
+  Module M("Mod", Ctx);
+  FunctionType *FT = FunctionType::get(Type::getVoidTy(Ctx), {}, false);
+  Function *F = Function::Create(FT, Function::ExternalLinkage, "f", M);
+  BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
+  IRBuilder<> B(BB);
+
+  Type *FTy = B.getFloatTy();
+  Value *LHS = ConstantFP::get(FTy, 1.0);
+  Value *RHS = ConstantFP::get(FTy, 2.0);
+
+  auto *Min = unwrap<CallInst>(LLVMBuildMinNum(wrap(&B), wrap(LHS), wrap(RHS)));
+  Function *MinFunc = Min->getCalledFunction();
+  EXPECT_EQ(MinFunc->getIntrinsicID(), Intrinsic::minnum);
+  EXPECT_EQ(Min->getType(), FTy);
+
+  auto *Max = unwrap<CallInst>(LLVMBuildMaxNum(wrap(&B), wrap(LHS), wrap(RHS)));
+  Function *MaxFunc = Max->getCalledFunction();
+  EXPECT_EQ(MaxFunc->getIntrinsicID(), Intrinsic::maxnum);
+  EXPECT_EQ(Max->getType(), FTy);
+}
+
 } // end anonymous namespace
 } // end namespace llvm

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

I'm not sure why we have these functions on the Rust side at all. minnum and maxnum are just normal intrinsics, so we should just do something like self.call_intrinsic("llvm.minnum", &[self.val_ty(lhs)], &[lhs, rhs]).

@nikic
Copy link
Contributor

nikic commented Oct 8, 2025

This also applies to all the LLVMRustBuildVectorReduceXYZ functions.

@AMS21
Copy link
Contributor Author

AMS21 commented Oct 8, 2025

I'm not sure why we have these functions on the Rust side at all. minnum and maxnum are just normal intrinsics, so we should just do something like self.call_intrinsic("llvm.minnum", &[self.val_ty(lhs)], &[lhs, rhs]).
This also applies to all the LLVMRustBuildVectorReduceXYZ functions.

Good question. Seems like they were added 8 Years ago with rust-lang/rust@7d5343a and rust-lang/rust@01cc5b3.
I'll close this and refactor this on the rust side instead :)

@AMS21 AMS21 closed this Oct 8, 2025
@AMS21 AMS21 deleted the upstream_build_min_max_num branch October 9, 2025 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants