Bug in InstCombiner::FoldAndOfFCmps

Hey guys,

I’ve come across a bug when combining an AND of FCMPs. This bug occurs in my compiler as well as Clang built from trunk.

A reduced test case is:

int foo( float a, double b ) {
return (a == a) & (b == b);
}

and the error is:

Assertion failed: (getOperand(0)->getType() == getOperand(1)->getType() && “Both operands to FCmp instruction are not of the same type!”), function FCmpInst, file [snip]/clang/llvm/include/llvm/IR/Instructions.h, line 1117.

We begin with a float “a” and double “b”:

(fcmp oeq a, a) & (fcmp oeq b, b)

After canonicalization in InstCombine, we end up with the expression:

(fcmp ord a, 0.0) & (fcmp ord b, 0.0)

The bug manifest is in InstCombiner::FoldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS), when trying to perform this transformation:

(fcmp ord x, c) & (fcmp ord y, c) → (fcmp ord x, y)

This is all fine, except that the FCmpInst constructor in the IRBuilder requires that both operands to the new fcmp are the same type, which they are not.

Any suggestions on a proper fix for this issue? Some initial thoughts…

  1. The transformation could be suppressed if the operand types do not match.

  2. Cast the smaller operand to the type of the larger operand. Are there any unforeseen implications here?

In any case, I suspect that there may be other transformations that need similar checks also. If there is a clear solution, I will be happy to submit a patch. Otherwise, I will file a Bug.

Thanks in advance,
Cameron

I don't get any errors compiling this. Do you know if it was fixed? Do
you get an error only for some particular target? What is the 'clang
-cc1' command line that you seed in the error?

Cheers,
Rafael

I see this error in our compiler, but not with the trunk. I guess it's been fixed, but I don't know which commit did it.

-Krzysztof

I believe this is

http://llvm.org/viewvc/llvm-project?view=revision&revision=179417

An nice way to research for commits is the revision log if you know which file:

  http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?view=log

or just:
git log lib/Transforms/InstCombine/InstCombineAndOrXor.cpp