Index: llvm/include/llvm/Transforms/Scalar/Float2Int.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/Float2Int.h +++ llvm/include/llvm/Transforms/Scalar/Float2Int.h @@ -25,6 +25,7 @@ class Function; class Instruction; class LLVMContext; +template class Optional; class Type; class Value; @@ -41,7 +42,7 @@ ConstantRange badRange(); ConstantRange unknownRange(); ConstantRange validateRange(ConstantRange R); - ConstantRange calcRange(Instruction *I); + Optional calcRange(Instruction *I); void walkBackwards(); void walkForwards(); bool validateAndTransform(); Index: llvm/lib/Transforms/Scalar/Float2Int.cpp =================================================================== --- llvm/lib/Transforms/Scalar/Float2Int.cpp +++ llvm/lib/Transforms/Scalar/Float2Int.cpp @@ -235,14 +235,17 @@ } } -// 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 Float2IntPass::calcRange(Instruction *I) { SmallVector OpRanges; for (Value *O : I->operands()) { if (Instruction *OI = dyn_cast(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(O)) { // Work out if the floating point number can be losslessly represented // as an integer. @@ -324,12 +327,19 @@ // 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 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 Range = calcRange(I)) + seen(I, *Range); + else + Worklist.push_front(I); // Reprocess later. } }