diff --git a/llvm/include/llvm/Transforms/Scalar/Float2Int.h b/llvm/include/llvm/Transforms/Scalar/Float2Int.h index 9def40ed880d47..f4bec228ea9633 100644 --- a/llvm/include/llvm/Transforms/Scalar/Float2Int.h +++ b/llvm/include/llvm/Transforms/Scalar/Float2Int.h @@ -25,6 +25,7 @@ class DominatorTree; class Function; class Instruction; class LLVMContext; +template class Optional; class Type; class Value; @@ -41,7 +42,7 @@ class Float2IntPass : public PassInfoMixin { ConstantRange badRange(); ConstantRange unknownRange(); ConstantRange validateRange(ConstantRange R); - ConstantRange calcRange(Instruction *I); + Optional calcRange(Instruction *I); void walkBackwards(); void walkForwards(); bool validateAndTransform(); diff --git a/llvm/lib/Transforms/Scalar/Float2Int.cpp b/llvm/lib/Transforms/Scalar/Float2Int.cpp index 6b04d2ce073240..d781cc0ab19df8 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 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 @@ 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 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. } } diff --git a/llvm/test/Transforms/Float2Int/pr54669.ll b/llvm/test/Transforms/Float2Int/pr54669.ll index 135bee55fe260b..f56040c14d577c 100644 --- a/llvm/test/Transforms/Float2Int/pr54669.ll +++ b/llvm/test/Transforms/Float2Int/pr54669.ll @@ -3,11 +3,9 @@ declare void @use(i32) -; FIXME: Currently being miscompiled. - define i1 @src() { ; CHECK-LABEL: @src( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 2147483647, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 -1, -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %add = fadd double 2.000000e+00, -1.000000e+00