Index: include/llvm/IR/Constants.h =================================================================== --- include/llvm/IR/Constants.h +++ include/llvm/IR/Constants.h @@ -1103,7 +1103,8 @@ /// \param FMF common fast-math flags that can affect folding. static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr, - FastMathFlags FMF = FastMathFlags()); + FastMathFlags FMF = FastMathFlags(), + bool Strict = false); /// Return a binary or shift operator constant expression, folding if /// possible. Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -1030,7 +1030,7 @@ return C; } - return ConstantExpr::get(Opcode, Ops[0], Ops[1], FMF); + return ConstantExpr::get(Opcode, Ops[0], Ops[1], FMF, /* Strict = */ true); } switch (Opcode) { Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -1801,7 +1801,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 && @@ -1886,6 +1887,13 @@ if (OnlyIfReducedTy == C1->getType()) return nullptr; + if (C1->getType()->isFPOrFPVectorTy()) { + // ConstantExpression can't store these flags, which can lead to going + // against them. + if (Strict && (!FMF.noExceptions() || !FMF.noRounding())) + 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 nrnd double 1.000000e+300, 1.000000e+300 + br label %cond.end + +cond.false: ; preds = %entry + %val.false = fmul nrnd 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 +}