diff options
author | Nikita Popov <npopov@redhat.com> | 2022-04-01 12:28:21 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2022-04-04 10:18:39 +0200 |
commit | c0cc98251a453e2850c25adb10a3fd6b3e86a2e8 (patch) | |
tree | a571b9cb644cc160a08d51f6920825d4bbd29559 /llvm/lib/Transforms/Scalar/Float2Int.cpp | |
parent | b8e8f62d5e72c7f4fc61985406fb27714e2c2f7c (diff) | |
download | llvm-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.cpp | 30 |
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. } } |