Skip to content

Commit 6fde4bc

Browse files
committed
Create llvm dot intrinsic
Per https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294 `dot` should be an LLVM intrinsic. This adds the llvm intrinsics and updates HLSL builtin codegen to emit them. Removed some stale comments that gave the obsolete impression that type conversions should be expected to match overloads. With dot moving into an LLVM intrinsic, the lowering to dx-specific operations doesn't take place until DXIL intrinsic expansion. This moves the introduction of arity-specific DX opcodes to DXIL intrinsic expansion. Part of #88056
1 parent 3c3df1b commit 6fde4bc

File tree

5 files changed

+159
-130
lines changed

5 files changed

+159
-130
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18470,22 +18470,14 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments,
1847018470
return Arg;
1847118471
}
1847218472

18473-
Intrinsic::ID getDotProductIntrinsic(QualType QT, int elementCount) {
18474-
if (QT->hasFloatingRepresentation()) {
18475-
switch (elementCount) {
18476-
case 2:
18477-
return Intrinsic::dx_dot2;
18478-
case 3:
18479-
return Intrinsic::dx_dot3;
18480-
case 4:
18481-
return Intrinsic::dx_dot4;
18482-
}
18483-
}
18484-
if (QT->hasSignedIntegerRepresentation())
18485-
return Intrinsic::dx_sdot;
18486-
18487-
assert(QT->hasUnsignedIntegerRepresentation());
18488-
return Intrinsic::dx_udot;
18473+
// Return dot product intrinsic that corresponds to the QT scalar type
18474+
Intrinsic::ID getDotProductIntrinsic(QualType QT) {
18475+
if (QT->isFloatingType())
18476+
return Intrinsic::fdot;
18477+
if (QT->isSignedIntegerType())
18478+
return Intrinsic::sdot;
18479+
assert(QT->isUnsignedIntegerType());
18480+
return Intrinsic::udot;
1848918481
}
1849018482

1849118483
Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
@@ -18528,37 +18520,38 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1852818520
Value *Op1 = EmitScalarExpr(E->getArg(1));
1852918521
llvm::Type *T0 = Op0->getType();
1853018522
llvm::Type *T1 = Op1->getType();
18523+
18524+
// If the arguments are scalars, just emit a multiply
1853118525
if (!T0->isVectorTy() && !T1->isVectorTy()) {
1853218526
if (T0->isFloatingPointTy())
18533-
return Builder.CreateFMul(Op0, Op1, "dx.dot");
18527+
return Builder.CreateFMul(Op0, Op1, "dot");
1853418528

1853518529
if (T0->isIntegerTy())
18536-
return Builder.CreateMul(Op0, Op1, "dx.dot");
18530+
return Builder.CreateMul(Op0, Op1, "dot");
1853718531

18538-
// Bools should have been promoted
1853918532
llvm_unreachable(
1854018533
"Scalar dot product is only supported on ints and floats.");
1854118534
}
18535+
// For vectors, validate types and emit the appropriate intrinsic
18536+
1854218537
// A VectorSplat should have happened
1854318538
assert(T0->isVectorTy() && T1->isVectorTy() &&
1854418539
"Dot product of vector and scalar is not supported.");
1854518540

18546-
// A vector sext or sitofp should have happened
18547-
assert(T0->getScalarType() == T1->getScalarType() &&
18548-
"Dot product of vectors need the same element types.");
18549-
1855018541
auto *VecTy0 = E->getArg(0)->getType()->getAs<VectorType>();
1855118542
[[maybe_unused]] auto *VecTy1 =
1855218543
E->getArg(1)->getType()->getAs<VectorType>();
18553-
// A HLSLVectorTruncation should have happend
18544+
18545+
assert(VecTy0->getElementType() == VecTy1->getElementType() &&
18546+
"Dot product of vectors need the same element types.");
18547+
1855418548
assert(VecTy0->getNumElements() == VecTy1->getNumElements() &&
1855518549
"Dot product requires vectors to be of the same size.");
1855618550

1855718551
return Builder.CreateIntrinsic(
1855818552
/*ReturnType=*/T0->getScalarType(),
18559-
getDotProductIntrinsic(E->getArg(0)->getType(),
18560-
VecTy0->getNumElements()),
18561-
ArrayRef<Value *>{Op0, Op1}, nullptr, "dx.dot");
18553+
getDotProductIntrinsic(VecTy0->getElementType()),
18554+
ArrayRef<Value *>{Op0, Op1}, nullptr, "dot");
1856218555
} break;
1856318556
case Builtin::BI__builtin_hlsl_lerp: {
1856418557
Value *X = EmitScalarExpr(E->getArg(0));

clang/test/CodeGenHLSL/builtins/dot-builtin.hlsl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
// CHECK-LABEL: builtin_bool_to_float_type_promotion
44
// CHECK: %conv1 = uitofp i1 %loadedv to double
5-
// CHECK: %dx.dot = fmul double %conv, %conv1
6-
// CHECK: %conv2 = fptrunc double %dx.dot to float
5+
// CHECK: %dot = fmul double %conv, %conv1
6+
// CHECK: %conv2 = fptrunc double %dot to float
77
// CHECK: ret float %conv2
88
float builtin_bool_to_float_type_promotion ( float p0, bool p1 ) {
99
return __builtin_hlsl_dot ( p0, p1 );
@@ -12,8 +12,8 @@ float builtin_bool_to_float_type_promotion ( float p0, bool p1 ) {
1212
// CHECK-LABEL: builtin_bool_to_float_arg1_type_promotion
1313
// CHECK: %conv = uitofp i1 %loadedv to double
1414
// CHECK: %conv1 = fpext float %1 to double
15-
// CHECK: %dx.dot = fmul double %conv, %conv1
16-
// CHECK: %conv2 = fptrunc double %dx.dot to float
15+
// CHECK: %dot = fmul double %conv, %conv1
16+
// CHECK: %conv2 = fptrunc double %dot to float
1717
// CHECK: ret float %conv2
1818
float builtin_bool_to_float_arg1_type_promotion ( bool p0, float p1 ) {
1919
return __builtin_hlsl_dot ( p0, p1 );
@@ -22,8 +22,8 @@ float builtin_bool_to_float_arg1_type_promotion ( bool p0, float p1 ) {
2222
// CHECK-LABEL: builtin_dot_int_to_float_promotion
2323
// CHECK: %conv = fpext float %0 to double
2424
// CHECK: %conv1 = sitofp i32 %1 to double
25-
// CHECK: dx.dot = fmul double %conv, %conv1
26-
// CHECK: %conv2 = fptrunc double %dx.dot to float
25+
// CHECK: dot = fmul double %conv, %conv1
26+
// CHECK: %conv2 = fptrunc double %dot to float
2727
// CHECK: ret float %conv2
2828
float builtin_dot_int_to_float_promotion ( float p0, int p1 ) {
2929
return __builtin_hlsl_dot ( p0, p1 );

clang/test/CodeGenHLSL/builtins/dot.hlsl

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -7,155 +7,155 @@
77
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
88

99
#ifdef __HLSL_ENABLE_16_BIT
10-
// NATIVE_HALF: %dx.dot = mul i16 %0, %1
11-
// NATIVE_HALF: ret i16 %dx.dot
10+
// NATIVE_HALF: %dot = mul i16 %0, %1
11+
// NATIVE_HALF: ret i16 %dot
1212
int16_t test_dot_short(int16_t p0, int16_t p1) { return dot(p0, p1); }
1313

14-
// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.sdot.v2i16(<2 x i16> %0, <2 x i16> %1)
15-
// NATIVE_HALF: ret i16 %dx.dot
14+
// NATIVE_HALF: %dot = call i16 @llvm.sdot.v2i16(<2 x i16> %0, <2 x i16> %1)
15+
// NATIVE_HALF: ret i16 %dot
1616
int16_t test_dot_short2(int16_t2 p0, int16_t2 p1) { return dot(p0, p1); }
1717

18-
// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.sdot.v3i16(<3 x i16> %0, <3 x i16> %1)
19-
// NATIVE_HALF: ret i16 %dx.dot
18+
// NATIVE_HALF: %dot = call i16 @llvm.sdot.v3i16(<3 x i16> %0, <3 x i16> %1)
19+
// NATIVE_HALF: ret i16 %dot
2020
int16_t test_dot_short3(int16_t3 p0, int16_t3 p1) { return dot(p0, p1); }
2121

22-
// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.sdot.v4i16(<4 x i16> %0, <4 x i16> %1)
23-
// NATIVE_HALF: ret i16 %dx.dot
22+
// NATIVE_HALF: %dot = call i16 @llvm.sdot.v4i16(<4 x i16> %0, <4 x i16> %1)
23+
// NATIVE_HALF: ret i16 %dot
2424
int16_t test_dot_short4(int16_t4 p0, int16_t4 p1) { return dot(p0, p1); }
2525

26-
// NATIVE_HALF: %dx.dot = mul i16 %0, %1
27-
// NATIVE_HALF: ret i16 %dx.dot
26+
// NATIVE_HALF: %dot = mul i16 %0, %1
27+
// NATIVE_HALF: ret i16 %dot
2828
uint16_t test_dot_ushort(uint16_t p0, uint16_t p1) { return dot(p0, p1); }
2929

30-
// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.udot.v2i16(<2 x i16> %0, <2 x i16> %1)
31-
// NATIVE_HALF: ret i16 %dx.dot
30+
// NATIVE_HALF: %dot = call i16 @llvm.udot.v2i16(<2 x i16> %0, <2 x i16> %1)
31+
// NATIVE_HALF: ret i16 %dot
3232
uint16_t test_dot_ushort2(uint16_t2 p0, uint16_t2 p1) { return dot(p0, p1); }
3333

34-
// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.udot.v3i16(<3 x i16> %0, <3 x i16> %1)
35-
// NATIVE_HALF: ret i16 %dx.dot
34+
// NATIVE_HALF: %dot = call i16 @llvm.udot.v3i16(<3 x i16> %0, <3 x i16> %1)
35+
// NATIVE_HALF: ret i16 %dot
3636
uint16_t test_dot_ushort3(uint16_t3 p0, uint16_t3 p1) { return dot(p0, p1); }
3737

38-
// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.udot.v4i16(<4 x i16> %0, <4 x i16> %1)
39-
// NATIVE_HALF: ret i16 %dx.dot
38+
// NATIVE_HALF: %dot = call i16 @llvm.udot.v4i16(<4 x i16> %0, <4 x i16> %1)
39+
// NATIVE_HALF: ret i16 %dot
4040
uint16_t test_dot_ushort4(uint16_t4 p0, uint16_t4 p1) { return dot(p0, p1); }
4141
#endif
4242

43-
// CHECK: %dx.dot = mul i32 %0, %1
44-
// CHECK: ret i32 %dx.dot
43+
// CHECK: %dot = mul i32 %0, %1
44+
// CHECK: ret i32 %dot
4545
int test_dot_int(int p0, int p1) { return dot(p0, p1); }
4646

47-
// CHECK: %dx.dot = call i32 @llvm.dx.sdot.v2i32(<2 x i32> %0, <2 x i32> %1)
48-
// CHECK: ret i32 %dx.dot
47+
// CHECK: %dot = call i32 @llvm.sdot.v2i32(<2 x i32> %0, <2 x i32> %1)
48+
// CHECK: ret i32 %dot
4949
int test_dot_int2(int2 p0, int2 p1) { return dot(p0, p1); }
5050

51-
// CHECK: %dx.dot = call i32 @llvm.dx.sdot.v3i32(<3 x i32> %0, <3 x i32> %1)
52-
// CHECK: ret i32 %dx.dot
51+
// CHECK: %dot = call i32 @llvm.sdot.v3i32(<3 x i32> %0, <3 x i32> %1)
52+
// CHECK: ret i32 %dot
5353
int test_dot_int3(int3 p0, int3 p1) { return dot(p0, p1); }
5454

55-
// CHECK: %dx.dot = call i32 @llvm.dx.sdot.v4i32(<4 x i32> %0, <4 x i32> %1)
56-
// CHECK: ret i32 %dx.dot
55+
// CHECK: %dot = call i32 @llvm.sdot.v4i32(<4 x i32> %0, <4 x i32> %1)
56+
// CHECK: ret i32 %dot
5757
int test_dot_int4(int4 p0, int4 p1) { return dot(p0, p1); }
5858

59-
// CHECK: %dx.dot = mul i32 %0, %1
60-
// CHECK: ret i32 %dx.dot
59+
// CHECK: %dot = mul i32 %0, %1
60+
// CHECK: ret i32 %dot
6161
uint test_dot_uint(uint p0, uint p1) { return dot(p0, p1); }
6262

63-
// CHECK: %dx.dot = call i32 @llvm.dx.udot.v2i32(<2 x i32> %0, <2 x i32> %1)
64-
// CHECK: ret i32 %dx.dot
63+
// CHECK: %dot = call i32 @llvm.udot.v2i32(<2 x i32> %0, <2 x i32> %1)
64+
// CHECK: ret i32 %dot
6565
uint test_dot_uint2(uint2 p0, uint2 p1) { return dot(p0, p1); }
6666

67-
// CHECK: %dx.dot = call i32 @llvm.dx.udot.v3i32(<3 x i32> %0, <3 x i32> %1)
68-
// CHECK: ret i32 %dx.dot
67+
// CHECK: %dot = call i32 @llvm.udot.v3i32(<3 x i32> %0, <3 x i32> %1)
68+
// CHECK: ret i32 %dot
6969
uint test_dot_uint3(uint3 p0, uint3 p1) { return dot(p0, p1); }
7070

71-
// CHECK: %dx.dot = call i32 @llvm.dx.udot.v4i32(<4 x i32> %0, <4 x i32> %1)
72-
// CHECK: ret i32 %dx.dot
71+
// CHECK: %dot = call i32 @llvm.udot.v4i32(<4 x i32> %0, <4 x i32> %1)
72+
// CHECK: ret i32 %dot
7373
uint test_dot_uint4(uint4 p0, uint4 p1) { return dot(p0, p1); }
7474

75-
// CHECK: %dx.dot = mul i64 %0, %1
76-
// CHECK: ret i64 %dx.dot
75+
// CHECK: %dot = mul i64 %0, %1
76+
// CHECK: ret i64 %dot
7777
int64_t test_dot_long(int64_t p0, int64_t p1) { return dot(p0, p1); }
7878

79-
// CHECK: %dx.dot = call i64 @llvm.dx.sdot.v2i64(<2 x i64> %0, <2 x i64> %1)
80-
// CHECK: ret i64 %dx.dot
79+
// CHECK: %dot = call i64 @llvm.sdot.v2i64(<2 x i64> %0, <2 x i64> %1)
80+
// CHECK: ret i64 %dot
8181
int64_t test_dot_long2(int64_t2 p0, int64_t2 p1) { return dot(p0, p1); }
8282

83-
// CHECK: %dx.dot = call i64 @llvm.dx.sdot.v3i64(<3 x i64> %0, <3 x i64> %1)
84-
// CHECK: ret i64 %dx.dot
83+
// CHECK: %dot = call i64 @llvm.sdot.v3i64(<3 x i64> %0, <3 x i64> %1)
84+
// CHECK: ret i64 %dot
8585
int64_t test_dot_long3(int64_t3 p0, int64_t3 p1) { return dot(p0, p1); }
8686

87-
// CHECK: %dx.dot = call i64 @llvm.dx.sdot.v4i64(<4 x i64> %0, <4 x i64> %1)
88-
// CHECK: ret i64 %dx.dot
87+
// CHECK: %dot = call i64 @llvm.sdot.v4i64(<4 x i64> %0, <4 x i64> %1)
88+
// CHECK: ret i64 %dot
8989
int64_t test_dot_long4(int64_t4 p0, int64_t4 p1) { return dot(p0, p1); }
9090

91-
// CHECK: %dx.dot = mul i64 %0, %1
92-
// CHECK: ret i64 %dx.dot
91+
// CHECK: %dot = mul i64 %0, %1
92+
// CHECK: ret i64 %dot
9393
uint64_t test_dot_ulong(uint64_t p0, uint64_t p1) { return dot(p0, p1); }
9494

95-
// CHECK: %dx.dot = call i64 @llvm.dx.udot.v2i64(<2 x i64> %0, <2 x i64> %1)
96-
// CHECK: ret i64 %dx.dot
95+
// CHECK: %dot = call i64 @llvm.udot.v2i64(<2 x i64> %0, <2 x i64> %1)
96+
// CHECK: ret i64 %dot
9797
uint64_t test_dot_ulong2(uint64_t2 p0, uint64_t2 p1) { return dot(p0, p1); }
9898

99-
// CHECK: %dx.dot = call i64 @llvm.dx.udot.v3i64(<3 x i64> %0, <3 x i64> %1)
100-
// CHECK: ret i64 %dx.dot
99+
// CHECK: %dot = call i64 @llvm.udot.v3i64(<3 x i64> %0, <3 x i64> %1)
100+
// CHECK: ret i64 %dot
101101
uint64_t test_dot_ulong3(uint64_t3 p0, uint64_t3 p1) { return dot(p0, p1); }
102102

103-
// CHECK: %dx.dot = call i64 @llvm.dx.udot.v4i64(<4 x i64> %0, <4 x i64> %1)
104-
// CHECK: ret i64 %dx.dot
103+
// CHECK: %dot = call i64 @llvm.udot.v4i64(<4 x i64> %0, <4 x i64> %1)
104+
// CHECK: ret i64 %dot
105105
uint64_t test_dot_ulong4(uint64_t4 p0, uint64_t4 p1) { return dot(p0, p1); }
106106

107-
// NATIVE_HALF: %dx.dot = fmul half %0, %1
108-
// NATIVE_HALF: ret half %dx.dot
109-
// NO_HALF: %dx.dot = fmul float %0, %1
110-
// NO_HALF: ret float %dx.dot
107+
// NATIVE_HALF: %dot = fmul half %0, %1
108+
// NATIVE_HALF: ret half %dot
109+
// NO_HALF: %dot = fmul float %0, %1
110+
// NO_HALF: ret float %dot
111111
half test_dot_half(half p0, half p1) { return dot(p0, p1); }
112112

113-
// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot2.v2f16(<2 x half> %0, <2 x half> %1)
114-
// NATIVE_HALF: ret half %dx.dot
115-
// NO_HALF: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %1)
116-
// NO_HALF: ret float %dx.dot
113+
// NATIVE_HALF: %dot = call half @llvm.fdot.v2f16(<2 x half> %0, <2 x half> %1)
114+
// NATIVE_HALF: ret half %dot
115+
// NO_HALF: %dot = call float @llvm.fdot.v2f32(<2 x float> %0, <2 x float> %1)
116+
// NO_HALF: ret float %dot
117117
half test_dot_half2(half2 p0, half2 p1) { return dot(p0, p1); }
118118

119-
// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot3.v3f16(<3 x half> %0, <3 x half> %1)
120-
// NATIVE_HALF: ret half %dx.dot
121-
// NO_HALF: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %1)
122-
// NO_HALF: ret float %dx.dot
119+
// NATIVE_HALF: %dot = call half @llvm.fdot.v3f16(<3 x half> %0, <3 x half> %1)
120+
// NATIVE_HALF: ret half %dot
121+
// NO_HALF: %dot = call float @llvm.fdot.v3f32(<3 x float> %0, <3 x float> %1)
122+
// NO_HALF: ret float %dot
123123
half test_dot_half3(half3 p0, half3 p1) { return dot(p0, p1); }
124124

125-
// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot4.v4f16(<4 x half> %0, <4 x half> %1)
126-
// NATIVE_HALF: ret half %dx.dot
127-
// NO_HALF: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %0, <4 x float> %1)
128-
// NO_HALF: ret float %dx.dot
125+
// NATIVE_HALF: %dot = call half @llvm.fdot.v4f16(<4 x half> %0, <4 x half> %1)
126+
// NATIVE_HALF: ret half %dot
127+
// NO_HALF: %dot = call float @llvm.fdot.v4f32(<4 x float> %0, <4 x float> %1)
128+
// NO_HALF: ret float %dot
129129
half test_dot_half4(half4 p0, half4 p1) { return dot(p0, p1); }
130130

131-
// CHECK: %dx.dot = fmul float %0, %1
132-
// CHECK: ret float %dx.dot
131+
// CHECK: %dot = fmul float %0, %1
132+
// CHECK: ret float %dot
133133
float test_dot_float(float p0, float p1) { return dot(p0, p1); }
134134

135-
// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %1)
136-
// CHECK: ret float %dx.dot
135+
// CHECK: %dot = call float @llvm.fdot.v2f32(<2 x float> %0, <2 x float> %1)
136+
// CHECK: ret float %dot
137137
float test_dot_float2(float2 p0, float2 p1) { return dot(p0, p1); }
138138

139-
// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %1)
140-
// CHECK: ret float %dx.dot
139+
// CHECK: %dot = call float @llvm.fdot.v3f32(<3 x float> %0, <3 x float> %1)
140+
// CHECK: ret float %dot
141141
float test_dot_float3(float3 p0, float3 p1) { return dot(p0, p1); }
142142

143-
// CHECK: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %0, <4 x float> %1)
144-
// CHECK: ret float %dx.dot
143+
// CHECK: %dot = call float @llvm.fdot.v4f32(<4 x float> %0, <4 x float> %1)
144+
// CHECK: ret float %dot
145145
float test_dot_float4(float4 p0, float4 p1) { return dot(p0, p1); }
146146

147-
// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %splat.splat, <2 x float> %1)
148-
// CHECK: ret float %dx.dot
147+
// CHECK: %dot = call float @llvm.fdot.v2f32(<2 x float> %splat.splat, <2 x float> %1)
148+
// CHECK: ret float %dot
149149
float test_dot_float2_splat(float p0, float2 p1) { return dot(p0, p1); }
150150

151-
// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %splat.splat, <3 x float> %1)
152-
// CHECK: ret float %dx.dot
151+
// CHECK: %dot = call float @llvm.fdot.v3f32(<3 x float> %splat.splat, <3 x float> %1)
152+
// CHECK: ret float %dot
153153
float test_dot_float3_splat(float p0, float3 p1) { return dot(p0, p1); }
154154

155-
// CHECK: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %splat.splat, <4 x float> %1)
156-
// CHECK: ret float %dx.dot
155+
// CHECK: %dot = call float @llvm.fdot.v4f32(<4 x float> %splat.splat, <4 x float> %1)
156+
// CHECK: ret float %dot
157157
float test_dot_float4_splat(float p0, float4 p1) { return dot(p0, p1); }
158158

159-
// CHECK: %dx.dot = fmul double %0, %1
160-
// CHECK: ret double %dx.dot
159+
// CHECK: %dot = fmul double %0, %1
160+
// CHECK: ret double %dot
161161
double test_dot_double(double p0, double p1) { return dot(p0, p1); }

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,15 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
10451045
def int_nearbyint : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10461046
def int_round : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
10471047
def int_roundeven : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
1048+
def int_udot : Intrinsic<[LLVMVectorElementType<0>],
1049+
[llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
1050+
[IntrNoMem, IntrWillReturn, Commutative] >;
1051+
def int_sdot : Intrinsic<[LLVMVectorElementType<0>],
1052+
[llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
1053+
[IntrNoMem, IntrWillReturn, Commutative] >;
1054+
def int_fdot : Intrinsic<[LLVMVectorElementType<0>],
1055+
[llvm_anyfloat_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>],
1056+
[IntrNoMem, IntrWillReturn, Commutative] >;
10481057

10491058
// Truncate a floating point number with a specific rounding mode
10501059
def int_fptrunc_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],

0 commit comments

Comments
 (0)