diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1351,6 +1351,14 @@ unsigned FCmpCodeL = getFCmpCode(PredL); unsigned FCmpCodeR = getFCmpCode(PredR); unsigned NewPred = IsAnd ? FCmpCodeL & FCmpCodeR : FCmpCodeL | FCmpCodeR; + + // Intersect the fast math flags. + // TODO: We can union the fast math flags. + IRBuilder<>::FastMathFlagGuard FMFG(Builder); + FastMathFlags FMF = LHS->getFastMathFlags(); + FMF &= RHS->getFastMathFlags(); + Builder.setFastMathFlags(FMF); + return getFCmpValue(NewPred, LHS0, LHS1, Builder); } diff --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll --- a/llvm/test/Transforms/InstCombine/and-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/and-fcmp.ll @@ -3120,3 +3120,47 @@ %retval = select i1 %cmp, i1 %cmp1, i1 false ret i1 %retval } + +define i1 @intersect_fmf_1(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_1( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast oeq double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp fast ole double %a, %b + %cmp1 = fcmp fast oge double %a, %b + %retval = and i1 %cmp, %cmp1 + ret i1 %retval +} + +define i1 @intersect_fmf_2(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_2( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp fast ole double %a, %b + %cmp1 = fcmp oge double %a, %b + %retval = and i1 %cmp, %cmp1 + ret i1 %retval +} + +define i1 @intersect_fmf_3(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_3( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp ole double %a, %b + %cmp1 = fcmp fast oge double %a, %b + %retval = and i1 %cmp, %cmp1 + ret i1 %retval +} + +define i1 @intersect_fmf_4(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_4( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp ninf ole double %a, %b + %cmp1 = fcmp nnan oge double %a, %b + %retval = and i1 %cmp, %cmp1 + ret i1 %retval +} diff --git a/llvm/test/Transforms/InstCombine/or-fcmp.ll b/llvm/test/Transforms/InstCombine/or-fcmp.ll --- a/llvm/test/Transforms/InstCombine/or-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/or-fcmp.ll @@ -3072,3 +3072,47 @@ %retval = select i1 %cmp, i1 true, i1 %cmp1 ret i1 %retval } + +define i1 @intersect_fmf_1(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_1( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast one double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp fast olt double %a, %b + %cmp1 = fcmp fast ogt double %a, %b + %retval = or i1 %cmp, %cmp1 + ret i1 %retval +} + +define i1 @intersect_fmf_2(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_2( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp one double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp fast olt double %a, %b + %cmp1 = fcmp ogt double %a, %b + %retval = or i1 %cmp, %cmp1 + ret i1 %retval +} + +define i1 @intersect_fmf_3(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_3( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp one double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp olt double %a, %b + %cmp1 = fcmp fast ogt double %a, %b + %retval = or i1 %cmp, %cmp1 + ret i1 %retval +} + +define i1 @intersect_fmf_4(double %a, double %b) { +; CHECK-LABEL: @intersect_fmf_4( +; CHECK-NEXT: [[TMP1:%.*]] = fcmp one double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = fcmp ninf olt double %a, %b + %cmp1 = fcmp nnan ogt double %a, %b + %retval = or i1 %cmp, %cmp1 + ret i1 %retval +}