I am writing an LLVM pass that needs to convert an integer type into various floating point types. I am trying to use the UIToFp instruction to convert the integer value into a floating point value. As a basic test case I am using code similar to
Value* promotedRandom = Builder.CreateUIToFP(ConstantInt::get(Type::getInt32Ty(M.getContext()), 4), Type::getFloatTy(M.getContext()));
where Builder is an instance of IRBuilder for my function. However for some reason this value is 0 instead of 4 after the conversion which I can confirm by printing the value. Strangely if the type argument to CreateUIToFP is a double type instead of a float type the correct answer of 4 is printed instead. In the documentation of UIToFP below I don't see any reason for this behavior occurring. What is the cause of this problem and how should it be fixed.
Convert an unsigned integer constant to the corresponding floating-point constant. TYPE must be a scalar or vector floating-point type. CST must be of scalar or vector integer type. Both CST and TYPE must be scalars, or vectors of the same number of elements.
Additionally if i compile this code with clang
int main(){
int test = 4;
float test2 = (float)test;
printf("%f\n", test2);
}
I get the following instructions
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca float, align 4
store i32 4, i32* %1, align 4
%3 = load i32, i32* %1, align 4
%4 = sitofp i32 %3 to float
store float %4, float* %2, align 4
%5 = load float, float* %2, align 4
%6 = fpext float %5 to double
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), double %6)
ret i32 0
}
which shows sitofp and integer to float conversion working correctly. Even though im uitofp instead of sitofp, I have tried both and neither work.
I see the problem was that printf does not take a float as an argument. When floats are passed to printf they are promoted to doubles. When I took the float value and then promoted it to a double value the code worked correctly.