aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Scalar/Float2Int.cpp
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2022-04-01 12:28:21 +0200
committerNikita Popov <npopov@redhat.com>2022-04-04 10:18:39 +0200
commitc0cc98251a453e2850c25adb10a3fd6b3e86a2e8 (patch)
treea571b9cb644cc160a08d51f6920825d4bbd29559 /llvm/lib/Transforms/Scalar/Float2Int.cpp
parentb8e8f62d5e72c7f4fc61985406fb27714e2c2f7c (diff)
downloadllvm-c0cc98251a453e2850c25adb10a3fd6b3e86a2e8.zip
llvm-c0cc98251a453e2850c25adb10a3fd6b3e86a2e8.tar.gz
llvm-c0cc98251a453e2850c25adb10a3fd6b3e86a2e8.tar.bz2
[Float2Int] Make sure dependent ranges are calculated first (PR54669)
The range calculation in walkForwards() assumes that the ranges of the operands have already been calculated. With the used visit order, this is not necessarily the case when there are multiple roots. (There is nothing guaranteeing that instructions are visited in topological order.) Fix this by queuing instructions for reprocessing if the operand ranges haven't been calculated yet. Fixes https://github.com/llvm/llvm-project/issues/54669. Differential Revision: https://reviews.llvm.org/D122817
Diffstat (limited to 'llvm/lib/Transforms/Scalar/Float2Int.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/Float2Int.cpp30
1 files changed, 20 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/Scalar/Float2Int.cpp b/llvm/lib/Transforms/Scalar/Float2Int.cpp
index 6b04d2c..d781cc0 100644
--- a/llvm/lib/Transforms/Scalar/Float2Int.cpp
+++ b/llvm/lib/Transforms/Scalar/Float2Int.cpp
@@ -235,14 +235,17 @@ void Float2IntPass::walkBackwards() {
}
}
-// Calculate result range from operand ranges
-ConstantRange Float2IntPass::calcRange(Instruction *I) {
+// Calculate result range from operand ranges.
+// Return None if the range cannot be calculated yet.
+Optional<ConstantRange> Float2IntPass::calcRange(Instruction *I) {
SmallVector<ConstantRange, 4> OpRanges;
for (Value *O : I->operands()) {
if (Instruction *OI = dyn_cast<Instruction>(O)) {
- assert(SeenInsts.find(OI) != SeenInsts.end() &&
- "def not seen before use!");
- OpRanges.push_back(SeenInsts.find(OI)->second);
+ auto OpIt = SeenInsts.find(OI);
+ assert(OpIt != SeenInsts.end() && "def not seen before use!");
+ if (OpIt->second == unknownRange())
+ return None; // Wait until operand range has been calculated.
+ OpRanges.push_back(OpIt->second);
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
// Work out if the floating point number can be losslessly represented
// as an integer.
@@ -324,12 +327,19 @@ ConstantRange Float2IntPass::calcRange(Instruction *I) {
// Walk forwards down the list of seen instructions, so we visit defs before
// uses.
void Float2IntPass::walkForwards() {
- for (auto &It : reverse(SeenInsts)) {
- if (It.second != unknownRange())
- continue;
+ std::deque<Instruction *> Worklist;
+ for (const auto &Pair : SeenInsts)
+ if (Pair.second == unknownRange())
+ Worklist.push_back(Pair.first);
+
+ while (!Worklist.empty()) {
+ Instruction *I = Worklist.back();
+ Worklist.pop_back();
- Instruction *I = It.first;
- seen(I, calcRange(I));
+ if (Optional<ConstantRange> Range = calcRange(I))
+ seen(I, *Range);
+ else
+ Worklist.push_front(I); // Reprocess later.
}
}