title: LLVM IR floating point cast
body: <p>Today I came across weird problem with floating point cast in LLVM IR. I'm using Windows 10, and llvm-3.5.2. I wrote this code in C:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  int main() {
    double b = 2.0;
    float c = b;
    printf("%d\n", c == 2.0); 
    return 0;
  }
  </code></pre>
  
  <p>And I used <code>clang -S -emit-llvm</code> and obtained this LLVM IR:</p>
  
  <pre><code>@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
  
  ; Function Attrs: nounwind
  define i32 @main() #0 {
  entry:
    %retval = alloca i32, align 4
    %b = alloca double, align 8
    %c = alloca float, align 4
    store i32 0, i32* %retval
    store double 2.000000e+00, double* %b, align 8
    %0 = load double* %b, align 8
    %conv = fptrunc double %0 to float
    store float %conv, float* %c, align 4
    %1 = load float* %c, align 4
    %conv1 = fpext float %1 to double
    %cmp = fcmp oeq double %conv1, 2.000000e+00
    %conv2 = zext i1 %cmp to i32
    %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %conv2) #1
    ret i32 0
  }
  
  ; Function Attrs: nounwind
  declare i32 @printf(i8*, ...) #0
  </code></pre>
  
  <p>Which executed (after <code>llvm-as</code> and <code>lli</code>) gave an incorrect result of <code>0</code> !</p>
  
  <p>The problem seems to be in <code>fpext</code> which isn't very intuitive, because it should be this 'safe' conversion (better direction than <code>fptrunc</code> which is from double to float).</p>
  
  <p>I think so, because when I change this line:</p>
  
  <p><code>%cmp = fcmp oeq double %conv1, 2.000000e+00</code></p>
  
  <p>to this:</p>
  
  <p><code>%cmp = fcmp oeq float %1, 2.000000e+00</code></p>
  
  <p>then the result is as expected <code>1</code>.</p>
  
  <p>So my question is why is it like that, why this conversion fails? Is this some kind of a bug in LLVM? Or there exists some better way of this type of conversion? Or maybe I wrote an unsafe code in C? If so, then there is a huge problem in using floats. I don't have an influence on clang when performing this conversions. For example let's say that I want to output <code>c</code> above. Then I write <code>printf("%f", c)</code> and clang generates code that casts <code>c</code> to double before passing it to <code>printf</code>. And the result is incorrect again. So how to safely print a float? How to safely use floats at all?</p>
  
  <p>I'm not sure whether this problem appears on Linux too.</p>