-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Transforms] Resolve FIXME: No Lowering of FNeg to FMul unless it is safe #85252
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-transforms Author: AtariDreams (AtariDreams) ChangesOr association flags are specified. Full diff: https://github.com/llvm/llvm-project/pull/85252.diff 1 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index d91320863e241d..f44608624cf3df 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -287,11 +287,17 @@ static Instruction *CreateNeg(Value *S1, const Twine &Name,
static BinaryOperator *LowerNegateToMultiply(Instruction *Neg) {
assert((isa<UnaryOperator>(Neg) || isa<BinaryOperator>(Neg)) &&
"Expected a Negate!");
- // FIXME: It's not safe to lower a unary FNeg into a FMul by -1.0.
unsigned OpNo = isa<BinaryOperator>(Neg) ? 1 : 0;
Type *Ty = Neg->getType();
- Constant *NegOne = Ty->isIntOrIntVectorTy() ?
- ConstantInt::getAllOnesValue(Ty) : ConstantFP::get(Ty, -1.0);
+
+ // Only lower to FMul if the operation is not a unary FNeg or Neg has the
+ // correct flags.
+ if (Ty->isFloatingPointTy() && isa<UnaryOperator>(Neg) &&
+ !hasFPAssociativeFlags(Neg))
+ return nullptr;
+
+ Constant *NegOne = Ty->isIntOrIntVectorTy() ? ConstantInt::getAllOnesValue(Ty)
+ : ConstantFP::get(Ty, -1.0);
BinaryOperator *Res =
CreateMul(Neg->getOperand(OpNo), NegOne, "", Neg->getIterator(), Neg);
|
Could you please provide the proof? I cannot prove the correctness with alive2. |
https://alive2.llvm.org/ce/z/Ki3Rf2
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
cf284e9
to
199fb5e
Compare
…safe or flags are specified
In this context, it's not simply doing this transform in isolation. It's being consumed by another canonicalizing operation. The problem is this is introducing a canonicalization, which doesn't matter if it's only used by operations that canonicalize the inputs. nnan would not be sufficient to introduce this, since operations may also do other bit pattern changing side effects (like denormal flush). Since this is consumed by a canonicalizing operation, it's either correct to always do (in the has one use case) (or it's wrong to ever do). |
ConstantInt::getAllOnesValue(Ty) : ConstantFP::get(Ty, -1.0); | ||
// Only lower to FMul if the operation is not a unary FNeg or Neg has the | ||
// correct flags. | ||
if (Ty->isFPOrFPVectorTy() && isa<UnaryOperator>(Neg) && !Neg->hasNoNaNs()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to directly check for fneg? isa that's floating point type isn't really obvious
%b = fmul fast float %a, -2.0 | ||
%neg = fneg fast float %a | ||
%mul = fmul fast float %neg, %b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need the full set of fast flags. Also don't need it on every instruction. Should target testing missing specific flags contexts
%neg = fneg fast nnan <4 x float> %a | ||
%mul = fmul fast <4 x float> %neg, %b | ||
ret <4 x float> %mul | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add test where it's know not-nan from the source
I guess we technically don't guarantee canonicalization on FP operations, but I think we can assert that it may happen |
Or association flags are specified.