Index: include/llvm/Analysis/ConstantFolding.h =================================================================== --- include/llvm/Analysis/ConstantFolding.h +++ include/llvm/Analysis/ConstantFolding.h @@ -20,6 +20,8 @@ #ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H #define LLVM_ANALYSIS_CONSTANTFOLDING_H +#include "llvm/IR/FastMathFlags.h" + namespace llvm { class Constant; class ConstantExpr; @@ -44,7 +46,8 @@ /// result is returned, if not, null is returned. Constant * ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, - const TargetLibraryInfo *TLI = nullptr); + const TargetLibraryInfo *TLI = nullptr, + FastMathFlags FMF = FastMathFlags()); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, @@ -55,7 +58,8 @@ Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, ArrayRef Ops, const DataLayout &DL, - const TargetLibraryInfo *TLI = nullptr); + const TargetLibraryInfo *TLI = nullptr, + FastMathFlags FMF = FastMathFlags()); /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare /// instruction (icmp/fcmp) with the specified operands. If it fails, it Index: include/llvm/Analysis/TargetFolder.h =================================================================== --- include/llvm/Analysis/TargetFolder.h +++ include/llvm/Analysis/TargetFolder.h @@ -22,6 +22,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/FastMathFlags.h" #include "llvm/IR/InstrTypes.h" namespace llvm { @@ -51,22 +52,25 @@ bool HasNUW = false, bool HasNSW = false) const { return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); } - Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFAdd(LHS, RHS)); + Constant *CreateFAdd(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return Fold(ConstantExpr::getFAdd(LHS, RHS, FMF)); } Constant *CreateSub(Constant *LHS, Constant *RHS, bool HasNUW = false, bool HasNSW = false) const { return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); } - Constant *CreateFSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFSub(LHS, RHS)); + Constant *CreateFSub(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return Fold(ConstantExpr::getFSub(LHS, RHS, FMF)); } Constant *CreateMul(Constant *LHS, Constant *RHS, bool HasNUW = false, bool HasNSW = false) const { return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); } - Constant *CreateFMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFMul(LHS, RHS)); + Constant *CreateFMul(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return Fold(ConstantExpr::getFMul(LHS, RHS, FMF)); } Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); @@ -74,8 +78,9 @@ Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); } - Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFDiv(LHS, RHS)); + Constant *CreateFDiv(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return Fold(ConstantExpr::getFDiv(LHS, RHS, FMF)); } Constant *CreateURem(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getURem(LHS, RHS)); @@ -83,8 +88,9 @@ Constant *CreateSRem(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getSRem(LHS, RHS)); } - Constant *CreateFRem(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFRem(LHS, RHS)); + Constant *CreateFRem(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return Fold(ConstantExpr::getFRem(LHS, RHS, FMF)); } Constant *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, bool HasNSW = false) const { Index: include/llvm/IR/ConstantFolder.h =================================================================== --- include/llvm/IR/ConstantFolder.h +++ include/llvm/IR/ConstantFolder.h @@ -18,6 +18,7 @@ #define LLVM_IR_CONSTANTFOLDER_H #include "llvm/IR/Constants.h" +#include "llvm/IR/FastMathFlags.h" #include "llvm/IR/InstrTypes.h" namespace llvm { @@ -35,22 +36,25 @@ bool HasNUW = false, bool HasNSW = false) const { return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW); } - Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFAdd(LHS, RHS); + Constant *CreateFAdd(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return ConstantExpr::getFAdd(LHS, RHS, FMF); } Constant *CreateSub(Constant *LHS, Constant *RHS, bool HasNUW = false, bool HasNSW = false) const { return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); } - Constant *CreateFSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFSub(LHS, RHS); + Constant *CreateFSub(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return ConstantExpr::getFSub(LHS, RHS, FMF); } Constant *CreateMul(Constant *LHS, Constant *RHS, bool HasNUW = false, bool HasNSW = false) const { return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); } - Constant *CreateFMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFMul(LHS, RHS); + Constant *CreateFMul(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return ConstantExpr::getFMul(LHS, RHS, FMF); } Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false) const { @@ -60,8 +64,9 @@ bool isExact = false) const { return ConstantExpr::getSDiv(LHS, RHS, isExact); } - Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFDiv(LHS, RHS); + Constant *CreateFDiv(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return ConstantExpr::getFDiv(LHS, RHS, FMF); } Constant *CreateURem(Constant *LHS, Constant *RHS) const { return ConstantExpr::getURem(LHS, RHS); @@ -69,8 +74,9 @@ Constant *CreateSRem(Constant *LHS, Constant *RHS) const { return ConstantExpr::getSRem(LHS, RHS); } - Constant *CreateFRem(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFRem(LHS, RHS); + Constant *CreateFRem(Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return ConstantExpr::getFRem(LHS, RHS, FMF); } Constant *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, bool HasNSW = false) const { @@ -95,8 +101,9 @@ } Constant *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { - return ConstantExpr::get(Opc, LHS, RHS); + Constant *LHS, Constant *RHS, + FastMathFlags FMF = FastMathFlags()) const { + return ConstantExpr::get(Opc, LHS, RHS, 0, nullptr, FMF); } //===--------------------------------------------------------------------===// Index: include/llvm/IR/Constants.h =================================================================== --- include/llvm/IR/Constants.h +++ include/llvm/IR/Constants.h @@ -920,19 +920,24 @@ static Constant *getNot(Constant *C); static Constant *getAdd(Constant *C1, Constant *C2, bool HasNUW = false, bool HasNSW = false); - static Constant *getFAdd(Constant *C1, Constant *C2); + static Constant *getFAdd(Constant *C1, Constant *C2, + FastMathFlags FMF = FastMathFlags()); static Constant *getSub(Constant *C1, Constant *C2, bool HasNUW = false, bool HasNSW = false); - static Constant *getFSub(Constant *C1, Constant *C2); + static Constant *getFSub(Constant *C1, Constant *C2, + FastMathFlags FMF = FastMathFlags()); static Constant *getMul(Constant *C1, Constant *C2, bool HasNUW = false, bool HasNSW = false); - static Constant *getFMul(Constant *C1, Constant *C2); + static Constant *getFMul(Constant *C1, Constant *C2, + FastMathFlags FMF = FastMathFlags()); static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false); static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getFDiv(Constant *C1, Constant *C2); + static Constant *getFDiv(Constant *C1, Constant *C2, + FastMathFlags FMF = FastMathFlags()); static Constant *getURem(Constant *C1, Constant *C2); static Constant *getSRem(Constant *C1, Constant *C2); - static Constant *getFRem(Constant *C1, Constant *C2); + static Constant *getFRem(Constant *C1, Constant *C2, + FastMathFlags FMF = FastMathFlags()); static Constant *getAnd(Constant *C1, Constant *C2); static Constant *getOr(Constant *C1, Constant *C2); static Constant *getXor(Constant *C1, Constant *C2); Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -785,7 +785,7 @@ MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateFAdd(LC, RC), Name); + return Insert(Folder.CreateFAdd(LC, RC, FMF), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFAdd(LHS, RHS), FPMathTag, FMF), Name); } @@ -807,7 +807,7 @@ MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateFSub(LC, RC), Name); + return Insert(Folder.CreateFSub(LC, RC, FMF), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFSub(LHS, RHS), FPMathTag, FMF), Name); } @@ -829,7 +829,7 @@ MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateFMul(LC, RC), Name); + return Insert(Folder.CreateFMul(LC, RC, FMF), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFMul(LHS, RHS), FPMathTag, FMF), Name); } @@ -861,7 +861,7 @@ MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateFDiv(LC, RC), Name); + return Insert(Folder.CreateFDiv(LC, RC, FMF), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFDiv(LHS, RHS), FPMathTag, FMF), Name); } @@ -881,7 +881,7 @@ MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateFRem(LC, RC), Name); + return Insert(Folder.CreateFRem(LC, RC, FMF), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFRem(LHS, RHS), FPMathTag, FMF), Name); } Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -894,6 +894,12 @@ /// and stores, which have no constant expression form. Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI) { + FastMathFlags FMF; + + if (isa(I)) { + FMF = I->getFastMathFlags(); + } + // Handle PHI nodes quickly here... if (PHINode *PN = dyn_cast(I)) { Constant *CommonValue = nullptr; @@ -911,7 +917,7 @@ return nullptr; // Fold the PHI's operands. if (ConstantExpr *NewC = dyn_cast(C)) - C = ConstantFoldConstantExpression(NewC, DL, TLI); + C = ConstantFoldConstantExpression(NewC, DL, TLI, FMF); // If the incoming value is a different constant to // the one we saw previously, then give up. if (CommonValue && C != CommonValue) @@ -934,7 +940,8 @@ // Fold the Instruction's operands. if (ConstantExpr *NewCE = dyn_cast(Op)) - Op = ConstantFoldConstantExpression(NewCE, DL, TLI); + if (Constant *C = ConstantFoldConstantExpression(NewCE, DL, TLI, FMF)) + Op = C; Ops.push_back(Op); } @@ -959,13 +966,15 @@ EVI->getIndices()); } - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, DL, TLI); + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, DL, TLI, + FMF); } static Constant * ConstantFoldConstantExpressionImpl(const ConstantExpr *CE, const DataLayout &DL, const TargetLibraryInfo *TLI, - SmallPtrSetImpl &FoldedOps) { + SmallPtrSetImpl &FoldedOps, + FastMathFlags FMF) { SmallVector Ops; for (User::const_op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) { @@ -974,7 +983,9 @@ // a ConstantExpr, we don't have to process it again. if (ConstantExpr *NewCE = dyn_cast(NewC)) { if (FoldedOps.insert(NewCE).second) - NewC = ConstantFoldConstantExpressionImpl(NewCE, DL, TLI, FoldedOps); + if (Constant *C = ConstantFoldConstantExpressionImpl(NewCE, DL, TLI, + FoldedOps, FMF)) + NewC = C; } Ops.push_back(NewC); } @@ -982,7 +993,8 @@ if (CE->isCompare()) return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], DL, TLI); - return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, DL, TLI); + return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, DL, TLI, + FMF); } /// Attempt to fold the constant expression @@ -990,9 +1002,10 @@ /// result is returned, if not, null is returned. Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, - const TargetLibraryInfo *TLI) { + const TargetLibraryInfo *TLI, + FastMathFlags FMF) { SmallPtrSet FoldedOps; - return ConstantFoldConstantExpressionImpl(CE, DL, TLI, FoldedOps); + return ConstantFoldConstantExpressionImpl(CE, DL, TLI, FoldedOps, FMF); } /// Attempt to constant fold an instruction with the @@ -1008,7 +1021,8 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, ArrayRef Ops, const DataLayout &DL, - const TargetLibraryInfo *TLI) { + const TargetLibraryInfo *TLI, + FastMathFlags FMF) { // Handle easy binops first. if (Instruction::isBinaryOp(Opcode)) { if (isa(Ops[0]) || isa(Ops[1])) { @@ -1016,7 +1030,7 @@ return C; } - return ConstantExpr::get(Opcode, Ops[0], Ops[1]); + return ConstantExpr::get(Opcode, Ops[0], Ops[1], 0, nullptr, FMF); } switch (Opcode) { Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -3350,7 +3350,7 @@ if (!ConstantExpr::getFPOpExceptions(Inst, S)) return false; - if (KeepExceptions && (S != APFloat::opOK || (S & APFloat::opInexact))) + if (S != APFloat::opOK || (S & APFloat::opInexact)) return false; } return true; Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -2276,8 +2276,8 @@ return get(Instruction::Add, C1, C2, Flags); } -Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2) { - return get(Instruction::FAdd, C1, C2); +Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2, FastMathFlags FMF) { + return get(Instruction::FAdd, C1, C2, 0, nullptr, FMF); } Constant *ConstantExpr::getSub(Constant *C1, Constant *C2, @@ -2287,19 +2287,19 @@ return get(Instruction::Sub, C1, C2, Flags); } -Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2) { - return get(Instruction::FSub, C1, C2); +Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2, FastMathFlags FMF) { + return get(Instruction::FSub, C1, C2, 0, nullptr, FMF); } Constant *ConstantExpr::getMul(Constant *C1, Constant *C2, bool HasNUW, bool HasNSW) { unsigned Flags = (HasNUW ? OverflowingBinaryOperator::NoUnsignedWrap : 0) | (HasNSW ? OverflowingBinaryOperator::NoSignedWrap : 0); - return get(Instruction::Mul, C1, C2, Flags); + return get(Instruction::Mul, C1, C2, Flags, nullptr); } -Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2) { - return get(Instruction::FMul, C1, C2); +Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2, FastMathFlags FMF) { + return get(Instruction::FMul, C1, C2, 0, nullptr, FMF); } Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2, bool isExact) { @@ -2312,8 +2312,8 @@ isExact ? PossiblyExactOperator::IsExact : 0); } -Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) { - return get(Instruction::FDiv, C1, C2); +Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2, FastMathFlags FMF) { + return get(Instruction::FDiv, C1, C2, 0, nullptr, FMF); } Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) { @@ -2324,8 +2324,8 @@ return get(Instruction::SRem, C1, C2); } -Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2) { - return get(Instruction::FRem, C1, C2); +Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2, FastMathFlags FMF) { + return get(Instruction::FRem, C1, C2, 0, nullptr, FMF); } Constant *ConstantExpr::getAnd(Constant *C1, Constant *C2) { Index: test/Other/fpenv-constant-fold.ll =================================================================== --- /dev/null +++ test/Other/fpenv-constant-fold.ll @@ -0,0 +1,130 @@ +; InstCombine is used just for its calls to constant folder. +; RUN: opt -S -instcombine -o - < %s | FileCheck %s + +; Target independent constant folder should not fold floating-point operations +; that have constant expression as their operands when FEnv access is requested +; and such folding leads to differences in observable effects at runtime. + +define double @do-not-fold-fadd-that-can-trap() { +; CHECK-LABEL: @do-not-fold-fadd-that-can-trap +; CHECK: fadd {{.*}} 1.000000e+308, {{.*}} 1.000000e+308 +entry: + %val = fadd nrnd double 1.000000e+308, 1.000000e+308 + ret double %val +} + +define double @do-not-fold-fsub-that-can-trap() { +; CHECK-LABEL: @do-not-fold-fsub-that-can-trap +; CHECK: fsub {{.*}} 1.000000e-308, {{.*}} 1.000000e+308 +entry: + %val = fsub nrnd double 1.000000e-308, 1.000000e+308 + ret double %val +} + +define double @do-not-fold-fmul-that-can-trap() { +; CHECK-LABEL: @do-not-fold-fmul-that-can-trap +; CHECK: fmul {{.*}} 1.000000e+300, {{.*}} 1.000000e+300 +entry: + %val = fmul nrnd double 1.000000e+300, 1.000000e+300 + ret double %val +} + +define double @do-not-fold-fdiv-that-can-trap() { +; CHECK-LABEL: @do-not-fold-fdiv-that-can-trap +; CHECK: fdiv {{.*}} 1.000000e+300, {{.*}} 1.000000e-300 +entry: + %val = fdiv nrnd double 1.000000e+300, 1.000000e-300 + ret double %val +} + +define double @do-not-fold-frem-that-can-trap() { +; CHECK-LABEL: @do-not-fold-frem-that-can-trap +; CHECK: frem {{.*}} 1.000000e+300, {{.*}} 1.000000e-300 +entry: + %val = frem nrnd double 1.000000e+300, 1.000000e-300 + ret double %val +} + +define double @do-not-fold-fadd-because-of-rounding() { +; CHECK-LABEL: @do-not-fold-fadd-because-of-rounding +; CHECK: fadd {{.*}} 1.010000e-01, {{.*}} 9.300000e-01 +entry: + %val = fadd nexc double 0.101, 0.93 + ret double %val +} + +define double @do-not-fold-fsub-because-of-rounding() { +; CHECK-LABEL: @do-not-fold-fsub-because-of-rounding +; CHECK: fsub {{.*}} 1.010000e-01, {{.*}} 9.300000e-01 +entry: + %val = fsub nexc double 0.101, 0.93 + ret double %val +} + +define double @do-not-fold-fmul-because-of-rounding() { +; CHECK-LABEL: @do-not-fold-fmul-because-of-rounding +; CHECK: fmul {{.*}} 1.010000e-01, {{.*}} 9.300000e-01 +entry: + %val = fmul nexc double 0.101, 0.93 + ret double %val +} + +define double @do-not-fold-fdiv-because-of-rounding() { +; CHECK-LABEL: @do-not-fold-fdiv-because-of-rounding +; CHECK: fdiv {{.*}} 1.010000e-01, {{.*}} 9.300000e-01 +entry: + %val = fdiv nexc double 0.101, 0.93 + ret double %val +} + +; "frem" instruction falls into the same category, but none of tried test-cases +; could raised inexact exception. + +define double @fold-fadd-that-cant-trap() { +; CHECK-LABEL: @fold-fadd-that-cant-trap +; CHECK-NOT: fadd +entry: + %val = fadd double 1.0, 1.0 + ret double %val +} + +define double @fold-fsub-that-cant-trap() { +; CHECK-LABEL: @fold-fsub-that-cant-trap +; CHECK-NOT: fsub +entry: + %val = fsub double 1.0, 1.0 + ret double %val +} + +define double @fold-fmul-that-cant-trap() { +; CHECK-LABEL: @fold-fmul-that-cant-trap +; CHECK-NOT: fmul +entry: + %val = fmul double 1.0, 1.0 + ret double %val +} + +define double @fold-fdiv-that-cant-trap() { +; CHECK-LABEL: @fold-fdiv-that-cant-trap +; CHECK-NOT: fdiv +entry: + %val = fdiv double 1.0, 1.0 + ret double %val +} + +define double @fold-frem-that-cant-trap() { +; CHECK-LABEL: @fold-frem-that-cant-trap +; CHECK-NOT: frem +entry: + %val = frem double 1.0, 1.0 + ret double %val +} + +define double @correcly-handle-nested-expressions() { +; CHECK-LABEL: @correcly-handle-nested-expressions +; CHECK: fmul {{.*}} 1.000000e+300, {{.*}} 1.000000e+300 +entry: + %val1 = fmul nrnd double 1.000000e+300, 1.000000e+300 + %val2 = fdiv nrnd double %val1, 1.000000e+300 + ret double %val2 +}