Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/lib/IR/Instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,7 @@ bool Instruction::isAssociative() const {

switch (Opcode) {
case FMul:
return cast<FPMathOperator>(this)->hasAllowReassoc();
case FAdd:
return cast<FPMathOperator>(this)->hasAllowReassoc() &&
cast<FPMathOperator>(this)->hasNoSignedZeros();
Expand Down
288 changes: 288 additions & 0 deletions llvm/test/Transforms/Attributor/nofpclass-fmul.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal < %s | FileCheck %s

; Test that multiply by a constant with a sufficiently large exponent
; proves the result is not subnormal.

define float @ret_fmul_f32(float %arg0, float %arg1) {
; CHECK-LABEL: define float @ret_fmul_f32(
; CHECK-SAME: float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FMUL]]
;
%fmul = fmul float %arg0, %arg1
ret float %fmul
}

define float @ret_fmul_square_f32(float %arg) {
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_fmul_square_f32(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[ARG]], [[ARG]]
; CHECK-NEXT: ret float [[FMUL]]
;
%fmul = fmul float %arg, %arg
ret float %fmul
}

define float @ret_mul_exponent_f32_22(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_22(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4150000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x4150000000000000
ret float %call
}

define float @ret_mul_exponent_f32_23(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_23(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4160000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x4160000000000000
ret float %call
}

define float @ret_mul_exponent_f32_24(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_24(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4170000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x4170000000000000
ret float %call
}

define float @ret_mul_exponent_f32_23_nnan(float nofpclass(nan) %arg0) {
; CHECK-LABEL: define nofpclass(nan) float @ret_mul_exponent_f32_23_nnan(
; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4160000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x4160000000000000
ret float %call
}

define double @ret_mul_exponent_f64_24(double %arg0) {
; CHECK-LABEL: define double @ret_mul_exponent_f64_24(
; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4170000000000000
; CHECK-NEXT: ret double [[CALL]]
;
%call = fmul double %arg0, 0x4170000000000000
ret double %call
}

define double @ret_mul_exponent_f64_51(double %arg0) {
; CHECK-LABEL: define double @ret_mul_exponent_f64_51(
; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4320000000000000
; CHECK-NEXT: ret double [[CALL]]
;
%call = fmul double %arg0, 0x4320000000000000
ret double %call
}

define double @ret_mul_exponent_f64_52(double %arg0) {
; CHECK-LABEL: define double @ret_mul_exponent_f64_52(
; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4330000000000000
; CHECK-NEXT: ret double [[CALL]]
;
%call = fmul double %arg0, 0x4330000000000000
ret double %call
}

define double @ret_mul_exponent_f64_53(double %arg0) {
; CHECK-LABEL: define double @ret_mul_exponent_f64_53(
; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4340000000000000
; CHECK-NEXT: ret double [[CALL]]
;
%call = fmul double %arg0, 0x4340000000000000
ret double %call
}

define half @ret_mul_exponent_f16_8(half %arg0) {
; CHECK-LABEL: define half @ret_mul_exponent_f16_8(
; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul half [[ARG0]], 0xH5C00
; CHECK-NEXT: ret half [[CALL]]
;
%call = fmul half %arg0, 0xH5C00
ret half %call
}

define half @ret_mul_exponent_f16_9(half %arg0) {
; CHECK-LABEL: define half @ret_mul_exponent_f16_9(
; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul half [[ARG0]], 0xH6000
; CHECK-NEXT: ret half [[CALL]]
;
%call = fmul half %arg0, 0xH6000
ret half %call
}

define half @ret_mul_exponent_f16_10(half %arg0) {
; CHECK-LABEL: define half @ret_mul_exponent_f16_10(
; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul half [[ARG0]], 0xH6400
; CHECK-NEXT: ret half [[CALL]]
;
%call = fmul half %arg0, 0xH6400
ret half %call
}

define bfloat @ret_mul_exponent_bf16_6(bfloat %arg0) {
; CHECK-LABEL: define bfloat @ret_mul_exponent_bf16_6(
; CHECK-SAME: bfloat [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul bfloat [[ARG0]], 0xR4280
; CHECK-NEXT: ret bfloat [[CALL]]
;
%call = fmul bfloat %arg0, 0xR4280
ret bfloat %call
}

define bfloat @ret_mul_exponent_bf16_7(bfloat %arg0) {
; CHECK-LABEL: define bfloat @ret_mul_exponent_bf16_7(
; CHECK-SAME: bfloat [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul bfloat [[ARG0]], 0xR4300
; CHECK-NEXT: ret bfloat [[CALL]]
;
%call = fmul bfloat %arg0, 0xR4300
ret bfloat %call
}

define bfloat @ret_mul_exponent_bf16_8(bfloat %arg0) {
; CHECK-LABEL: define bfloat @ret_mul_exponent_bf16_8(
; CHECK-SAME: bfloat [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul bfloat [[ARG0]], 0xR4380
; CHECK-NEXT: ret bfloat [[CALL]]
;
%call = fmul bfloat %arg0, 0xR4380
ret bfloat %call
}

define float @ret_mul_exponent_f32_neg22(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_neg22(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3E90000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x3E90000000000000
ret float %call
}

define float @ret_mul_exponent_f32_neg23(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_neg23(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3E80000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x3E80000000000000
ret float %call
}

define float @ret_mul_exponent_f32_neg24(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_neg24(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3E70000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x3E70000000000000
ret float %call
}

define float @ret_mul_exponent_f32_neg126(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_neg126(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3810000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x3810000000000000
ret float %call
}

define float @ret_mul_exponent_f32_neg127(float %arg0) {
; CHECK-LABEL: define float @ret_mul_exponent_f32_neg127(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3800000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x3800000000000000
ret float %call
}

define <2 x float> @ret_mul_exponent_v2f32_splat_23(<2 x float> %arg0) {
; CHECK-LABEL: define <2 x float> @ret_mul_exponent_v2f32_splat_23(
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], splat (float 0x4160000000000000)
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
%call = fmul <2 x float> %arg0, splat (float 0x4160000000000000)
ret <2 x float> %call
}

define <2 x float> @ret_mul_exponent_v2f32_splat_poison_23(<2 x float> %arg0) {
; CHECK-LABEL: define <2 x float> @ret_mul_exponent_v2f32_splat_poison_23(
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], <float 0x4160000000000000, float poison>
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
%call = fmul <2 x float> %arg0, <float 0x4160000000000000, float poison>
ret <2 x float> %call
}

; TODO: Should be able to prove nofpclass(sub)
define <2 x float> @ret_mul_exponent_v2f32_nonsplat(<2 x float> %arg0) {
; CHECK-LABEL: define <2 x float> @ret_mul_exponent_v2f32_nonsplat(
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], <float 0x4160000000000000, float 0x4170000000000000>
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
%call = fmul <2 x float> %arg0, <float 0x4160000000000000, float 0x4170000000000000>
ret <2 x float> %call
}

; Cannot prove this is not-subnormal
define <2 x float> @ret_mul_partially_foldable_exponent_v2f32(<2 x float> %arg0) {
; CHECK-LABEL: define <2 x float> @ret_mul_partially_foldable_exponent_v2f32(
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], <float 0x4160000000000000, float 0x4150000000000000>
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
%call = fmul <2 x float> %arg0, <float 0x4160000000000000, float 0x4150000000000000>
ret <2 x float> %call
}

define float @ret_mul_f32_0(float %arg0) {
; CHECK-LABEL: define float @ret_mul_f32_0(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0.000000e+00
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0.0
ret float %call
}

define float @ret_mul_f32_inf(float %arg0) {
; CHECK-LABEL: define float @ret_mul_f32_inf(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x7FF0000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x7FF0000000000000
ret float %call
}

define float @ret_mul_f32_nan(float %arg0) {
; CHECK-LABEL: define float @ret_mul_f32_nan(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x7FF8000000000000
; CHECK-NEXT: ret float [[CALL]]
;
%call = fmul float %arg0, 0x7FF8000000000000
ret float %call
}

6 changes: 2 additions & 4 deletions llvm/test/Transforms/InstCombine/2006-10-26-VectorReassoc.ll
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@ define <4 x float> @test_fmul_reassoc_nsz(<4 x float> %V) {
}

; (V * C1) * C2 => V * (C1 * C2)
; TODO: This doesn't require 'nsz'. It should fold to V * { 1.0, 4.0e+05, -9.0, 16.0 }
define <4 x float> @test_fmul_reassoc(<4 x float> %V) {
; CHECK-LABEL: @test_fmul_reassoc(
; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc <4 x float> [[V:%.*]], <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>
; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc <4 x float> [[TMP1]], <float 1.000000e+00, float 2.000000e+05, float -3.000000e+00, float 4.000000e+00>
; CHECK-NEXT: ret <4 x float> [[TMP2]]
; CHECK: [[TMP1:%.*]] = fmul reassoc <4 x float> %V, <float 1.000000e+00, float 4.000000e+05, float -9.000000e+00, float 1.600000e+01>
; CHECK-NEXT: ret <4 x float> [[TMP1]]
%Y = fmul reassoc <4 x float> %V, < float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00 >
%Z = fmul reassoc <4 x float> %Y, < float 1.000000e+00, float 2.000000e+05, float -3.000000e+00, float 4.000000e+00 >
ret <4 x float> %Z
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/Transforms/InstCombine/fdiv.ll
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,7 @@ define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) {

define <2 x float> @div_constant_dividend3(<2 x float> %x) {
; CHECK-LABEL: @div_constant_dividend3(
; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 1.500000e+01, float -7.000000e+00>
; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 0x3FD5555560000000, float 0x3FC24924A0000000>
; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 5.000000e+00, float -1.000000e+00>
; CHECK-NEXT: ret <2 x float> [[T2]]
;
%t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %x
Expand Down
18 changes: 6 additions & 12 deletions llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ define float @fmul(float %x) {
define float @fmul_reassoc(float %x) {
; CHECK-LABEL: define float @fmul_reassoc(
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 2.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], 8.000000e+00
; CHECK-NEXT: ret float [[FMUL1]]
;
%fmul0 = fmul reassoc float %x, 2.0
Expand All @@ -37,8 +36,7 @@ define float @fmul_reassoc(float %x) {
define <2 x float> @fmul_reassoc_v2(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @fmul_reassoc_v2(
; CHECK-SAME: <2 x float> [[X:%.*]]) {
; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc <2 x float> [[X]], splat (float 2.000000e+00)
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc <2 x float> [[FMUL0]], splat (float 4.000000e+00)
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc <2 x float> [[X]], splat (float 8.000000e+00)
; CHECK-NEXT: ret <2 x float> [[FMUL1]]
;
%fmul0 = fmul reassoc <2 x float> %x, splat (float 2.0)
Expand All @@ -54,8 +52,7 @@ define <2 x float> @fmul_reassoc_v2(<2 x float> %x) {
define float @fmul_reassoc_negative_0(float %x) {
; CHECK-LABEL: define float @fmul_reassoc_negative_0(
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 2.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], -4.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], -8.000000e+00
; CHECK-NEXT: ret float [[FMUL1]]
;
%fmul0 = fmul reassoc float %x, 2.0
Expand All @@ -71,8 +68,7 @@ define float @fmul_reassoc_negative_0(float %x) {
define float @fmul_reassoc_negative_1(float %x) {
; CHECK-LABEL: define float @fmul_reassoc_negative_1(
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], -2.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], -8.000000e+00
; CHECK-NEXT: ret float [[FMUL1]]
;
%fmul0 = fmul reassoc float %x, -2.0
Expand All @@ -95,8 +91,7 @@ define float @fmul_reassoc_nsz(float %x) {
define float @fmul_reassoc_posk_neg0(float %x) {
; CHECK-LABEL: define float @fmul_reassoc_posk_neg0(
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 4.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], -0.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], -0.000000e+00
; CHECK-NEXT: ret float [[FMUL1]]
;
%fmul0 = fmul reassoc float %x, 4.0
Expand All @@ -108,8 +103,7 @@ define float @fmul_reassoc_neg0_posk(float %x) {
; CHECK-LABEL: define float @fmul_reassoc_neg0_posk(
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], -0.000000e+00
; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00
; CHECK-NEXT: ret float [[FMUL1]]
; CHECK-NEXT: ret float [[FMUL0]]
;
%fmul0 = fmul reassoc float %x, -0.0
%fmul1 = fmul reassoc float %fmul0, 4.0
Expand Down
Loading