[llvm-dev] Implementing a proposed InstCombine optimization
Carlos Liam via llvm-dev
llvm-dev at lists.llvm.org
Thu Apr 7 10:06:23 PDT 2016
@escha:
Alive-NJ (https://github.com/rutgers-apl/alive-nj) verifies the optimization as correct for half, single and double floating-point types:
carloss-mbp:alive-nj aarzee$ python run.py ~/floatcast.opt
----------
Name: /Users/aarzee/floatcast.opt#1:xor->fsub
Pre: isSignBit(C)
%x = bitcast %A
%y = xor %x, C
%z = bitcast %y
=>
%z = fsub -0.0, %A
Done: 3
Optimization is correct
However, I'm not entirely familiar with the machinery behind Alive-NJ and whether the concerns you raise are covered.
@Sanjay:
This is what I have so far, with necessary changes marked as XXX:
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 8ca0e50..e08881d 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1748,7 +1748,7 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
// E.g. (icmp sgt x, n) | (icmp slt x, 0) --> icmp ugt x, n
if (Value *V = simplifyRangeCheck(RHS, LHS, /*Inverted=*/true))
return V;
-
+
// This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
if (!LHSCst || !RHSCst) return nullptr;
@@ -2748,5 +2748,19 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
}
}
+ // If we are XORing the sign bit of a floating-point value, convert
+ // this to fsub from -0.0, then cast back to integer.
+ ConstantInt *CI;
+ if (isa<BitCastInst>(Op0C) && SrcTy->isFloatingPointTy() &&
+ match(Op1, m_ConstantInt(CI)) && CI->isSignBit(true)) {
+ // XXX ^ changed to isSignBit
+ Module *M = I.getModule();
+ Function *Fabs = Intrinsic::getDeclaration(M, Intrinsic::fabs, SrcTy);
+ // ^ XXX this is wrong; I need the equivalent of fsub -0.0, M
+ Value *Call = Builder->CreateCall(Fabs, Op0COp, "fabs");
+ // ^ XXX also wrong
+ return CastInst::CreateBitOrPointerCast(Call, I.getType());
+ }
+
return Changed ? &I : nullptr;
}
The whitespace change is an artifact from my text editor.
- CL
> On Apr 7, 2016, at 12:43 PM, escha at apple.com wrote:
>
> I am not entirely sure this is safe. Transforming this to an fsub could change the value stored on platforms that implement negates using arithmetic instead of with bitmath (such as ours) and either canonicalize NaNs or don’t support denormals. This is actually important because this kind of bitmath on floats is very commonly used as part of algorithms for complex math functions that need to get precise bit patterns from the source (similarly for the transformation of masking off the sign bit -> fabs). It’s also important because if the float happens to “really” be an integer, it’s highly likely we’ll end up zero-flushing it and losing the data.
>
> Example:
>
> a = load float
> b = bitcast a to int
> c = xor b, signbit
> d = bitcast c to float
> store d
>
> Personally I would feel this is safe if and only if the float is coming from an arithmetic operation — in that case, we know that doing another arithmetic operation on it should be safe, since it’s already canonalized and can’t be a denorm [if the platform doesn’t support them].
>
> I say this coming only a few weeks after our team spent literally dozens of human-hours tracking down an extremely obscure bug involving a GL conformance test in which ints were casted to floats, manipulated with float instructions, then sent back to int, resulting in the ints being flushed to zero and the test failing.
>
> —escha
>
>> On Apr 7, 2016, at 9:09 AM, Sanjay Patel via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>>
>> Hi Carlos -
>>
>> That sounds like a good patch.
>>
>> Warning - following the link below may remove some of the educational joy for the immediate task at hand:
>> http://reviews.llvm.org/D13076
>>
>> ...but I wouldn't worry too much, there's plenty more opportunity where that came from. :)
>>
>> Feel free to post follow-up questions here or via a patch review on Phabricator:
>> http://llvm.org/docs/Phabricator.html
>>
>>
>> On Thu, Apr 7, 2016 at 7:17 AM, Carlos Liam via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>> Hi,
>>
>> I'm interested in implementing an InstCombine optimization that I discovered and verified with Alive-NJ (with the help of the authors of Alive-NJ). The optimization is described in Alive-NJ format as follows:
>>
>> Name: xor->fsub
>> Pre: isSignBit(C)
>> %x = bitcast %A
>> %y = xor %x, C
>> %z = bitcast %y
>> =>
>> %z = fsub -0.0, %A
>>
>> Effectively the optimization targets code that casts a float to an int with the same width, XORs the sign bit, and casts back to float, and replaces it with a subtraction from -0.0.
>>
>> I am not very familiar with C++ or the LLVM codebase so I would greatly appreciate some help in writing a patch adding this optimization.
>>
>> Thanks in advance.
>>
>> - CL
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
More information about the llvm-dev
mailing list