Index: include/llvm/IR/Constants.h =================================================================== --- include/llvm/IR/Constants.h +++ include/llvm/IR/Constants.h @@ -1076,7 +1076,8 @@ /// \param OnlyIfReducedTy see \a getWithOperands() docs. static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr, - FastMathFlags FMF = FastMathFlags()); + FastMathFlags FMF = FastMathFlags(), + bool Strict = false); /// \brief Return an ICmp or FCmp comparison operator constant expression. /// Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -1028,7 +1028,8 @@ return C; } - return ConstantExpr::get(Opcode, Ops[0], Ops[1], 0, nullptr, FMF); + return ConstantExpr::get(Opcode, Ops[0], Ops[1], 0, nullptr, + FMF, /* Strict = */ true); } switch (Opcode) { Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -1871,7 +1871,8 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags, Type *OnlyIfReducedTy, - FastMathFlags FMF) { + FastMathFlags FMF, + bool Strict) { // Check the operands for consistency first. assert(Opcode >= Instruction::BinaryOpsBegin && Opcode < Instruction::BinaryOpsEnd && @@ -1944,6 +1945,11 @@ if (OnlyIfReducedTy == C1->getType()) return nullptr; + // ConstantExpression can't store these flags, which can lead to going against + // them. + if (Strict && (FMF.keepExceptions() || FMF.keepRounding())) + return nullptr; + Constant *ArgVec[] = { C1, C2 }; ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags); Index: test/Transforms/EarlyCSE/fpenv.ll =================================================================== --- /dev/null +++ test/Transforms/EarlyCSE/fpenv.ll @@ -0,0 +1,24 @@ +; %val.true and %val.false should not be moved inside phi-node as constant +; expressions as such transformation looses fast-math flags. +; RUN: opt < %s -S -early-cse | FileCheck %s + +define double @do-not-turn-into-constexpr(double %x) { +; CHECK-LABEL: @do-not-turn-into-constexpr( +; CHECK: %val.true = fmul +; CHECK: %val.false = fmul +entry: + %cmp = fcmp oeq double %x, 0.000000e+00 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + %val.true = fmul kexc double 1.000000e+300, 1.000000e+300 + br label %cond.end + +cond.false: ; preds = %entry + %val.false = fmul kexc double 1.000000e-300, 1.000000e-300 + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi double [ %val.true, %cond.true ], [ %val.false, %cond.false ] + ret double %cond +}