Index: llvm/lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenPrepare.cpp +++ llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -944,8 +944,10 @@ InsertedCmp = CmpInst::Create(CI->getOpcode(), CI->getPredicate(), CI->getOperand(0), CI->getOperand(1), "", &*InsertPt); - // Propagate the debug info. + // Propagate the debug info and FastMath flags. InsertedCmp->setDebugLoc(CI->getDebugLoc()); + if (isa(CI)) + InsertedCmp->copyFastMathFlags(CI->getFastMathFlags()); } // Replace a use of the cmp with a use of the new cmp. Index: llvm/lib/Transforms/Scalar/GVN.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GVN.cpp +++ llvm/lib/Transforms/Scalar/GVN.cpp @@ -1724,14 +1724,20 @@ return Changed; } -static void patchReplacementInstruction(Instruction *I, Value *Repl) { +static void patchReplacementInstruction(Instruction *I, Value *Repl, + bool IsLoad) { auto *ReplInst = dyn_cast(Repl); if (!ReplInst) return; // Patch the replacement so that it is not more restrictive than the value // being replaced. - ReplInst->andIRFlags(I); + // Note that if 'I' is a load being replaced by some operation, + // for example, by an arithmetic operation, then andIRFlags() + // would just erase all math flags from the original arithmetic + // operation, which is clearly not wanted and not needed. + if (!IsLoad) + ReplInst->andIRFlags(I); // FIXME: If both the original and replacement value are part of the // same control-flow region (meaning that the execution of one @@ -1750,8 +1756,9 @@ combineMetadata(ReplInst, I, KnownIDs); } -static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) { - patchReplacementInstruction(I, Repl); +static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl, + bool IsLoad = false) { + patchReplacementInstruction(I, Repl, IsLoad); I->replaceAllUsesWith(Repl); } @@ -1794,7 +1801,7 @@ Value *AvailableValue = AV.MaterializeAdjustedValue(L, L, *this); // Replace the load! - patchAndReplaceAllUsesWith(L, AvailableValue); + patchAndReplaceAllUsesWith(L, AvailableValue, true /* IsLoad */); markInstructionForDeletion(L); ++NumGVNLoad; // Tell MDA to rexamine the reused pointer since we might have more Index: llvm/lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- llvm/lib/Transforms/Scalar/Reassociate.cpp +++ llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -1777,6 +1777,13 @@ return nullptr; // All distinct factors, so nothing left for us to do. IRBuilder<> Builder(I); + if (isa(I)) { + // This place can be reached only if unsafe algebra is permitted. + // The newly generated operations must also have the proper MathFlags. + FastMathFlags FMF; + FMF.setUnsafeAlgebra(); + Builder.setFastMathFlags(FMF); + } Value *V = buildMinimalMultiplyDAG(Builder, Factors); if (Ops.empty()) return V; Index: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -2422,11 +2422,13 @@ if (Value *V = alreadyVectorized(E->Scalars)) return V; - CmpInst::Predicate P0 = cast(VL0)->getPredicate(); + CmpInst *CI = cast(VL0); + CmpInst::Predicate P0 = CI->getPredicate(); Value *V; - if (Opcode == Instruction::FCmp) + if (Opcode == Instruction::FCmp) { V = Builder.CreateFCmp(P0, L, R); - else + cast(V)->copyFastMathFlags(CI); + } else V = Builder.CreateICmp(P0, L, R); E->VectorizedValue = V;