[llvm] [LLVM][Intrinsics] Adds an API to automatically resolve overload types (PR #169007)
Durgadoss R via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 20 23:48:47 PST 2025
================
@@ -197,4 +197,169 @@ TEST(IntrinsicAttributes, TestGetFnAttributesBug) {
AttributeSet AS = getFnAttributes(Context, experimental_guard);
EXPECT_FALSE(AS.hasAttributes());
}
+
+// Tests non-overloaded intrinsic declaration.
+TEST_F(IntrinsicsTest, NonOverloadedIntrinsic) {
+ Type *RetTy = Type::getVoidTy(Context);
+ SmallVector<Type *, 1> ArgTys;
+ ArgTys.push_back(Type::getInt1Ty(Context));
+
+ Function *F = Intrinsic::getOrInsertDeclaration(M.get(), Intrinsic::assume,
+ RetTy, ArgTys);
+
+ ASSERT_NE(F, nullptr);
+ EXPECT_EQ(F->getIntrinsicID(), Intrinsic::assume);
+ EXPECT_EQ(F->getReturnType(), RetTy);
+ EXPECT_EQ(F->arg_size(), 1u);
+ EXPECT_FALSE(F->isVarArg());
+ EXPECT_EQ(F->getName(), "llvm.assume");
+}
+
+// Tests overloaded intrinsic with automatic type resolution for scalar types.
+TEST_F(IntrinsicsTest, OverloadedIntrinsicScalar) {
+ Type *RetTy = Type::getInt32Ty(Context);
+ SmallVector<Type *, 2> ArgTys;
+ ArgTys.push_back(Type::getInt32Ty(Context));
+ ArgTys.push_back(Type::getInt32Ty(Context));
+
+ Function *F = Intrinsic::getOrInsertDeclaration(M.get(), Intrinsic::umax,
+ RetTy, ArgTys);
+
+ ASSERT_NE(F, nullptr);
+ EXPECT_EQ(F->getIntrinsicID(), Intrinsic::umax);
+ EXPECT_EQ(F->getReturnType(), RetTy);
+ EXPECT_EQ(F->arg_size(), 2u);
+ EXPECT_FALSE(F->isVarArg());
+ EXPECT_EQ(F->getName(), "llvm.umax.i32");
+}
+
+// Tests overloaded intrinsic with automatic type resolution for vector types.
+TEST_F(IntrinsicsTest, OverloadedIntrinsicVector) {
+ Type *RetTy = FixedVectorType::get(Type::getInt32Ty(Context), 4);
+ SmallVector<Type *, 2> ArgTys;
+ ArgTys.push_back(RetTy);
+ ArgTys.push_back(RetTy);
+
+ Function *F = Intrinsic::getOrInsertDeclaration(M.get(), Intrinsic::umax,
+ RetTy, ArgTys);
+
+ ASSERT_NE(F, nullptr);
+ EXPECT_EQ(F->getIntrinsicID(), Intrinsic::umax);
+ EXPECT_EQ(F->getReturnType(), RetTy);
+ EXPECT_EQ(F->arg_size(), 2u);
+ EXPECT_FALSE(F->isVarArg());
+ EXPECT_EQ(F->getName(), "llvm.umax.v4i32");
+}
+
+// Tests vararg intrinsic declaration.
+TEST_F(IntrinsicsTest, VarArgIntrinsicStatepoint) {
+ Type *RetTy = Type::getTokenTy(Context);
+ SmallVector<Type *, 5> ArgTys;
+ ArgTys.push_back(Type::getInt64Ty(Context)); // ID
+ ArgTys.push_back(Type::getInt32Ty(Context)); // NumPatchBytes
+ ArgTys.push_back(PointerType::get(Context, 0)); // Target
+ ArgTys.push_back(Type::getInt32Ty(Context)); // NumCallArgs
+ ArgTys.push_back(Type::getInt32Ty(Context)); // Flags
+
+ Function *F = Intrinsic::getOrInsertDeclaration(
+ M.get(), Intrinsic::experimental_gc_statepoint, RetTy, ArgTys);
+
+ ASSERT_NE(F, nullptr);
+ EXPECT_EQ(F->getIntrinsicID(), Intrinsic::experimental_gc_statepoint);
+ EXPECT_EQ(F->getReturnType(), RetTy);
+ EXPECT_EQ(F->arg_size(), 5u);
+ EXPECT_TRUE(F->isVarArg()) << "experimental_gc_statepoint must be vararg";
+ EXPECT_EQ(F->getName(), "llvm.experimental.gc.statepoint.p0");
+}
+
+// Tests that different overloads create different declarations.
+TEST_F(IntrinsicsTest, DifferentOverloads) {
+ // i32 version
+ Type *RetTy32 = Type::getInt32Ty(Context);
+ SmallVector<Type *, 2> ArgTys32;
+ ArgTys32.push_back(Type::getInt32Ty(Context));
+ ArgTys32.push_back(Type::getInt32Ty(Context));
+
+ Function *F32 = Intrinsic::getOrInsertDeclaration(M.get(), Intrinsic::umax,
+ RetTy32, ArgTys32);
+
+ // i64 version
+ Type *RetTy64 = Type::getInt64Ty(Context);
+ SmallVector<Type *, 2> ArgTys64;
+ ArgTys64.push_back(Type::getInt64Ty(Context));
+ ArgTys64.push_back(Type::getInt64Ty(Context));
+
+ Function *F64 = Intrinsic::getOrInsertDeclaration(M.get(), Intrinsic::umax,
+ RetTy64, ArgTys64);
+
+ EXPECT_NE(F32, F64) << "Different overloads should be different functions";
+ EXPECT_EQ(F32->getName(), "llvm.umax.i32");
+ EXPECT_EQ(F64->getName(), "llvm.umax.i64");
+}
+
+// Tests IRBuilder::CreateIntrinsic with overloaded scalar type.
+TEST_F(IntrinsicsTest, IRBuilderCreateIntrinsicScalar) {
+ IRBuilder<> Builder(BB);
+
+ Type *RetTy = Type::getInt32Ty(Context);
+ SmallVector<Value *, 2> Args;
+ Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), 10));
+ Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), 20));
+
+ CallInst *CI = Builder.CreateIntrinsic(RetTy, Intrinsic::umax, Args);
+
+ ASSERT_NE(CI, nullptr);
+ EXPECT_EQ(CI->getIntrinsicID(), Intrinsic::umax);
+ EXPECT_EQ(CI->getType(), RetTy);
+ EXPECT_EQ(CI->arg_size(), 2u);
+ EXPECT_FALSE(CI->getCalledFunction()->isVarArg());
+}
+
+// Tests IRBuilder::CreateIntrinsic with overloaded vector type.
----------------
durga4github wrote:
Along with tests for scalar and vector types:
can we have a test for `overloads on pointers of different addr spaces`, if we can find one in llvm:: namespace (target agnostic) ?
https://github.com/llvm/llvm-project/pull/169007
More information about the llvm-commits
mailing list