Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -694,6 +694,13 @@ if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT, TLI)) return true; + // isSafeToSpeculativelyExecute() is not enough, because its result is + // taken into account only when it's positive and we need to forbid the case + // where its result is negative. + if (const FPMathOperator *MathOp = dyn_cast(&Inst)) + if (!MathOp->hasNoExceptions() || !MathOp->hasNoRounding()) + return false; + return isGuaranteedToExecute(Inst, DT, CurLoop, SafetyInfo); } Index: test/Transforms/LICM/fpenv.ll =================================================================== --- /dev/null +++ test/Transforms/LICM/fpenv.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -O3 -S | FileCheck %s + +define void @fdiv-is-not-hoisted-out-of-loop(i32 %n) { +; CHECK-LABEL: @fdiv-is-not-hoisted-out-of-loop( +; CHECK: for.body: +; CHECK: fdiv +entry: + %cmp2 = icmp sgt i32 %n, 0 + br i1 %cmp2, label %for.body.lr.ph, label %for.end + +for.body.lr.ph: + %0 = add i32 %n, -1 + br label %for.body + +for.body: + %i.03 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] + %div = fdiv double 0.000000e+00, 0.000000e+00 + tail call void @process(double %div) + %inc = add nuw nsw i32 %i.03, 1 + %exitcond = icmp eq i32 %i.03, %0 + br i1 %exitcond, label %for.end.loopexit, label %for.body + +for.end.loopexit: + br label %for.end + +for.end: + ret void +} + +declare void @process(double) nounwind