Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Clang optimizing this code out?

The purpose of the code is to find the total number of 32-bit floating point bit patterns which represent values between 0 and 1. It seems to me this should work, but for some reason the assembly output from Clang is basically the equivalent of return 0;.

I compiled this with Clang 3.3 and Clang 3.4.1, using -std=c++1y -Wall -Wextra -pedantic -O2 and -std=c++1y -Wall -Wextra -pedantic -O3

Clang 3.4 optimizes everything away with -O2 and -O3.

Clang 3.3 only optimizes everything away with -O3.

By "optimizes everything away" I mean that this is the assembly output of the program:

main:                                   # @main     xorl    %eax, %eax     ret 
#include <limits> #include <cstring> #include <cstdint>  template <class TO, class FROM> inline TO punning_cast(const FROM &input) {     TO out;     std::memcpy(&out, &input, sizeof(TO));     return out; }  int main() {     uint32_t i = std::numeric_limits<uint32_t>::min();     uint32_t count = 0;      while (1)     {         float n = punning_cast<float>(i);         if(n >= 0.0f && n <= 1.0f)             count++;         if (i == std::numeric_limits<uint32_t>::max())             break;         i++;     }      return count; } 
like image 442
Chris_F Avatar asked May 23 '14 21:05

Chris_F


1 Answers

Here's a simpler test case which points out that it's a compiler bug:

http://coliru.stacked-crooked.com/a/58b3f9b4edd8e373

#include <cstdint>  int main() {     uint32_t i = 0;     uint32_t count = 1;      while (1)     {         if( i < 5 )             count+=1;          if (i == 0xFFFFFFFF)             break;         i++;     }      return count; // should return 6 } 

The assembly shows that it outputs 1, instead of 6. It doesn't think it's an infinite loop either, in which case the assembly doesn't return from main.

like image 118
mukunda Avatar answered Sep 27 '22 23:09

mukunda