diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll | 497 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/fast-math.ll | 373 |
2 files changed, 497 insertions, 373 deletions
diff --git a/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll b/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll new file mode 100644 index 00000000000..da9afca0861 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fadd-fsub-factor.ll @@ -0,0 +1,497 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; ========================================================================= +; +; Test FP factorization with patterns: +; X * Z + Y * Z --> (X + Y) * Z (including all 4 commuted variants) +; X * Z - Y * Z --> (X - Y) * Z (including all 4 commuted variants) +; X / Z + Y / Z --> (X + Y) / Z +; X / Z - Y / Z --> (X - Y) / Z +; +; ========================================================================= + +; Minimum FMF - the final result requires/propagates FMF. + +define float @fmul_fadd(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fadd( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %x, %z + %t2 = fmul float %y, %z + %r = fadd reassoc nsz float %t1, %t2 + ret float %r +} + +; FIXME: +; Verify vector types and commuted operands. + +define <2 x float> @fmul_fadd_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fmul_fadd_commute1_vec( +; CHECK-NEXT: [[T1:%.*]] = fmul <2 x float> [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fmul <2 x float> [[Z]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz <2 x float> [[T1]], [[T2]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %t1 = fmul <2 x float> %z, %x + %t2 = fmul <2 x float> %z, %y + %r = fadd reassoc nsz <2 x float> %t1, %t2 + ret <2 x float> %r +} + +; FIXME: +; Verify vector types, commuted operands, FMF propagation. + +define <2 x float> @fmul_fadd_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fmul_fadd_commute2_vec( +; CHECK-NEXT: [[T1:%.*]] = fmul fast <2 x float> [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fmul nnan <2 x float> [[Z]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = fadd reassoc ninf nsz <2 x float> [[T1]], [[T2]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %t1 = fmul fast <2 x float> %x, %z + %t2 = fmul nnan <2 x float> %z, %y + %r = fadd reassoc nsz ninf <2 x float> %t1, %t2 + ret <2 x float> %r +} + +; Verify different scalar type, commuted operands, FMF propagation. + +define double @fmul_fadd_commute3(double %x, double %y, double %z) { +; CHECK-LABEL: @fmul_fadd_commute3( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nnan nsz double [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret double [[TMP2]] +; + %t1 = fmul double %z, %x + %t2 = fmul fast double %y, %z + %r = fadd reassoc nsz nnan double %t1, %t2 + ret double %r +} + +; Negative test - verify the fold is not done with only 'reassoc' ('nsz' is required). + +define float @fmul_fadd_not_enough_FMF(float %x, float %y, float %z) { +; 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: ret float [[R]] +; + %t1 = fmul fast float %x, %z + %t2 = fmul fast float %y, %z + %r = fadd reassoc float %t1, %t2 + ret float %r +} + +declare void @use(float) + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fmul_fadd_uses1(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fadd_uses1( +; CHECK-NEXT: [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T1]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %z, %x + %t2 = fmul float %y, %z + %r = fadd reassoc nsz float %t1, %t2 + call void @use(float %t1) + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fmul_fadd_uses2(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fadd_uses2( +; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T2]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %z, %x + %t2 = fmul float %z, %y + %r = fadd reassoc nsz float %t1, %t2 + call void @use(float %t2) + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fmul_fadd_uses3(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fadd_uses3( +; CHECK-NEXT: [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T1]]) +; CHECK-NEXT: call void @use(float [[T2]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %x, %z + %t2 = fmul float %z, %y + %r = fadd reassoc nsz float %t1, %t2 + call void @use(float %t1) + call void @use(float %t2) + ret float %r +} + +; Minimum FMF - the final result requires/propagates FMF. + +define half @fmul_fsub(half %x, half %y, half %z) { +; CHECK-LABEL: @fmul_fsub( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz half [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz half [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret half [[TMP2]] +; + %t1 = fmul half %x, %z + %t2 = fmul half %y, %z + %r = fsub reassoc nsz half %t1, %t2 + ret half %r +} + +; FIXME: +; Verify vector types and commuted operands. + +define <2 x float> @fmul_fsub_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fmul_fsub_commute1_vec( +; CHECK-NEXT: [[T1:%.*]] = fmul <2 x float> [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fmul <2 x float> [[Y:%.*]], [[Z]] +; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> [[T1]], [[T2]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %t1 = fmul <2 x float> %z, %x + %t2 = fmul <2 x float> %y, %z + %r = fsub reassoc nsz <2 x float> %t1, %t2 + ret <2 x float> %r +} + +; FIXME: +; Verify vector types, commuted operands, FMF propagation. + +define <2 x float> @fmul_fsub_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fmul_fsub_commute2_vec( +; CHECK-NEXT: [[T1:%.*]] = fmul fast <2 x float> [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fmul nnan <2 x float> [[Z]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = fsub reassoc ninf nsz <2 x float> [[T1]], [[T2]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %t1 = fmul fast <2 x float> %x, %z + %t2 = fmul nnan <2 x float> %z, %y + %r = fsub reassoc nsz ninf <2 x float> %t1, %t2 + ret <2 x float> %r +} + +; Verify different scalar type, commuted operands, FMF propagation. + +define double @fmul_fsub_commute3(double %x, double %y, double %z) { +; CHECK-LABEL: @fmul_fsub_commute3( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nnan nsz double [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret double [[TMP2]] +; + %t1 = fmul double %z, %x + %t2 = fmul fast double %z, %y + %r = fsub reassoc nsz nnan double %t1, %t2 + ret double %r +} + +; Negative test - verify the fold is not done with only 'nsz' ('reassoc' is required). + +define float @fmul_fsub_not_enough_FMF(float %x, float %y, float %z) { +; 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: ret float [[R]] +; + %t1 = fmul fast float %z, %x + %t2 = fmul fast float %y, %z + %r = fsub nsz float %t1, %t2 + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fmul_fsub_uses1(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fsub_uses1( +; CHECK-NEXT: [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T1]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %x, %z + %t2 = fmul float %y, %z + %r = fsub reassoc nsz float %t1, %t2 + call void @use(float %t1) + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fmul_fsub_uses2(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fsub_uses2( +; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T2]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %z, %x + %t2 = fmul float %z, %y + %r = fsub reassoc nsz float %t1, %t2 + call void @use(float %t2) + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fmul_fsub_uses3(float %x, float %y, float %z) { +; CHECK-LABEL: @fmul_fsub_uses3( +; CHECK-NEXT: [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T1]]) +; CHECK-NEXT: call void @use(float [[T2]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul float %x, %z + %t2 = fmul float %y, %z + %r = fsub reassoc nsz float %t1, %t2 + call void @use(float %t1) + call void @use(float %t2) + ret float %r +} + +; Common divisor + +define double @fdiv_fadd(double %x, double %y, double %z) { +; CHECK-LABEL: @fdiv_fadd( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz double [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc nsz double [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret double [[TMP2]] +; + %t1 = fdiv double %x, %z + %t2 = fdiv double %y, %z + %r = fadd reassoc nsz double %t1, %t2 + ret double %r +} + +define float @fdiv_fsub(float %x, float %y, float %z) { +; CHECK-LABEL: @fdiv_fsub( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc nsz float [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fdiv fast float %x, %z + %t2 = fdiv nnan float %y, %z + %r = fsub reassoc nsz float %t1, %t2 + ret float %r +} + +; FIXME: +; Verify vector types. + +define <2 x double> @fdiv_fadd_vec(<2 x double> %x, <2 x double> %y, <2 x double> %z) { +; CHECK-LABEL: @fdiv_fadd_vec( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast <2 x double> [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv <2 x double> [[Y:%.*]], [[Z]] +; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz <2 x double> [[T1]], [[T2]] +; CHECK-NEXT: ret <2 x double> [[R]] +; + %t1 = fdiv fast <2 x double> %x, %z + %t2 = fdiv <2 x double> %y, %z + %r = fadd reassoc nsz <2 x double> %t1, %t2 + ret <2 x double> %r +} + +; FIXME: +; Verify vector types. + +define <2 x float> @fdiv_fsub_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fdiv_fsub_vec( +; CHECK-NEXT: [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv nnan <2 x float> [[Y:%.*]], [[Z]] +; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> [[T1]], [[T2]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %t1 = fdiv <2 x float> %x, %z + %t2 = fdiv nnan <2 x float> %y, %z + %r = fsub reassoc nsz <2 x float> %t1, %t2 + ret <2 x float> %r +} + +; Negative test - common operand is not divisor. + +define float @fdiv_fadd_commute1(float %x, float %y, float %z) { +; CHECK-LABEL: @fdiv_fadd_commute1( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fadd fast float [[T1]], [[T2]] +; CHECK-NEXT: ret float [[R]] +; + %t1 = fdiv fast float %z, %y + %t2 = fdiv fast float %z, %x + %r = fadd fast float %t1, %t2 + ret float %r +} + +; Negative test - common operand is not divisor. + +define float @fdiv_fsub_commute2(float %x, float %y, float %z) { +; CHECK-LABEL: @fdiv_fsub_commute2( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[X:%.*]], [[Z]] +; CHECK-NEXT: [[R:%.*]] = fsub fast float [[T1]], [[T2]] +; CHECK-NEXT: ret float [[R]] +; + %t1 = fdiv fast float %z, %y + %t2 = fdiv fast float %x, %z + %r = fsub fast float %t1, %t2 + ret float %r +} + +; Negative test - verify the fold is not done with only 'nsz' ('reassoc' is required). + +define float @fdiv_fadd_not_enough_FMF(float %x, float %y, float %z) { +; 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: ret float [[T3]] +; + %t1 = fdiv fast float %y, %x + %t2 = fdiv fast float %z, %x + %t3 = fadd nsz float %t1, %t2 + ret float %t3 +} + +; Negative test - verify the fold is not done with only 'reassoc' ('nsz' is required). + +define float @fdiv_fsub_not_enough_FMF(float %x, float %y, float %z) { +; 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: ret float [[T3]] +; + %t1 = fdiv fast float %y, %x + %t2 = fdiv fast float %z, %x + %t3 = fsub reassoc float %t1, %t2 + ret float %t3 +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fdiv_fadd_uses1(float %x, float %y, float %z) { +; CHECK-LABEL: @fdiv_fadd_uses1( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[X]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T1]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fdiv fast float %x, %z + %t2 = fdiv fast float %y, %z + %r = fadd fast float %t1, %t2 + call void @use(float %t1) + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fdiv_fsub_uses2(float %x, float %y, float %z) { +; CHECK-LABEL: @fdiv_fsub_uses2( +; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[X:%.*]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T2]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fdiv fast float %x, %z + %t2 = fdiv fast float %y, %z + %r = fsub fast float %t1, %t2 + call void @use(float %t2) + ret float %r +} + +; FIXME: +; Negative test - extra uses should disable the fold. + +define float @fdiv_fsub_uses3(float %x, float %y, float %z) { +; CHECK-LABEL: @fdiv_fsub_uses3( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[X]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[Z]] +; CHECK-NEXT: call void @use(float [[T1]]) +; CHECK-NEXT: call void @use(float [[T2]]) +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fdiv fast float %x, %z + %t2 = fdiv fast float %y, %z + %r = fsub fast float %t1, %t2 + call void @use(float %t1) + call void @use(float %t2) + ret float %r +} + +; Constants are fine to combine if they are not denorms. + +define float @fdiv_fadd_not_denorm(float %x) { +; CHECK-LABEL: @fdiv_fadd_not_denorm( +; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float 0x3818000000000000, [[X:%.*]] +; CHECK-NEXT: ret float [[TMP1]] +; + %t1 = fdiv fast float 0x3810000000000000, %x + %t2 = fdiv fast float 0x3800000000000000, %x + %r = fadd fast float %t1, %t2 + ret float %r +} + +; Negative test - disabled if x+y is denormal. + +define float @fdiv_fadd_denorm(float %x) { +; CHECK-LABEL: @fdiv_fadd_denorm( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast float 0xB810000000000000, [[X:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]] +; CHECK-NEXT: [[R:%.*]] = fadd fast float [[T1]], [[T2]] +; CHECK-NEXT: ret float [[R]] +; + %t1 = fdiv fast float 0xB810000000000000, %x + %t2 = fdiv fast float 0x3800000000000000, %x + %r = fadd fast float %t1, %t2 + ret float %r +} + +; Negative test - disabled if x-y is denormal. + +define float @fdiv_fsub_denorm(float %x) { +; CHECK-LABEL: @fdiv_fsub_denorm( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast float 0x3810000000000000, [[X:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]] +; CHECK-NEXT: [[R:%.*]] = fsub fast float [[T1]], [[T2]] +; CHECK-NEXT: ret float [[R]] +; + %t1 = fdiv fast float 0x3810000000000000, %x + %t2 = fdiv fast float 0x3800000000000000, %x + %r = fsub fast float %t1, %t2 + ret float %r +} + diff --git a/llvm/test/Transforms/InstCombine/fast-math.ll b/llvm/test/Transforms/InstCombine/fast-math.ll index 7a62eef8ac2..a3bfdc6ada2 100644 --- a/llvm/test/Transforms/InstCombine/fast-math.ll +++ b/llvm/test/Transforms/InstCombine/fast-math.ll @@ -622,379 +622,6 @@ define float @fdiv4(float %x) { ; ========================================================================= ; -; Testing-cases about factorization -; -; ========================================================================= -; x*z + y*z => (x+y) * z -define float @fact_mul1(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul1( -; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul fast float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul fast float %x, %z - %t2 = fmul fast float %y, %z - %t3 = fadd fast float %t1, %t2 - ret float %t3 -} - -; Check again using the minimal subset of FMF. -define float @fact_mul1_reassoc_nsz(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul1_reassoc_nsz( -; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul reassoc nsz float %x, %z - %t2 = fmul reassoc nsz float %y, %z - %t3 = fadd reassoc nsz float %t1, %t2 - ret float %t3 -} - -; Verify the fold is not done with only 'reassoc' ('nsz' is required). -define float @fact_mul1_reassoc(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul1_reassoc( -; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[T3:%.*]] = fadd reassoc float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fmul reassoc float %x, %z - %t2 = fmul reassoc float %y, %z - %t3 = fadd reassoc float %t1, %t2 - ret float %t3 -} - -; z*x + y*z => (x+y) * z -define float @fact_mul2(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul2( -; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul fast float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul fast float %z, %x - %t2 = fmul fast float %y, %z - %t3 = fsub fast float %t1, %t2 - ret float %t3 -} - -; Check again using the minimal subset of FMF. -define float @fact_mul2_reassoc_nsz(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul2_reassoc_nsz( -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul reassoc nsz float %z, %x - %t2 = fmul reassoc nsz float %y, %z - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -; Verify the fold is not done with only 'reassoc' ('nsz' is required). -define float @fact_mul2_reassoc(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul2_reassoc( -; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fmul reassoc float %z, %x - %t2 = fmul reassoc float %y, %z - %t3 = fsub reassoc float %t1, %t2 - ret float %t3 -} - -; z*x - z*y => (x-y) * z -define float @fact_mul3(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul3( -; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul fast float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t2 = fmul fast float %z, %y - %t1 = fmul fast float %z, %x - %t3 = fsub fast float %t1, %t2 - ret float %t3 -} - -; Check again using the minimal subset of FMF. -define float @fact_mul3_reassoc_nsz(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul3_reassoc_nsz( -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t2 = fmul reassoc nsz float %z, %y - %t1 = fmul reassoc nsz float %z, %x - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -; Verify the fold is not done with only 'reassoc' ('nsz' is required). -define float @fact_mul3_reassoc(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul3_reassoc( -; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[Z:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[Z]], [[X:%.*]] -; CHECK-NEXT: [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t2 = fmul reassoc float %z, %y - %t1 = fmul reassoc float %z, %x - %t3 = fsub reassoc float %t1, %t2 - ret float %t3 -} - -; x*z - z*y => (x-y) * z -define float @fact_mul4(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4( -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul float %x, %z - %t2 = fmul float %z, %y - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -define float @fact_mul4_commute1(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4_commute1( -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul float %x, %z - %t2 = fmul float %y, %z - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -define float @fact_mul4_commute2(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4_commute2( -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul float %z, %x - %t2 = fmul float %y, %z - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -define <2 x float> @fact_mul4_commute3_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { -; CHECK-LABEL: @fact_mul4_commute3_vec( -; CHECK-NEXT: [[T1:%.*]] = fmul <2 x float> [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fmul <2 x float> [[Z]], [[Y:%.*]] -; CHECK-NEXT: [[T3:%.*]] = fsub reassoc nsz <2 x float> [[T1]], [[T2]] -; CHECK-NEXT: ret <2 x float> [[T3]] -; - %t1 = fmul <2 x float> %z, %x - %t2 = fmul <2 x float> %z, %y - %t3 = fsub reassoc nsz <2 x float> %t1, %t2 - ret <2 x float> %t3 -} - -declare void @use(float) - -define float @fact_mul4_uses1(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4_uses1( -; CHECK-NEXT: [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: call void @use(float [[T1]]) -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X]], [[Y:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul float %z, %x - call void @use(float %t1) - %t2 = fmul float %y, %z - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -define float @fact_mul4_uses2(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4_uses2( -; CHECK-NEXT: [[T2:%.*]] = fmul float [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: call void @use(float [[T2]]) -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul float %x, %z - %t2 = fmul float %y, %z - call void @use(float %t2) - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -define float @fact_mul4_uses3(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4_uses3( -; CHECK-NEXT: [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: call void @use(float [[T1]]) -; CHECK-NEXT: [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]] -; CHECK-NEXT: call void @use(float [[T2]]) -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X]], [[Y]] -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fmul float %z, %x - call void @use(float %t1) - %t2 = fmul float %z, %y - call void @use(float %t2) - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -; Verify the fold is not done with only 'reassoc' ('nsz' is required). -define float @fact_mul4_reassoc(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_mul4_reassoc( -; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[Z]], [[Y:%.*]] -; CHECK-NEXT: [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fmul reassoc float %x, %z - %t2 = fmul reassoc float %z, %y - %t3 = fsub reassoc float %t1, %t2 - ret float %t3 -} - -; x/y + x/z, no xform -define float @fact_div1(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div1( -; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[X]], [[Z:%.*]] -; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fdiv fast float %x, %y - %t2 = fdiv fast float %x, %z - %t3 = fadd fast float %t1, %t2 - ret float %t3 -} - -; x/y + z/x; no xform -define float @fact_div2(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div2( -; CHECK-NEXT: [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fdiv fast float [[Z:%.*]], [[X]] -; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fdiv fast float %x, %y - %t2 = fdiv fast float %z, %x - %t3 = fadd fast float %t1, %t2 - ret float %t3 -} - -; y/x + z/x => (y+z)/x -define float @fact_div3(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div3( -; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[X:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fdiv fast float %y, %x - %t2 = fdiv fast float %z, %x - %t3 = fadd fast float %t1, %t2 - ret float %t3 -} - -; Check again using the minimal subset of FMF. -define float @fact_div3_reassoc_nsz(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div3_reassoc_nsz( -; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc nsz float [[TMP1]], [[X:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fdiv reassoc nsz float %y, %x - %t2 = fdiv reassoc nsz float %z, %x - %t3 = fadd reassoc nsz float %t1, %t2 - ret float %t3 -} - -; Verify the fold is not done with only 'reassoc' ('nsz' is required). -define float @fact_div3_reassoc(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div3_reassoc( -; CHECK-NEXT: [[T1:%.*]] = fdiv reassoc float [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc float [[Z:%.*]], [[X]] -; CHECK-NEXT: [[T3:%.*]] = fadd reassoc float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fdiv reassoc float %y, %x - %t2 = fdiv reassoc float %z, %x - %t3 = fadd reassoc float %t1, %t2 - ret float %t3 -} - -; y/x - z/x => (y-z)/x -define float @fact_div4(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div4( -; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[X:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fdiv fast float %y, %x - %t2 = fdiv fast float %z, %x - %t3 = fsub fast float %t1, %t2 - ret float %t3 -} - -; Check again using the minimal subset of FMF. -define float @fact_div4_reassoc_nsz(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div4_reassoc_nsz( -; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc nsz float [[TMP1]], [[X:%.*]] -; CHECK-NEXT: ret float [[TMP2]] -; - %t1 = fdiv reassoc nsz float %y, %x - %t2 = fdiv reassoc nsz float %z, %x - %t3 = fsub reassoc nsz float %t1, %t2 - ret float %t3 -} - -; Verify the fold is not done with only 'reassoc' ('nsz' is required). -define float @fact_div4_reassoc(float %x, float %y, float %z) { -; CHECK-LABEL: @fact_div4_reassoc( -; CHECK-NEXT: [[T1:%.*]] = fdiv reassoc float [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc float [[Z:%.*]], [[X]] -; CHECK-NEXT: [[T3:%.*]] = fsub reassoc float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fdiv reassoc float %y, %x - %t2 = fdiv reassoc float %z, %x - %t3 = fsub reassoc float %t1, %t2 - ret float %t3 -} - -; y/x - z/x => (y-z)/x is disabled if y-z is denormal. -define float @fact_div5(float %x) { -; CHECK-LABEL: @fact_div5( -; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float 0x3818000000000000, [[X:%.*]] -; CHECK-NEXT: ret float [[TMP1]] -; - %t1 = fdiv fast float 0x3810000000000000, %x - %t2 = fdiv fast float 0x3800000000000000, %x - %t3 = fadd fast float %t1, %t2 - ret float %t3 -} - -; y/x - z/x => (y-z)/x is disabled if y-z is denormal. -define float @fact_div6(float %x) { -; CHECK-LABEL: @fact_div6( -; CHECK-NEXT: [[T1:%.*]] = fdiv fast float 0x3810000000000000, [[X:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fdiv fast float 0x3800000000000000, [[X]] -; CHECK-NEXT: [[T3:%.*]] = fsub fast float [[T1]], [[T2]] -; CHECK-NEXT: ret float [[T3]] -; - %t1 = fdiv fast float 0x3810000000000000, %x - %t2 = fdiv fast float 0x3800000000000000, %x - %t3 = fsub fast float %t1, %t2 - ret float %t3 -} - -; ========================================================================= -; ; Test-cases for square root ; ; ========================================================================= |