-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Local] Move OverflowTracking to Local.h, move logic to helpers (NFC) #140403
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
base: main
Are you sure you want to change the base?
Conversation
Move parts of the logic used by Reassociate to OverflowTracking (mergeFlags & applyFlags) and move the definition to Local.h (not sure if there's a better place?). For now it just moves the NUW/NSW handling, as this matches the uses in LICM. I'll look into the FP math handling separately, as it looks like there's a difference between Reassociate (takes all flags from I, while LICM takes the intersection of the flags on both instructions).
@llvm/pr-subscribers-llvm-transforms Author: Florian Hahn (fhahn) ChangesMove parts of the logic used by Reassociate to OverflowTracking (mergeFlags & applyFlags) and move the definition to Local.h (not sure if there's a better place?). For now it just moves the NUW/NSW handling, as this matches the uses in LICM. I'll look into the FP math handling separately, as it looks like there's a difference between Reassociate (takes all flags from I, while LICM takes the intersection of the flags on both instructions). Full diff: https://github.com/llvm/llvm-project/pull/140403.diff 4 Files Affected:
diff --git a/llvm/include/llvm/Transforms/Scalar/Reassociate.h b/llvm/include/llvm/Transforms/Scalar/Reassociate.h
index 23b70164d96a4..a5d137661e11e 100644
--- a/llvm/include/llvm/Transforms/Scalar/Reassociate.h
+++ b/llvm/include/llvm/Transforms/Scalar/Reassociate.h
@@ -39,6 +39,7 @@ class Function;
class Instruction;
class IRBuilderBase;
class Value;
+struct OverflowTracking;
/// A private "module" namespace for types and utilities used by Reassociate.
/// These are implementation details and should not be used by clients.
@@ -64,17 +65,6 @@ struct Factor {
Factor(Value *Base, unsigned Power) : Base(Base), Power(Power) {}
};
-struct OverflowTracking {
- bool HasNUW = true;
- bool HasNSW = true;
- bool AllKnownNonNegative = true;
- bool AllKnownNonZero = true;
- // Note: AllKnownNonNegative can be true in a case where one of the operands
- // is negative, but one the operators is not NSW. AllKnownNonNegative should
- // not be used independently of HasNSW
- OverflowTracking() = default;
-};
-
class XorOpnd;
} // end namespace reassociate
@@ -115,7 +105,7 @@ class ReassociatePass : public PassInfoMixin<ReassociatePass> {
void ReassociateExpression(BinaryOperator *I);
void RewriteExprTree(BinaryOperator *I,
SmallVectorImpl<reassociate::ValueEntry> &Ops,
- reassociate::OverflowTracking Flags);
+ OverflowTracking Flags);
Value *OptimizeExpression(BinaryOperator *I,
SmallVectorImpl<reassociate::ValueEntry> &Ops);
Value *OptimizeAdd(Instruction *I,
diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h
index db064e1f41f02..d57e741aba206 100644
--- a/llvm/include/llvm/Transforms/Utils/Local.h
+++ b/llvm/include/llvm/Transforms/Utils/Local.h
@@ -556,6 +556,27 @@ Value *invertCondition(Value *Condition);
/// function, explicitly materialize the maximal set in the IR.
bool inferAttributesFromOthers(Function &F);
+//===----------------------------------------------------------------------===//
+// Helpers to track and update flags on instructions.
+//
+
+struct OverflowTracking {
+ bool HasNUW = true;
+ bool HasNSW = true;
+ bool AllKnownNonNegative = true;
+ bool AllKnownNonZero = true;
+ // Note: AllKnownNonNegative can be true in a case where one of the operands
+ // is negative, but one the operators is not NSW. AllKnownNonNegative should
+ // not be used independently of HasNSW
+ OverflowTracking() = default;
+
+ /// Merge in the no-wrap flags from \p I.
+ void mergeFlags(Instruction &I);
+
+ /// Apply the no-wrap flags to \p I if applicable.
+ void applyFlags(Instruction &I);
+};
+
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_LOCAL_H
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp
index cb7a9ef9b6711..778a6a012556b 100644
--- a/llvm/lib/Transforms/Scalar/Reassociate.cpp
+++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp
@@ -382,7 +382,7 @@ using RepeatedValue = std::pair<Value *, uint64_t>;
static bool LinearizeExprTree(Instruction *I,
SmallVectorImpl<RepeatedValue> &Ops,
ReassociatePass::OrderedSet &ToRedo,
- reassociate::OverflowTracking &Flags) {
+ OverflowTracking &Flags) {
assert((isa<UnaryOperator>(I) || isa<BinaryOperator>(I)) &&
"Expected a UnaryOperator or BinaryOperator!");
LLVM_DEBUG(dbgs() << "LINEARIZE: " << *I << '\n');
@@ -431,10 +431,7 @@ static bool LinearizeExprTree(Instruction *I,
// We examine the operands of this binary operator.
auto [I, Weight] = Worklist.pop_back_val();
- if (isa<OverflowingBinaryOperator>(I)) {
- Flags.HasNUW &= I->hasNoUnsignedWrap();
- Flags.HasNSW &= I->hasNoSignedWrap();
- }
+ Flags.mergeFlags(*I);
for (unsigned OpIdx = 0; OpIdx < I->getNumOperands(); ++OpIdx) { // Visit operands.
Value *Op = I->getOperand(OpIdx);
@@ -734,15 +731,7 @@ void ReassociatePass::RewriteExprTree(BinaryOperator *I,
ExpressionChangedStart->clearSubclassOptionalData();
ExpressionChangedStart->setFastMathFlags(Flags);
} else {
- ExpressionChangedStart->clearSubclassOptionalData();
- if (ExpressionChangedStart->getOpcode() == Instruction::Add ||
- (ExpressionChangedStart->getOpcode() == Instruction::Mul &&
- Flags.AllKnownNonZero)) {
- if (Flags.HasNUW)
- ExpressionChangedStart->setHasNoUnsignedWrap();
- if (Flags.HasNSW && (Flags.AllKnownNonNegative || Flags.HasNUW))
- ExpressionChangedStart->setHasNoSignedWrap();
- }
+ Flags.applyFlags(*ExpressionChangedStart);
}
}
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 3dbd605e19c3a..4d168ce7cf591 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -4362,3 +4362,21 @@ bool llvm::inferAttributesFromOthers(Function &F) {
return Changed;
}
+
+void OverflowTracking::mergeFlags(Instruction &I) {
+ if (isa<OverflowingBinaryOperator>(&I)) {
+ HasNUW &= I.hasNoUnsignedWrap();
+ HasNSW &= I.hasNoSignedWrap();
+ }
+}
+
+void OverflowTracking::applyFlags(Instruction &I) {
+ I.clearSubclassOptionalData();
+ if (I.getOpcode() == Instruction::Add ||
+ (I.getOpcode() == Instruction::Mul && AllKnownNonZero)) {
+ if (HasNUW)
+ I.setHasNoUnsignedWrap();
+ if (HasNSW && (AllKnownNonNegative || HasNUW))
+ I.setHasNoSignedWrap();
+ }
+}
|
This enables preserving NSW when both adds have NSW and NUW. For now, set AllKnownNonNegative/AllKnownNonZero to false when using in LICM. https://alive2.llvm.org/ce/z/uu79Xc Depends on llvm#140403 (included in PR)
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.
LGTM
I'll note that leaving the AllKnownNonZero in Reasociate seems slightly odd, but we can be incremental here.
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.
LG
struct OverflowTracking { | ||
bool HasNUW = true; | ||
bool HasNSW = true; | ||
bool AllKnownNonNegative = true; |
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.
Please add a comment indicating that the user is responsible for updating AllKnownNonNegative
and AllKnownNonZero
.
Move parts of the logic used by Reassociate to OverflowTracking (mergeFlags & applyFlags) and move the definition to Local.h (not sure if there's a better place?).
For now it just moves the NUW/NSW handling, as this matches the uses in LICM. I'll look into the FP math handling separately, as it looks like there's a difference between Reassociate (takes all flags from I, while LICM takes the intersection of the flags on both instructions).