Optimizing functions using logical operators

Hi,

I’m looking at what the LLVM compilation chain does to optimize the following functions using logical operators. The one using integer type (t1 and t3) are optimized, but not the ones using float type (t2 and t4), even when using -O3 or -Ofast. Why is that ?

Thera are those kind of optimizations done in the LLVM source code?

Thanks.

bool t1(int v1)
{
    return (2 + v1) == 7;
}

bool t2(float v1)
{
    return (2.f + v1) == 7.f;
}

bool t3(int v1)
{
    return (2 * v1) > 0;
}

bool t4(float v1)
{
    return (2.f * v1) > 0;
}

; Function Attrs: norecurse nounwind readnone ssp uwtable
define zeroext i1 @_Z2t1i(i32) #0 {
  %2 = icmp eq i32 %0, 5
  ret i1 %2
}

; Function Attrs: norecurse nounwind readnone ssp uwtable
define zeroext i1 @_Z2t2f(float) #0 {
  %2 = fadd float %0, 2.000000e+00
  %3 = fcmp oeq float %2, 7.000000e+00
  ret i1 %3
}

; Function Attrs: norecurse nounwind readnone ssp uwtable
define zeroext i1 @_Z2t3i(i32) #0 {
  %2 = icmp sgt i32 %0, 0
  ret i1 %2
}

; Function Attrs: norecurse nounwind readnone ssp uwtable
define zeroext i1 @_Z2t4f(float) #0 {
  %2 = fmul float %0, 2.000000e+00
  %3 = fcmp ogt float %2, 0.000000e+00
  ret i1 %3
}

The main source for these sorts of peephole optimizations at the LLVM IR level is in instcombine, spread out over several files in lib/Transforms/InstCombine. Specifically, the relevant patterns are all in InstCombineCompares.

The floating point code is not optimized because there are no patterns specified that come close to covering these instructions. There are probably two main reasons for this. First, floating point optimizations are more dangerous to do floating point arithmetic not following normal rules of associativity (so it requires a lot more care to make sure that it is correct). Second, these optimizations probably don't kick in very often in real code. I've noticed that none of the major compilers optimize these expressions.

gcc does optimize t2 to just a compare under -Ofast. But clang does not.