Skip to content

Commit b15a0a3

Browse files
authored
[clang] Add tanf16 builtin and support for tan constrained intrinsic (#93314)
In LLVM, the `llvm.experimental.constrained.cos` and `llvm.experimental.constrained.sin` intrinsics are used for performing cosine and sine calculations with additional constraints on floating-point operations. This behavior is expected for all floating-point math intrinsics. This change adds these constraints for the `tan` intrinsic. - `Builtins.td` - replace TanF128 with F16F128MathTemplate - `CGBuiltin.cpp` - map existing tan builtins to `tan` and `constrained_tan` intrinsic - `ConstrainedOps.def` map tan and constrained_tan to an ISDOpcode. - `ISDOpcodes.h` - define tan and strict tan opcodes resolves #91421
1 parent cd5045a commit b15a0a3

File tree

12 files changed

+103
-13
lines changed

12 files changed

+103
-13
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,11 +482,11 @@ def SqrtF16F128 : Builtin, F16F128MathTemplate {
482482
let Prototype = "T(T)";
483483
}
484484

485-
def TanF128 : Builtin {
486-
let Spellings = ["__builtin_tanf128"];
485+
def TanF16F128 : Builtin, F16F128MathTemplate {
486+
let Spellings = ["__builtin_tan"];
487487
let Attributes = [FunctionWithBuiltinPrefix, NoThrow,
488488
ConstIgnoringErrnoAndExceptions];
489-
let Prototype = "__float128(__float128)";
489+
let Prototype = "T(T)";
490490
}
491491

492492
def TanhF128 : Builtin {

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2923,6 +2923,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
29232923
SetSqrtFPAccuracy(Call);
29242924
return RValue::get(Call);
29252925
}
2926+
2927+
case Builtin::BItan:
2928+
case Builtin::BItanf:
2929+
case Builtin::BItanl:
2930+
case Builtin::BI__builtin_tan:
2931+
case Builtin::BI__builtin_tanf:
2932+
case Builtin::BI__builtin_tanf16:
2933+
case Builtin::BI__builtin_tanl:
2934+
case Builtin::BI__builtin_tanf128:
2935+
return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
2936+
*this, E, Intrinsic::tan, Intrinsic::experimental_constrained_tan));
2937+
29262938
case Builtin::BItrunc:
29272939
case Builtin::BItruncf:
29282940
case Builtin::BItruncl:

clang/test/CodeGen/X86/math-builtins.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,10 @@ __builtin_sqrt(f); __builtin_sqrtf(f); __builtin_sqrtl(f); __builtin_
674674

675675
__builtin_tan(f); __builtin_tanf(f); __builtin_tanl(f); __builtin_tanf128(f);
676676

677-
// NO__ERRNO: declare double @tan(double noundef) [[READNONE]]
678-
// NO__ERRNO: declare float @tanf(float noundef) [[READNONE]]
679-
// NO__ERRNO: declare x86_fp80 @tanl(x86_fp80 noundef) [[READNONE]]
680-
// NO__ERRNO: declare fp128 @tanf128(fp128 noundef) [[READNONE]]
677+
// NO__ERRNO: declare double @llvm.tan.f64(double) [[READNONE_INTRINSIC]]
678+
// NO__ERRNO: declare float @llvm.tan.f32(float) [[READNONE_INTRINSIC]]
679+
// NO__ERRNO: declare x86_fp80 @llvm.tan.f80(x86_fp80) [[READNONE_INTRINSIC]]
680+
// NO__ERRNO: declare fp128 @llvm.tan.f128(fp128) [[READNONE_INTRINSIC]]
681681
// HAS_ERRNO: declare double @tan(double noundef) [[NOT_READNONE]]
682682
// HAS_ERRNO: declare float @tanf(float noundef) [[NOT_READNONE]]
683683
// HAS_ERRNO: declare x86_fp80 @tanl(x86_fp80 noundef) [[NOT_READNONE]]

clang/test/CodeGen/constrained-math-builtins.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c, _
183183
// CHECK: call x86_fp80 @llvm.experimental.constrained.sqrt.f80(x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
184184
// CHECK: call fp128 @llvm.experimental.constrained.sqrt.f128(fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
185185

186+
__builtin_tan(f); __builtin_tanf(f); __builtin_tanl(f); __builtin_tanf128(f);
187+
188+
// CHECK: call double @llvm.experimental.constrained.tan.f64(double %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
189+
// CHECK: call float @llvm.experimental.constrained.tan.f32(float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
190+
// CHECK: call x86_fp80 @llvm.experimental.constrained.tan.f80(x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
191+
// CHECK: call fp128 @llvm.experimental.constrained.tan.f128(fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
192+
193+
186194
__builtin_trunc(f); __builtin_truncf(f); __builtin_truncl(f); __builtin_truncf128(f);
187195

188196
// CHECK: call double @llvm.experimental.constrained.trunc.f64(double %{{.*}}, metadata !"fpexcept.strict")
@@ -315,6 +323,11 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c, _
315323
// CHECK: declare x86_fp80 @llvm.experimental.constrained.sqrt.f80(x86_fp80, metadata, metadata)
316324
// CHECK: declare fp128 @llvm.experimental.constrained.sqrt.f128(fp128, metadata, metadata)
317325

326+
// CHECK: declare double @llvm.experimental.constrained.tan.f64(double, metadata, metadata)
327+
// CHECK: declare float @llvm.experimental.constrained.tan.f32(float, metadata, metadata)
328+
// CHECK: declare x86_fp80 @llvm.experimental.constrained.tan.f80(x86_fp80, metadata, metadata)
329+
// CHECK: declare fp128 @llvm.experimental.constrained.tan.f128(fp128, metadata, metadata)
330+
318331
// CHECK: declare double @llvm.experimental.constrained.trunc.f64(double, metadata)
319332
// CHECK: declare float @llvm.experimental.constrained.trunc.f32(float, metadata)
320333
// CHECK: declare x86_fp80 @llvm.experimental.constrained.trunc.f80(x86_fp80, metadata)

clang/test/CodeGen/math-libcalls.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,15 +662,15 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
662662

663663
tan(f); tanf(f); tanl(f);
664664

665-
// NO__ERRNO: declare double @tan(double noundef) [[READNONE]]
666-
// NO__ERRNO: declare float @tanf(float noundef) [[READNONE]]
667-
// NO__ERRNO: declare x86_fp80 @tanl(x86_fp80 noundef) [[READNONE]]
665+
// NO__ERRNO: declare double @llvm.tan.f64(double) [[READNONE_INTRINSIC]]
666+
// NO__ERRNO: declare float @llvm.tan.f32(float) [[READNONE_INTRINSIC]]
667+
// NO__ERRNO: declare x86_fp80 @llvm.tan.f80(x86_fp80) [[READNONE_INTRINSIC]]
668668
// HAS_ERRNO: declare double @tan(double noundef) [[NOT_READNONE]]
669669
// HAS_ERRNO: declare float @tanf(float noundef) [[NOT_READNONE]]
670670
// HAS_ERRNO: declare x86_fp80 @tanl(x86_fp80 noundef) [[NOT_READNONE]]
671-
// HAS_MAYTRAP: declare double @tan(double noundef) [[NOT_READNONE]]
672-
// HAS_MAYTRAP: declare float @tanf(float noundef) [[NOT_READNONE]]
673-
// HAS_MAYTRAP: declare x86_fp80 @tanl(x86_fp80 noundef) [[NOT_READNONE]]
671+
// HAS_MAYTRAP: declare double @llvm.experimental.constrained.tan.f64(
672+
// HAS_MAYTRAP: declare float @llvm.experimental.constrained.tan.f32(
673+
// HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.tan.f80(
674674

675675
tanh(f); tanhf(f); tanhl(f);
676676

clang/test/CodeGenOpenCL/builtins-f16.cl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ void test_half_builtins(half h0, half h1, half h2, int i0) {
6666
// CHECK: call half @llvm.sqrt.f16(half %h0)
6767
res = __builtin_sqrtf16(h0);
6868

69+
// CHECK: call half @llvm.tan.f16(half %h0)
70+
res = __builtin_tanf16(h0);
71+
6972
// CHECK: call half @llvm.trunc.f16(half %h0)
7073
res = __builtin_truncf16(h0);
7174

llvm/docs/LangRef.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26229,6 +26229,42 @@ same values as the libm ``cos`` functions would, and handles error
2622926229
conditions in the same way.
2623026230

2623126231

26232+
'``llvm.experimental.constrained.tan``' Intrinsic
26233+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26234+
26235+
Syntax:
26236+
"""""""
26237+
26238+
::
26239+
26240+
declare <type>
26241+
@llvm.experimental.constrained.tan(<type> <op1>,
26242+
metadata <rounding mode>,
26243+
metadata <exception behavior>)
26244+
26245+
Overview:
26246+
"""""""""
26247+
26248+
The '``llvm.experimental.constrained.tan``' intrinsic returns the tangent of the
26249+
first operand.
26250+
26251+
Arguments:
26252+
""""""""""
26253+
26254+
The first argument and the return type are floating-point numbers of the same
26255+
type.
26256+
26257+
The second and third arguments specify the rounding mode and exception
26258+
behavior as described above.
26259+
26260+
Semantics:
26261+
""""""""""
26262+
26263+
This function returns the tangent of the specified operand, returning the
26264+
same values as the libm ``tan`` functions would, and handles error
26265+
conditions in the same way.
26266+
26267+
2623226268
'``llvm.experimental.constrained.exp``' Intrinsic
2623326269
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2623426270

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ enum NodeType {
415415
STRICT_FLDEXP,
416416
STRICT_FSIN,
417417
STRICT_FCOS,
418+
STRICT_FTAN,
418419
STRICT_FEXP,
419420
STRICT_FEXP2,
420421
STRICT_FLOG,
@@ -934,6 +935,7 @@ enum NodeType {
934935
FCBRT,
935936
FSIN,
936937
FCOS,
938+
FTAN,
937939
FPOW,
938940
FPOWI,
939941
/// FLDEXP - ldexp, inspired by libm (op0 * 2**op1).

llvm/include/llvm/IR/ConstrainedOps.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ DAG_FUNCTION(round, 1, 0, experimental_constrained_round, FROUND)
9595
DAG_FUNCTION(roundeven, 1, 0, experimental_constrained_roundeven, FROUNDEVEN)
9696
DAG_FUNCTION(sin, 1, 1, experimental_constrained_sin, FSIN)
9797
DAG_FUNCTION(sqrt, 1, 1, experimental_constrained_sqrt, FSQRT)
98+
DAG_FUNCTION(tan, 1, 1, experimental_constrained_tan, FTAN)
9899
DAG_FUNCTION(trunc, 1, 0, experimental_constrained_trunc, FTRUNC)
99100

100101
// This is definition for fmuladd intrinsic function, that is converted into

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,10 @@ let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn, IntrStrictFP] in
12181218
[ LLVMMatchType<0>,
12191219
llvm_metadata_ty,
12201220
llvm_metadata_ty ]>;
1221+
def int_experimental_constrained_tan : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1222+
[ LLVMMatchType<0>,
1223+
llvm_metadata_ty,
1224+
llvm_metadata_ty ]>;
12211225
def int_experimental_constrained_pow : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
12221226
[ LLVMMatchType<0>,
12231227
LLVMMatchType<0>,

llvm/test/Assembler/fp-intrinsics-attr.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ define void @func(double %a, double %b, double %c, i32 %i) strictfp {
8585
metadata !"round.dynamic",
8686
metadata !"fpexcept.strict")
8787

88+
%tan = call double @llvm.experimental.constrained.tan.f64(
89+
double %a,
90+
metadata !"round.dynamic",
91+
metadata !"fpexcept.strict")
92+
8893
%pow = call double @llvm.experimental.constrained.pow.f64(
8994
double %a, double %b,
9095
metadata !"round.dynamic",
@@ -244,6 +249,9 @@ declare double @llvm.experimental.constrained.sin.f64(double, metadata, metadata
244249
declare double @llvm.experimental.constrained.cos.f64(double, metadata, metadata)
245250
; CHECK: @llvm.experimental.constrained.cos.f64({{.*}}) #[[ATTR1]]
246251

252+
declare double @llvm.experimental.constrained.tan.f64(double, metadata, metadata)
253+
; CHECK: @llvm.experimental.constrained.tan.f64({{.*}}) #[[ATTR1]]
254+
247255
declare double @llvm.experimental.constrained.pow.f64(double, double, metadata, metadata)
248256
; CHECK: @llvm.experimental.constrained.pow.f64({{.*}}) #[[ATTR1]]
249257

llvm/test/Feature/fp-intrinsics.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,17 @@ entry:
151151
ret double %result
152152
}
153153

154+
; Verify that tan(42.0) isn't simplified when the rounding mode is unknown.
155+
; CHECK-LABEL: ftan
156+
; CHECK: call double @llvm.experimental.constrained.tan
157+
define double @ftan() #0 {
158+
entry:
159+
%result = call double @llvm.experimental.constrained.tan.f64(double 42.0,
160+
metadata !"round.dynamic",
161+
metadata !"fpexcept.strict") #0
162+
ret double %result
163+
}
164+
154165
; Verify that exp(42.0) isn't simplified when the rounding mode is unknown.
155166
; CHECK-LABEL: f10
156167
; CHECK: call double @llvm.experimental.constrained.exp

0 commit comments

Comments
 (0)