Need help in understanding llvm optimization

Hi,

I have below code in C -

int main() {

double x,y;

x = 1e16;

y = (x + 1) - x;

printf(“y:%e\n”, y);

return 0;

}

llvm bitcode looks like this for this function -

; Function Attrs: nounwind uwtable

define dso_local i32 @main() local_unnamed_addr #0 {

entry:

%call = tail call i32 (i8*, …) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), double 0.000000e+00)

ret i32 0

}

I am not able to understand how addition and subtraction are performed in this code. There is no fadd or fsub instruction. How llvm knows that result of y is 0?

Is there any way to disable this in llvm?

Any help would be much appreciated.

Regards,

Sangeeta

Neither 1e16 or 1e16+1 can be accurately represented in a double. The largest integer than be accurately represented is 2^53. As the number gets larger floating sacrifices precision in the lower digits. Because of this 1e16 and 1e16+1 end up having the same representation. So the result of subtracting them is 0.0.

I am sorry to not make my question clear. My question is how this value is calculated without having fadd and fsub in IR?

The compiler constant folded it as an optimization. Was this compiled with optimization’s enabled?

Yes, with O1. Is there any way to disable constant folding for floating point computations?

You might find it useful to write functions that take arguments (of unknown value). If the function has external linkage (the default) then the compiler doesn’t know who else might call it and has to keep it around, even if it inlines some copies of it:

double foo(double x){
double y = (x + 1) - x;
return y;
}

If you compile it with “-c” or “-S” then you don’t need a main() at all.

Cool, thank you so much.