Skip to content

Commit 7e6e6c1

Browse files
committed
[InstCombine] Fold tan(x) * cos(x) => sin(x)
Summary: This patch enables folding tan(x) * cos(x) -> sin(x) under -ffast-math flag
1 parent 0df6432 commit 7e6e6c1

File tree

2 files changed

+21
-27
lines changed

2 files changed

+21
-27
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,18 @@ Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
10721072
return Result;
10731073
}
10741074

1075+
// tan(X) * cos(X) -> sin(X)
1076+
if (I.hasAllowContract() &&
1077+
match(&I,
1078+
m_c_FMul(m_OneUse(m_Intrinsic<Intrinsic::tan>(m_Value(X))),
1079+
m_OneUse(m_Intrinsic<Intrinsic::cos>(m_Deferred(X)))))) {
1080+
auto *Sin = Builder.CreateUnaryIntrinsic(Intrinsic::sin, X, &I);
1081+
if (auto *Metadata = I.getMetadata(LLVMContext::MD_fpmath)) {
1082+
Sin->setMetadata(LLVMContext::MD_fpmath, Metadata);
1083+
}
1084+
return replaceInstUsesWith(I, Sin);
1085+
}
1086+
10751087
return nullptr;
10761088
}
10771089

llvm/test/Transforms/InstCombine/fmul-tan-cos.ll

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ define double @fmul_strict_tan_strict_cos_contract(double %a) {
3232
define double @fmul_contract_tan_strict_cos_strict(double %a) {
3333
; CHECK-LABEL: define double @fmul_contract_tan_strict_cos_strict(
3434
; CHECK-SAME: double [[A:%.*]]) {
35-
; CHECK-NEXT: [[TAN:%.*]] = call double @llvm.tan.f64(double [[A]])
36-
; CHECK-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[A]])
37-
; CHECK-NEXT: [[RES:%.*]] = fmul contract double [[TAN]], [[COS]]
35+
; CHECK-NEXT: [[RES:%.*]] = call contract double @llvm.sin.f64(double [[A]])
3836
; CHECK-NEXT: ret double [[RES]]
3937
;
4038
%tan = call double @llvm.tan.f64(double %a)
@@ -46,9 +44,7 @@ define double @fmul_contract_tan_strict_cos_strict(double %a) {
4644
define double @fmul_contract_tan_contract_cos_strict(double %a) {
4745
; CHECK-LABEL: define double @fmul_contract_tan_contract_cos_strict(
4846
; CHECK-SAME: double [[A:%.*]]) {
49-
; CHECK-NEXT: [[TAN:%.*]] = call contract double @llvm.tan.f64(double [[A]])
50-
; CHECK-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[A]])
51-
; CHECK-NEXT: [[RES:%.*]] = fmul contract double [[TAN]], [[COS]]
47+
; CHECK-NEXT: [[RES:%.*]] = call contract double @llvm.sin.f64(double [[A]])
5248
; CHECK-NEXT: ret double [[RES]]
5349
;
5450
%tan = call contract double @llvm.tan.f64(double %a)
@@ -76,9 +72,7 @@ define double @fmul_tan_cos_contract_multiple_uses(double %a) {
7672
define double @fmul_tan_cos_contract(double %a) {
7773
; CHECK-LABEL: define double @fmul_tan_cos_contract(
7874
; CHECK-SAME: double [[A:%.*]]) {
79-
; CHECK-NEXT: [[TAN:%.*]] = call contract double @llvm.tan.f64(double [[A]])
80-
; CHECK-NEXT: [[COS:%.*]] = call contract double @llvm.cos.f64(double [[A]])
81-
; CHECK-NEXT: [[RES:%.*]] = fmul contract double [[TAN]], [[COS]]
75+
; CHECK-NEXT: [[RES:%.*]] = call contract double @llvm.sin.f64(double [[A]])
8276
; CHECK-NEXT: ret double [[RES]]
8377
;
8478
%tan = call contract double @llvm.tan.f64(double %a)
@@ -90,9 +84,7 @@ define double @fmul_tan_cos_contract(double %a) {
9084
define float @fmul_tanf_cosf_contract(float %a) {
9185
; CHECK-LABEL: define float @fmul_tanf_cosf_contract(
9286
; CHECK-SAME: float [[A:%.*]]) {
93-
; CHECK-NEXT: [[TAN:%.*]] = call contract float @llvm.tan.f32(float [[A]])
94-
; CHECK-NEXT: [[COS:%.*]] = call contract float @llvm.cos.f32(float [[A]])
95-
; CHECK-NEXT: [[RES:%.*]] = fmul contract float [[TAN]], [[COS]]
87+
; CHECK-NEXT: [[RES:%.*]] = call contract float @llvm.sin.f32(float [[A]])
9688
; CHECK-NEXT: ret float [[RES]]
9789
;
9890
%tan = call contract float @llvm.tan.f32(float %a)
@@ -104,9 +96,7 @@ define float @fmul_tanf_cosf_contract(float %a) {
10496
define fp128 @fmul_tanfp128_cosfp128_contract(fp128 %a) {
10597
; CHECK-LABEL: define fp128 @fmul_tanfp128_cosfp128_contract(
10698
; CHECK-SAME: fp128 [[A:%.*]]) {
107-
; CHECK-NEXT: [[TAN:%.*]] = call contract fp128 @llvm.tan.f128(fp128 [[A]])
108-
; CHECK-NEXT: [[COS:%.*]] = call contract fp128 @llvm.cos.f128(fp128 [[A]])
109-
; CHECK-NEXT: [[RES:%.*]] = fmul contract fp128 [[TAN]], [[COS]]
99+
; CHECK-NEXT: [[RES:%.*]] = call contract fp128 @llvm.sin.f128(fp128 [[A]])
110100
; CHECK-NEXT: ret fp128 [[RES]]
111101
;
112102
%tan = call contract fp128 @llvm.tan.fp128(fp128 %a)
@@ -119,9 +109,7 @@ define fp128 @fmul_tanfp128_cosfp128_contract(fp128 %a) {
119109
define double @commutativity_cos_tan(double %a) {
120110
; CHECK-LABEL: define double @commutativity_cos_tan(
121111
; CHECK-SAME: double [[A:%.*]]) {
122-
; CHECK-NEXT: [[COS:%.*]] = call contract double @llvm.cos.f64(double [[A]])
123-
; CHECK-NEXT: [[TAN:%.*]] = call contract double @llvm.tan.f64(double [[A]])
124-
; CHECK-NEXT: [[RES:%.*]] = fmul contract double [[COS]], [[TAN]]
112+
; CHECK-NEXT: [[RES:%.*]] = call contract double @llvm.sin.f64(double [[A]])
125113
; CHECK-NEXT: ret double [[RES]]
126114
;
127115
%cos = call contract double @llvm.cos.f64(double %a)
@@ -149,9 +137,7 @@ define double @tan_cos_value_mismatch(double %a, double %b) {
149137
define <2 x double> @fmul_tan_cos_vector(<2 x double> %a) {
150138
; CHECK-LABEL: define <2 x double> @fmul_tan_cos_vector(
151139
; CHECK-SAME: <2 x double> [[A:%.*]]) {
152-
; CHECK-NEXT: [[TAN:%.*]] = call contract <2 x double> @llvm.tan.v2f64(<2 x double> [[A]])
153-
; CHECK-NEXT: [[COS:%.*]] = call contract <2 x double> @llvm.cos.v2f64(<2 x double> [[A]])
154-
; CHECK-NEXT: [[RES:%.*]] = fmul contract <2 x double> [[TAN]], [[COS]]
140+
; CHECK-NEXT: [[RES:%.*]] = call contract <2 x double> @llvm.sin.v2f64(<2 x double> [[A]])
155141
; CHECK-NEXT: ret <2 x double> [[RES]]
156142
;
157143
%tan = call contract <2 x double> @llvm.tan.v2f64(<2 x double> %a)
@@ -164,9 +150,7 @@ define <2 x double> @fmul_tan_cos_vector(<2 x double> %a) {
164150
define double @fmul_tan_cos_nnan_preservation(double %a) {
165151
; CHECK-LABEL: define double @fmul_tan_cos_nnan_preservation(
166152
; CHECK-SAME: double [[A:%.*]]) {
167-
; CHECK-NEXT: [[TAN:%.*]] = call contract double @llvm.tan.f64(double [[A]])
168-
; CHECK-NEXT: [[COS:%.*]] = call contract double @llvm.cos.f64(double [[A]])
169-
; CHECK-NEXT: [[RES:%.*]] = fmul nnan contract double [[TAN]], [[COS]]
153+
; CHECK-NEXT: [[RES:%.*]] = call nnan contract double @llvm.sin.f64(double [[A]])
170154
; CHECK-NEXT: ret double [[RES]]
171155
;
172156
%tan = call contract double @llvm.tan.f64(double %a)
@@ -179,9 +163,7 @@ define double @fmul_tan_cos_nnan_preservation(double %a) {
179163
define double @fmul_tan_cos_fpmath_metadata_preservation(double %a) {
180164
; CHECK-LABEL: define double @fmul_tan_cos_fpmath_metadata_preservation(
181165
; CHECK-SAME: double [[A:%.*]]) {
182-
; CHECK-NEXT: [[TAN:%.*]] = call contract double @llvm.tan.f64(double [[A]])
183-
; CHECK-NEXT: [[COS:%.*]] = call contract double @llvm.cos.f64(double [[A]])
184-
; CHECK-NEXT: [[RES:%.*]] = fmul contract double [[TAN]], [[COS]], !fpmath [[META0:![0-9]+]]
166+
; CHECK-NEXT: [[RES:%.*]] = call contract double @llvm.sin.f64(double [[A]]), !fpmath [[META0:![0-9]+]]
185167
; CHECK-NEXT: ret double [[RES]]
186168
;
187169
%tan = call contract double @llvm.tan.f64(double %a)

0 commit comments

Comments
 (0)