I was trying to understand how intrinsics are implemented in LLVM. In Intrinsics.td file at path llvm/IR/Intrinsics.td, following commenta are present for the class LLVMatchType :
// Match the type of another intrinsic parameter. Number is an index into the
// list of overloaded types for the intrinsic, excluding all the fixed types.
// The Number value must refer to a previously listed type. For example:
// Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]>
// has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0>
// refers to the first overloaded type, which is the 2nd argument.
What is meant by âfixed typesâ here?
What are âoverloaded typesâ and how can we do overloading in tablegen?
In the example give in these comments, does âLLVMMatchType<0>â refers to âllvm_anyfloat_tyâ? If yes, why âLLVMMatchType<0>â has been used while we could have just used âllvm_anyfloat_tyâ directly?
âFixed typesâ are the ones that cannot change, like plain llvm_i32_ty. You donât need to use them with LLVMMatchType because you can just write down the original type again and get exactly the same thing.
âOverloaded typesâ are the ones that can take multiple values and the user has to decide what the actual type is (within the constraints) when creating the intrinsic. In that example thereâs llvm_anyfloat_ty.
Using llvm_anyfloat_ty a second time would mean the types donât have to be the same, but often intrinsics need their two operands (& result) to be the same type. So for a contrived example we could have
Then the only declarations you could write for the first one have the argument and return types the same. Theyâd look like declare float @llvm.increment.f32(float %in). But for the second you could write declare float @llvm.bad.increment.f32.f64(double) which the writer may not want to deal with.