title: Useless clang temporary in LLVM for `return 0` in simple C program
body: <p>I'm just getting started with LLVM. Consider the following programs.</p>
  <p><code>hello1.c</code></p>
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  
  int main(void)
  {
          printf(&quot;Hello, world!\n&quot;);
  }
  </code></pre>
  <p><code>hello2.c</code></p>
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdio.h&gt;
  
  int main(void)
  {
          printf(&quot;Hello, world!\n&quot;);
          return 0;
  }
  </code></pre>
  <p>These generate the following LLVM IR strings</p>
  <pre class="lang-sh prettyprint-override"><code>$ clang -S -emit-llvm -o hello1.ll hello1.c
  $ clang -S -emit-llvm -o hello2.ll hello2.c
  $ clang --version
  Debian clang version 11.0.1-2
  </code></pre>
  <p><code>hello1.ll</code></p>
  <pre><code>; ModuleID = 'res/c/hello.c'
  source_filename = &quot;res/c/hello.c&quot;
  target datalayout = &quot;e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128&quot;
  target triple = &quot;x86_64-pc-linux-gnu&quot;
  
  @.str = private unnamed_addr constant [15 x i8] c&quot;Hello, world!\0A\00&quot;, align 1
  
  ; Function Attrs: noinline nounwind optnone uwtable
  define dso_local i32 @main() #0 {
    %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i64 0, i64 0))
    ret i32 0
  }
  
  declare dso_local i32 @printf(i8*, ...) #1
  
  attributes #0 = { noinline nounwind optnone uwtable &quot;correctly-rounded-divide-sqrt-fp-math&quot;=&quot;false&quot; &quot;disable-tail-calls&quot;=&quot;false&quot; &quot;frame-pointer&quot;=&quot;all&quot; &quot;less-precise-fpmad&quot;=&quot;false&quot; &quot;min-legal-vector-width&quot;=&quot;0&quot; &quot;no-infs-fp-math&quot;=&quot;false&quot; &quot;no-jump-tables&quot;=&quot;false&quot; &quot;no-nans-fp-math&quot;=&quot;false&quot; &quot;no-signed-zeros-fp-math&quot;=&quot;false&quot; &quot;no-trapping-math&quot;=&quot;true&quot; &quot;stack-protector-buffer-size&quot;=&quot;8&quot; &quot;target-cpu&quot;=&quot;x86-64&quot; &quot;target-features&quot;=&quot;+cx8,+fxsr,+mmx,+sse,+sse2,+x87&quot; &quot;unsafe-fp-math&quot;=&quot;false&quot; &quot;use-soft-float&quot;=&quot;false&quot; }
  attributes #1 = { &quot;correctly-rounded-divide-sqrt-fp-math&quot;=&quot;false&quot; &quot;disable-tail-calls&quot;=&quot;false&quot; &quot;frame-pointer&quot;=&quot;all&quot; &quot;less-precise-fpmad&quot;=&quot;false&quot; &quot;no-infs-fp-math&quot;=&quot;false&quot; &quot;no-nans-fp-math&quot;=&quot;false&quot; &quot;no-signed-zeros-fp-math&quot;=&quot;false&quot; &quot;no-trapping-math&quot;=&quot;true&quot; &quot;stack-protector-buffer-size&quot;=&quot;8&quot; &quot;target-cpu&quot;=&quot;x86-64&quot; &quot;target-features&quot;=&quot;+cx8,+fxsr,+mmx,+sse,+sse2,+x87&quot; &quot;unsafe-fp-math&quot;=&quot;false&quot; &quot;use-soft-float&quot;=&quot;false&quot; }
  
  !llvm.module.flags = !{!0}
  !llvm.ident = !{!1}
  
  !0 = !{i32 1, !&quot;wchar_size&quot;, i32 4}
  !1 = !{!&quot;Debian clang version 11.0.1-2&quot;}
  </code></pre>
  <p><code>hello2.ll</code></p>
  <pre><code>; ....
  
  ; Function Attrs: noinline nounwind optnone uwtable
  define dso_local i32 @main() #0 {
    %1 = alloca i32, align 4
    store i32 0, i32* %1, align 4
    %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i64 0, i64 0))
    ret i32 0
  }
  
  ; ....
  </code></pre>
  <hr />
  <p>As you can see, the addition of the <code>return 0</code> appears to generate the allocation of a new stack temporary <code>%1</code> with value 0. It doesn't seem that this value is used anywhere. Even if I change the return stmt to, e.g., <code>return -1</code>, there is still the allocation and zeroing of the temporary <code>%1</code>, and the constant literal only appears in the return instruction <code>ret i32 -1</code>.</p>
  <p>I know that this will be inconsequential due to optimizations (e.g., live variable analysis). Is this an idiosyncrasy of the clang handling of return statements or is there a deeper reason for this?</p>