Skip to content

Commit 7ff9429

Browse files
authored
Merge branch 'llvm:main' into shape
2 parents 5cf4a38 + 2cd8edd commit 7ff9429

File tree

21 files changed

+308
-24
lines changed

21 files changed

+308
-24
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4891,6 +4891,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
48914891
let Prototype = "void(...)";
48924892
}
48934893

4894+
def HLSLDot2Add : LangBuiltin<"HLSL_LANG"> {
4895+
let Spellings = ["__builtin_hlsl_dot2add"];
4896+
let Attributes = [NoThrow, Const];
4897+
let Prototype = "float(_ExtVector<2, _Float16>, _ExtVector<2, _Float16>, float)";
4898+
}
4899+
48944900
def HLSLDot4AddI8Packed : LangBuiltin<"HLSL_LANG"> {
48954901
let Spellings = ["__builtin_hlsl_dot4add_i8packed"];
48964902
let Attributes = [NoThrow, Const];

clang/lib/CodeGen/CGHLSLBuiltins.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,19 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
380380
getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()),
381381
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.dot");
382382
}
383+
case Builtin::BI__builtin_hlsl_dot2add: {
384+
llvm::Triple::ArchType Arch = CGM.getTarget().getTriple().getArch();
385+
assert(Arch == llvm::Triple::dxil &&
386+
"Intrinsic dot2add is only allowed for dxil architecture");
387+
Value *A = EmitScalarExpr(E->getArg(0));
388+
Value *B = EmitScalarExpr(E->getArg(1));
389+
Value *C = EmitScalarExpr(E->getArg(2));
390+
391+
Intrinsic::ID ID = llvm ::Intrinsic::dx_dot2add;
392+
return Builder.CreateIntrinsic(
393+
/*ReturnType=*/C->getType(), ID, ArrayRef<Value *>{A, B, C}, nullptr,
394+
"dx.dot2add");
395+
}
383396
case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
384397
Value *A = EmitScalarExpr(E->getArg(0));
385398
Value *B = EmitScalarExpr(E->getArg(1));

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ distance_vec_impl(vector<T, N> X, vector<T, N> Y) {
4545
return length_vec_impl(X - Y);
4646
}
4747

48+
constexpr float dot2add_impl(half2 a, half2 b, float c) {
49+
#if defined(__DIRECTX__)
50+
return __builtin_hlsl_dot2add(a, b, c);
51+
#else
52+
return dot(a, b) + c;
53+
#endif
54+
}
55+
4856
template <typename T> constexpr T reflect_impl(T I, T N) {
4957
return I - 2 * N * I * N;
5058
}

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,21 @@ const inline float distance(__detail::HLSL_FIXED_VECTOR<float, N> X,
175175
return __detail::distance_vec_impl(X, Y);
176176
}
177177

178+
//===----------------------------------------------------------------------===//
179+
// dot2add builtins
180+
//===----------------------------------------------------------------------===//
181+
182+
/// \fn float dot2add(half2 A, half2 B, float C)
183+
/// \brief Dot product of 2 vector of type half and add a float scalar value.
184+
/// \param A The first input value to dot product.
185+
/// \param B The second input value to dot product.
186+
/// \param C The input value added to the dot product.
187+
188+
_HLSL_AVAILABILITY(shadermodel, 6.4)
189+
const inline float dot2add(half2 A, half2 B, float C) {
190+
return __detail::dot2add_impl(A, B, C);
191+
}
192+
178193
//===----------------------------------------------------------------------===//
179194
// fmod builtins
180195
//===----------------------------------------------------------------------===//
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
2+
// RUN: dxil-pc-shadermodel6.3-compute %s -emit-llvm -o - | \
3+
// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
4+
// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
5+
// RUN: spirv-pc-vulkan-compute %s -emit-llvm -o - | \
6+
// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
7+
8+
// Test basic lowering to runtime function call.
9+
10+
// CHECK-LABEL: define {{.*}}test_default_parameter_type
11+
float test_default_parameter_type(half2 p1, half2 p2, float p3) {
12+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
13+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
14+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
15+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
16+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
17+
// CHECK: ret float %[[RES]]
18+
return dot2add(p1, p2, p3);
19+
}
20+
21+
// CHECK-LABEL: define {{.*}}test_float_arg2_type
22+
float test_float_arg2_type(half2 p1, float2 p2, float p3) {
23+
// CHECK: %conv = fptrunc reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}} to <2 x half>
24+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
25+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
26+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
27+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
28+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
29+
// CHECK: ret float %[[RES]]
30+
return dot2add(p1, p2, p3);
31+
}
32+
33+
// CHECK-LABEL: define {{.*}}test_float_arg1_type
34+
float test_float_arg1_type(float2 p1, half2 p2, float p3) {
35+
// CHECK: %conv = fptrunc reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}} to <2 x half>
36+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
37+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
38+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
39+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
40+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
41+
// CHECK: ret float %[[RES]]
42+
return dot2add(p1, p2, p3);
43+
}
44+
45+
// CHECK-LABEL: define {{.*}}test_double_arg3_type
46+
float test_double_arg3_type(half2 p1, half2 p2, double p3) {
47+
// CHECK: %conv = fptrunc reassoc nnan ninf nsz arcp afn double %{{.*}} to float
48+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
49+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
50+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
51+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
52+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
53+
// CHECK: ret float %[[RES]]
54+
return dot2add(p1, p2, p3);
55+
}
56+
57+
// CHECK-LABEL: define {{.*}}test_float_arg1_arg2_type
58+
float test_float_arg1_arg2_type(float2 p1, float2 p2, float p3) {
59+
// CHECK: %conv = fptrunc reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}} to <2 x half>
60+
// CHECK: %conv1 = fptrunc reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}} to <2 x half>
61+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
62+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
63+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
64+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
65+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
66+
// CHECK: ret float %[[RES]]
67+
return dot2add(p1, p2, p3);
68+
}
69+
70+
// CHECK-LABEL: define {{.*}}test_double_arg1_arg2_type
71+
float test_double_arg1_arg2_type(double2 p1, double2 p2, float p3) {
72+
// CHECK: %conv = fptrunc reassoc nnan ninf nsz arcp afn <2 x double> %{{.*}} to <2 x half>
73+
// CHECK: %conv1 = fptrunc reassoc nnan ninf nsz arcp afn <2 x double> %{{.*}} to <2 x half>
74+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
75+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
76+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
77+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
78+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
79+
// CHECK: ret float %[[RES]]
80+
return dot2add(p1, p2, p3);
81+
}
82+
83+
// CHECK-LABEL: define {{.*}}test_int16_arg1_arg2_type
84+
float test_int16_arg1_arg2_type(int16_t2 p1, int16_t2 p2, float p3) {
85+
// CHECK: %conv = sitofp <2 x i16> %{{.*}} to <2 x half>
86+
// CHECK: %conv1 = sitofp <2 x i16> %{{.*}} to <2 x half>
87+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
88+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
89+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
90+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
91+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
92+
// CHECK: ret float %[[RES]]
93+
return dot2add(p1, p2, p3);
94+
}
95+
96+
// CHECK-LABEL: define {{.*}}test_int32_arg1_arg2_type
97+
float test_int32_arg1_arg2_type(int32_t2 p1, int32_t2 p2, float p3) {
98+
// CHECK: %conv = sitofp <2 x i32> %{{.*}} to <2 x half>
99+
// CHECK: %conv1 = sitofp <2 x i32> %{{.*}} to <2 x half>
100+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
101+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
102+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
103+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
104+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
105+
// CHECK: ret float %[[RES]]
106+
return dot2add(p1, p2, p3);
107+
}
108+
109+
// CHECK-LABEL: define {{.*}}test_int64_arg1_arg2_type
110+
float test_int64_arg1_arg2_type(int64_t2 p1, int64_t2 p2, float p3) {
111+
// CHECK: %conv = sitofp <2 x i64> %{{.*}} to <2 x half>
112+
// CHECK: %conv1 = sitofp <2 x i64> %{{.*}} to <2 x half>
113+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
114+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
115+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
116+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
117+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
118+
// CHECK: ret float %[[RES]]
119+
return dot2add(p1, p2, p3);
120+
}
121+
122+
// CHECK-LABEL: define {{.*}}test_bool_arg1_arg2_type
123+
float test_bool_arg1_arg2_type(bool2 p1, bool2 p2, float p3) {
124+
// CHECK: %loadedv = trunc <2 x i32> %{{.*}} to <2 x i1>
125+
// CHECK: %conv = uitofp <2 x i1> %loadedv to <2 x half>
126+
// CHECK: %loadedv1 = trunc <2 x i32> %{{.*}} to <2 x i1>
127+
// CHECK: %conv2 = uitofp <2 x i1> %loadedv1 to <2 x half>
128+
// CHECK-SPIRV: %[[MUL:.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.spv.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
129+
// CHECK-SPIRV: %[[CONV:.*]] = fpext reassoc nnan ninf nsz arcp afn half %[[MUL]] to float
130+
// CHECK-SPIRV: %[[C:.*]] = load float, ptr %c.addr.i, align 4
131+
// CHECK-SPIRV: %[[RES:.*]] = fadd reassoc nnan ninf nsz arcp afn float %[[CONV]], %[[C]]
132+
// CHECK-DXIL: %[[RES:.*]] = call {{.*}} float @llvm.dx.dot2add.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, float %{{.*}})
133+
// CHECK: ret float %[[RES]]
134+
return dot2add(p1, p2, p3);
135+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify
2+
3+
float test_too_few_arg() {
4+
return dot2add();
5+
// expected-error@-1 {{no matching function for call to 'dot2add'}}
6+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 3 arguments, but 0 were provided}}
7+
}
8+
9+
float test_too_many_arg(half2 p1, half2 p2, float p3) {
10+
return dot2add(p1, p2, p3, p1);
11+
// expected-error@-1 {{no matching function for call to 'dot2add'}}
12+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: requires 3 arguments, but 4 were provided}}
13+
}

flang-rt/lib/runtime/extensions.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,5 +272,8 @@ void FORTRAN_PROCEDURE_NAME(qsort)(int *array, int *len, int *isize,
272272
// PERROR(STRING)
273273
void RTNAME(Perror)(const char *str) { perror(str); }
274274

275+
// GNU extension function TIME()
276+
std::int64_t RTNAME(time)() { return time(nullptr); }
277+
275278
} // namespace Fortran::runtime
276279
} // extern "C"

flang/docs/Intrinsics.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,27 @@ end program rename_proc
10911091
This intrinsic is an alias for `CPU_TIME`: supporting both a subroutine and a
10921092
function form.
10931093

1094+
### Non-Standard Intrinsics: TIME
1095+
1096+
#### Description
1097+
`TIME()` returns the current time of the system as a INTEGER(8).
1098+
1099+
#### Usage and Info
1100+
1101+
- **Standard:** GNU extension
1102+
- **Class:** function
1103+
- **Syntax:** `RESULT = TIME()`
1104+
1105+
#### Example
1106+
```Fortran
1107+
PROGRAM example_time
1108+
print *, TIME()
1109+
print *, TIME()
1110+
call SLEEP(10)
1111+
print *, TIME()
1112+
END PROGRAM
1113+
```
1114+
10941115
### Non-Standard Intrinsics: UNLINK
10951116

10961117
#### Description

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ struct IntrinsicLibrary {
429429
mlir::ArrayRef<fir::ExtendedValue> args);
430430
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
431431
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
432+
mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
432433
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
433434
fir::ExtendedValue genTransfer(mlir::Type,
434435
llvm::ArrayRef<fir::ExtendedValue>);

flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ void genRandomSeed(fir::FirOpBuilder &, mlir::Location, mlir::Value size,
6565
void genRename(fir::FirOpBuilder &builder, mlir::Location loc,
6666
mlir::Value path1, mlir::Value path2, mlir::Value status);
6767

68+
/// generate time runtime call
69+
mlir::Value genTime(fir::FirOpBuilder &builder, mlir::Location loc);
70+
6871
/// generate runtime call to transfer intrinsic with no size argument
6972
void genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
7073
mlir::Value resultBox, mlir::Value sourceBox,

0 commit comments

Comments
 (0)