From 1b1172ad905da5cc8d12cebbe0ecb5dbc2f112ba Mon Sep 17 00:00:00 2001 From: Andrew Scheidecker Date: Tue, 19 Feb 2019 21:21:54 +0000 Subject: [PATCH] [ConstantFold] Fix misfolding fcmp of a ConstantExpr NaN with itself. The code incorrectly inferred that the relationship of a constant expression to itself is FCMP_OEQ (ordered and equal), when it's actually FCMP_UEQ (unordered *or* equal). This change corrects that, and adds some more limited folds that can be done in this case. Differential revision: https://reviews.llvm.org/D51216 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354381 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/ConstantFold.cpp | 13 ++++++++++--- test/Transforms/ConstProp/bitcast.ll | 8 ++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 2c958c7dd49..037f120f47d 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -1359,8 +1359,9 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) { assert(V1->getType() == V2->getType() && "Cannot compare values of different types!"); - // Handle degenerate case quickly - if (V1 == V2) return FCmpInst::FCMP_OEQ; + // We do not know if a constant expression will evaluate to a number or NaN. + // Therefore, we can only say that the relation is unordered or equal. + if (V1 == V2) return FCmpInst::FCMP_UEQ; if (!isa(V1)) { if (!isa(V2)) { @@ -1855,7 +1856,6 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, default: llvm_unreachable("Unknown relation!"); case FCmpInst::FCMP_UNO: case FCmpInst::FCMP_ORD: - case FCmpInst::FCMP_UEQ: case FCmpInst::FCMP_UNE: case FCmpInst::FCMP_ULT: case FCmpInst::FCMP_UGT: @@ -1901,6 +1901,13 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, else if (pred == FCmpInst::FCMP_ONE || pred == FCmpInst::FCMP_UNE) Result = 1; break; + case FCmpInst::FCMP_UEQ: // We know that C1 == C2 || isUnordered(C1, C2). + // We can only partially decide this relation. + if (pred == FCmpInst::FCMP_ONE) + Result = 0; + else if (pred == FCmpInst::FCMP_UEQ) + Result = 1; + break; } // If we evaluated the result, return it now. diff --git a/test/Transforms/ConstProp/bitcast.ll b/test/Transforms/ConstProp/bitcast.ll index bf21fdd852f..7b1908bd7ac 100644 --- a/test/Transforms/ConstProp/bitcast.ll +++ b/test/Transforms/ConstProp/bitcast.ll @@ -36,21 +36,21 @@ define i1 @bad_fcmp_constexpr_bitcast() { ret i1 %cmp } -; FIXME: If the bitcasts result in a NaN FP value, then "ordered and equal" would be false. +; Ensure that an "ordered and equal" fcmp of a ConstantExpr to itself is not folded, since the ConstantExpr may be a NaN. define i1 @fcmp_constexpr_oeq(float %conv) { ; CHECK-LABEL: @fcmp_constexpr_oeq( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 fcmp oeq (float bitcast (i32 ptrtoint (i16* @a to i32) to float), float bitcast (i32 ptrtoint (i16* @a to i32) to float)) ; %cmp = fcmp oeq float bitcast (i32 ptrtoint (i16* @a to i32) to float), bitcast (i32 ptrtoint (i16* @a to i32) to float) ret i1 %cmp } -; FIXME: If the bitcasts result in a NaN FP value, then "unordered or not equal" would be true. +; Ensure that an "unordered or not equal" fcmp of a ConstantExpr to itself is not folded, since the ConstantExpr may be a NaN. define i1 @fcmp_constexpr_une(float %conv) { ; CHECK-LABEL: @fcmp_constexpr_une( -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: ret i1 fcmp une (float bitcast (i32 ptrtoint (i16* @a to i32) to float), float bitcast (i32 ptrtoint (i16* @a to i32) to float)) ; %cmp = fcmp une float bitcast (i32 ptrtoint (i16* @a to i32) to float), bitcast (i32 ptrtoint (i16* @a to i32) to float) ret i1 %cmp -- 2.50.1