diff --git a/clang/test/CodeGen/builtins-systemz-zvector.c b/clang/test/CodeGen/builtins-systemz-zvector.c --- a/clang/test/CodeGen/builtins-systemz-zvector.c +++ b/clang/test/CodeGen/builtins-systemz-zvector.c @@ -4477,7 +4477,7 @@ // (emulated) vd = vec_ctd(vul, 1); // CHECK: [[VAL:%[^ ]+]] = uitofp <2 x i64> %{{.*}} to <2 x double> - // CHECK: fmul <2 x double> [[VAL]], + // CHECK: fmul nnan <2 x double> [[VAL]], // (emulated) vd = vec_ctd(vsl, 31); // CHECK: [[VAL:%[^ ]+]] = sitofp <2 x i64> %{{.*}} to <2 x double> @@ -4485,7 +4485,7 @@ // (emulated) vd = vec_ctd(vul, 31); // CHECK: [[VAL:%[^ ]+]] = uitofp <2 x i64> %{{.*}} to <2 x double> - // CHECK: fmul <2 x double> [[VAL]], + // CHECK: fmul nnan <2 x double> [[VAL]], // (emulated) vsl = vec_ctsl(vd, 0); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1580,7 +1580,9 @@ return replaceInstUsesWith(I, V); } - return nullptr; + return inferFastMathFlags(&I, {&I, I.getOperand(0), I.getOperand(1)}) + ? &I + : nullptr; } /// Optimize pointer differences into the same array into a size. Consider: @@ -2200,5 +2202,7 @@ return replaceInstUsesWith(I, V); } - return nullptr; + return inferFastMathFlags(&I, {&I, I.getOperand(0), I.getOperand(1)}) + ? &I + : nullptr; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6121,5 +6121,8 @@ if (Instruction *Res = foldVectorCmp(I, Builder)) return Res; + // Set fast math flags if both operands are compatible. + Changed |= inferFastMathFlags(&I, {I.getOperand(0), I.getOperand(1)}); + return Changed ? &I : nullptr; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -633,6 +633,11 @@ Instruction *foldIntrinsicWithOverflowCommon(IntrinsicInst *II); + /// Add fast math flags to the instruction if all Values statisfy the + /// constraints required by the flag, returning true if the instruction + /// was changed. + bool inferFastMathFlags(Instruction *I, ArrayRef Values) const; + public: /// Inserts an instruction \p New before instruction \p Old /// diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -570,7 +570,9 @@ } } - return nullptr; + return inferFastMathFlags(&I, {&I, I.getOperand(0), I.getOperand(1)}) + ? &I + : nullptr; } /// Fold a divide or remainder with a select instruction divisor when one of the diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1635,6 +1635,29 @@ return CastInst::Create(CastOpc, NarrowBO, BO.getType()); } +bool InstCombiner::inferFastMathFlags(Instruction *I, ArrayRef Values) const { + bool Changed = false; + if (!I->hasNoInfs() && + all_of(Values, [&](Value *V) { return isKnownNeverInfinity(V, &TLI); })) { + I->setHasNoInfs(true); + Changed = true; + } + + if (!I->hasNoNaNs() && + all_of(Values, [&](Value *V) { return isKnownNeverNaN(V, &TLI); })) { + I->setHasNoNaNs(true); + Changed = true; + } + + if (!I->hasNoSignedZeros() && + all_of(Values, [&](Value *V) { return CannotBeNegativeZero(V, &TLI); })) { + I->setHasNoSignedZeros(true); + Changed = true; + } + + return Changed; +} + Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector Ops(GEP.op_begin(), GEP.op_end()); Type *GEPType = GEP.getType(); diff --git a/llvm/test/Transforms/InstCombine/add-sitofp.ll b/llvm/test/Transforms/InstCombine/add-sitofp.ll --- a/llvm/test/Transforms/InstCombine/add-sitofp.ll +++ b/llvm/test/Transforms/InstCombine/add-sitofp.ll @@ -34,7 +34,7 @@ ; CHECK-LABEL: @test_neg( ; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 ; CHECK-NEXT: [[A_AND_FP:%.*]] = sitofp i32 [[A_AND]] to float -; CHECK-NEXT: [[RES:%.*]] = fadd float [[A_AND_FP]], 1.000000e+00 +; CHECK-NEXT: [[RES:%.*]] = fadd nnan float [[A_AND_FP]], 1.000000e+00 ; CHECK-NEXT: ret float [[RES]] ; ; Drop two highest bits to guarantee that %a + 1 doesn't overflow @@ -91,7 +91,7 @@ ; CHECK-NEXT: [[M:%.*]] = lshr i32 [[A:%.*]], 24 ; CHECK-NEXT: [[N:%.*]] = and i32 [[M]], [[B:%.*]] ; CHECK-NEXT: [[O:%.*]] = sitofp i32 [[N]] to float -; CHECK-NEXT: [[P:%.*]] = fadd float [[O]], 1.000000e+00 +; CHECK-NEXT: [[P:%.*]] = fadd nnan float [[O]], 1.000000e+00 ; CHECK-NEXT: ret float [[P]] ; %m = lshr i32 %a, 24 diff --git a/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll b/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll --- a/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll +++ b/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll @@ -274,7 +274,7 @@ define i1 @i32_cast_cmp_oeq_int_0_uitofp_ppcf128(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_0_uitofp_ppcf128( ; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to ppc_fp128 -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq ppc_fp128 [[F]], 0xM00000000000000000000000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ninf nsz oeq ppc_fp128 [[F]], 0xM00000000000000000000000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = uitofp i32 %i to ppc_fp128 @@ -314,7 +314,7 @@ define i1 @i32_cast_cmp_oeq_int_i24maxp1_uitofp(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24maxp1_uitofp( ; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0x4170000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ninf nsz oeq float [[F]], 0x4170000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = uitofp i32 %i to float @@ -326,7 +326,7 @@ define i1 @i32_cast_cmp_oeq_int_i24maxp1_sitofp(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24maxp1_sitofp( ; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0x4170000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan nsz oeq float [[F]], 0x4170000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = sitofp i32 %i to float @@ -337,7 +337,7 @@ define i1 @i32_cast_cmp_oeq_int_i32umax_uitofp(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32umax_uitofp( ; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0x41F0000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ninf nsz oeq float [[F]], 0x41F0000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = uitofp i32 %i to float @@ -368,7 +368,7 @@ define i1 @i32_cast_cmp_oeq_int_i32imin_sitofp(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imin_sitofp( ; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0xC1E0000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan nsz oeq float [[F]], 0xC1E0000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = sitofp i32 %i to float @@ -379,7 +379,7 @@ define i1 @i32_cast_cmp_oeq_int_i32imax_uitofp(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imax_uitofp( ; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0x41E0000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ninf nsz oeq float [[F]], 0x41E0000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = uitofp i32 %i to float @@ -390,7 +390,7 @@ define i1 @i32_cast_cmp_oeq_int_i32imax_sitofp(i32 %i) { ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imax_sitofp( ; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0x41E0000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan nsz oeq float [[F]], 0x41E0000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = sitofp i32 %i to float @@ -502,7 +502,7 @@ define i1 @i128_cast_cmp_oeq_int_inf_uitofp(i128 %i) { ; CHECK-LABEL: @i128_cast_cmp_oeq_int_inf_uitofp( ; CHECK-NEXT: [[F:%.*]] = uitofp i128 [[I:%.*]] to float -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[F]], 0x7FF0000000000000 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan nsz oeq float [[F]], 0x7FF0000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; %f = uitofp i128 %i to float diff --git a/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll b/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll --- a/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll +++ b/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll @@ -73,7 +73,7 @@ ; CHECK-LABEL: @fmul_fadd_not_enough_FMF( ; CHECK-NEXT: [[T1:%.*]] = fmul fast float [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[R:%.*]] = fadd reassoc float [[T1]], [[T2]] +; CHECK-NEXT: [[R:%.*]] = fadd reassoc nnan float [[T1]], [[T2]] ; CHECK-NEXT: ret float [[R]] ; %t1 = fmul fast float %x, %z @@ -199,7 +199,7 @@ ; CHECK-LABEL: @fmul_fsub_not_enough_FMF( ; CHECK-NEXT: [[T1:%.*]] = fmul fast float [[Z:%.*]], [[X:%.*]] ; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[R:%.*]] = fsub nsz float [[T1]], [[T2]] +; CHECK-NEXT: [[R:%.*]] = fsub nnan nsz float [[T1]], [[T2]] ; CHECK-NEXT: ret float [[R]] ; %t1 = fmul fast float %z, %x @@ -351,7 +351,7 @@ ; CHECK-LABEL: @fdiv_fadd_not_enough_FMF( ; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]] -; CHECK-NEXT: [[T3:%.*]] = fadd nsz float [[T1]], [[T2]] +; CHECK-NEXT: [[T3:%.*]] = fadd nnan nsz float [[T1]], [[T2]] ; CHECK-NEXT: ret float [[T3]] ; %t1 = fdiv fast float %y, %x @@ -366,7 +366,7 @@ ; CHECK-LABEL: @fdiv_fsub_not_enough_FMF( ; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]] -; CHECK-NEXT: [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]] +; CHECK-NEXT: [[T3:%.*]] = fsub reassoc nnan float [[T1]], [[T2]] ; CHECK-NEXT: ret float [[T3]] ; %t1 = fdiv fast float %y, %x diff --git a/llvm/test/Transforms/InstCombine/fast-math.ll b/llvm/test/Transforms/InstCombine/fast-math.ll --- a/llvm/test/Transforms/InstCombine/fast-math.ll +++ b/llvm/test/Transforms/InstCombine/fast-math.ll @@ -18,7 +18,7 @@ define float @notfold(float %a) { ; CHECK-LABEL: @notfold( ; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[A:%.*]], 0x3FF3333340000000 -; CHECK-NEXT: [[MUL1:%.*]] = fmul float [[MUL]], 0x4002666660000000 +; CHECK-NEXT: [[MUL1:%.*]] = fmul nnan float [[MUL]], 0x4002666660000000 ; CHECK-NEXT: ret float [[MUL1]] ; %mul = fmul fast float %a, 0x3FF3333340000000 diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -535,11 +535,11 @@ ; Do not fold 1.0 / X > 0.0 when ninf is missing define i1 @test24_recipX_noninf_cmp(float %X) { ; CHECK-LABEL: @test24_recipX_noninf_cmp( -; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv float 2.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[DIV]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[CMP]] ; - %div = fdiv ninf float 2.0, %X + %div = fdiv float 2.0, %X %cmp = fcmp ogt float %div, 0.0 ret i1 %cmp } diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll --- a/llvm/test/Transforms/InstCombine/known-never-nan.ll +++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll @@ -11,7 +11,7 @@ ; CHECK-LABEL: @fabs_sqrt_src_maybe_nan( ; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[ARG0:%.*]]) ; CHECK-NEXT: [[OP:%.*]] = call double @llvm.sqrt.f64(double [[FABS]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 +; CHECK-NEXT: [[TMP:%.*]] = fcmp nsz ord double [[OP]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[TMP]] ; %fabs = call double @llvm.fabs.f64(double %arg0) diff --git a/llvm/test/Transforms/InstCombine/minmax-fp.ll b/llvm/test/Transforms/InstCombine/minmax-fp.ll --- a/llvm/test/Transforms/InstCombine/minmax-fp.ll +++ b/llvm/test/Transforms/InstCombine/minmax-fp.ll @@ -273,7 +273,7 @@ ; CHECK-LABEL: define {{[^@]+}}@fsub_fmax( ; CHECK-NEXT: [[COND_INV:%.*]] = fcmp nnan nsz ogt <2 x float> [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = select nnan nsz <2 x i1> [[COND_INV]], <2 x float> [[Y]], <2 x float> [[X]] -; CHECK-NEXT: [[MAX:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: [[MAX:%.*]] = fsub nnan <2 x float> , [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[MAX]] ; %n1 = fsub <2 x float> , %x diff --git a/llvm/test/Transforms/InstCombine/pow_fp_int.ll b/llvm/test/Transforms/InstCombine/pow_fp_int.ll --- a/llvm/test/Transforms/InstCombine/pow_fp_int.ll +++ b/llvm/test/Transforms/InstCombine/pow_fp_int.ll @@ -91,7 +91,7 @@ define double @pow_uitofp_const_base_power_of_2_fast(i31 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_fast( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i31 [[X:%.*]] to float -; CHECK-NEXT: [[MUL:%.*]] = fmul afn float [[SUBFP]], 4.000000e+00 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan afn float [[SUBFP]], 4.000000e+00 ; CHECK-NEXT: [[EXP2:%.*]] = call afn float @llvm.exp2.f32(float [[MUL]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double ; CHECK-NEXT: ret double [[RES]] @@ -383,7 +383,7 @@ define double @pow_uitofp_const_base_power_of_2_no_fast(i32 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_power_of_2_no_fast( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUBFP]], 4.000000e+00 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[SUBFP]], 4.000000e+00 ; CHECK-NEXT: [[EXP2:%.*]] = call float @llvm.exp2.f32(float [[MUL]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double ; CHECK-NEXT: ret double [[RES]]