Skip to content

Commit ba1a09d

Browse files
authored
[AMDGPU] Allow overload of __builtin_amdgcn_mov_dpp8 (#113610)
The same handling as for __builtin_amdgcn_mov_dpp.
1 parent f0b9a0b commit ba1a09d

File tree

6 files changed

+133
-52
lines changed

6 files changed

+133
-52
lines changed

clang/include/clang/Basic/BuiltinsAMDGPU.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "dot11-insts")
282282
//===----------------------------------------------------------------------===//
283283
TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts")
284284
TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts")
285-
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts")
285+
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nct", "gfx10-insts")
286286
TARGET_BUILTIN(__builtin_amdgcn_s_ttracedata_imm, "vIs", "n", "gfx10-insts")
287287

288288
//===----------------------------------------------------------------------===//

clang/include/clang/Sema/SemaAMDGPU.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class SemaAMDGPU : public SemaBase {
2626

2727
bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
2828

29+
bool checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs,
30+
unsigned NumDataArgs);
31+
2932
/// Create an AMDGPUWavesPerEUAttr attribute.
3033
AMDGPUFlatWorkGroupSizeAttr *
3134
CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19115,8 +19115,6 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
1911519115
return emitBuiltinWithOneOverloadedType<2>(*this, E,
1911619116
Intrinsic::amdgcn_ds_swizzle);
1911719117
case AMDGPU::BI__builtin_amdgcn_mov_dpp8:
19118-
return emitBuiltinWithOneOverloadedType<2>(*this, E,
19119-
Intrinsic::amdgcn_mov_dpp8);
1912019118
case AMDGPU::BI__builtin_amdgcn_mov_dpp:
1912119119
case AMDGPU::BI__builtin_amdgcn_update_dpp: {
1912219120
llvm::SmallVector<llvm::Value *, 6> Args;
@@ -19130,14 +19128,20 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
1913019128
unsigned Size = DataTy->getPrimitiveSizeInBits();
1913119129
llvm::Type *IntTy =
1913219130
llvm::IntegerType::get(Builder.getContext(), std::max(Size, 32u));
19133-
Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, IntTy);
19134-
assert(E->getNumArgs() == 5 || E->getNumArgs() == 6);
19135-
bool InsertOld = E->getNumArgs() == 5;
19131+
Function *F =
19132+
CGM.getIntrinsic(BuiltinID == AMDGPU::BI__builtin_amdgcn_mov_dpp8
19133+
? Intrinsic::amdgcn_mov_dpp8
19134+
: Intrinsic::amdgcn_update_dpp,
19135+
IntTy);
19136+
assert(E->getNumArgs() == 5 || E->getNumArgs() == 6 ||
19137+
E->getNumArgs() == 2);
19138+
bool InsertOld = BuiltinID == AMDGPU::BI__builtin_amdgcn_mov_dpp;
1913619139
if (InsertOld)
1913719140
Args.push_back(llvm::PoisonValue::get(IntTy));
1913819141
for (unsigned I = 0; I != E->getNumArgs(); ++I) {
1913919142
llvm::Value *V = EmitScalarOrConstFoldImmArg(ICEArguments, I, E);
19140-
if (I <= (InsertOld ? 0u : 1u) && Size < 32) {
19143+
if (I < (BuiltinID == AMDGPU::BI__builtin_amdgcn_update_dpp ? 2 : 1) &&
19144+
Size < 32) {
1914119145
if (!DataTy->isIntegerTy())
1914219146
V = Builder.CreateBitCast(
1914319147
V, llvm::IntegerType::get(Builder.getContext(), Size));

clang/lib/Sema/SemaAMDGPU.cpp

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -63,49 +63,12 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
6363
OrderIndex = 0;
6464
ScopeIndex = 1;
6565
break;
66-
case AMDGPU::BI__builtin_amdgcn_mov_dpp: {
67-
if (SemaRef.checkArgCountRange(TheCall, 5, 5))
68-
return true;
69-
Expr *ValArg = TheCall->getArg(0);
70-
QualType Ty = ValArg->getType();
71-
// TODO: Vectors can also be supported.
72-
if (!Ty->isArithmeticType() || Ty->isAnyComplexType()) {
73-
SemaRef.Diag(ValArg->getBeginLoc(),
74-
diag::err_typecheck_cond_expect_int_float)
75-
<< Ty << ValArg->getSourceRange();
76-
return true;
77-
}
78-
return false;
79-
}
66+
case AMDGPU::BI__builtin_amdgcn_mov_dpp:
67+
return checkMovDPPFunctionCall(TheCall, 5, 1);
68+
case AMDGPU::BI__builtin_amdgcn_mov_dpp8:
69+
return checkMovDPPFunctionCall(TheCall, 2, 1);
8070
case AMDGPU::BI__builtin_amdgcn_update_dpp: {
81-
if (SemaRef.checkArgCountRange(TheCall, 6, 6))
82-
return true;
83-
Expr *Args[2];
84-
QualType ArgTys[2];
85-
for (unsigned I = 0; I != 2; ++I) {
86-
Args[I] = TheCall->getArg(I);
87-
ArgTys[I] = Args[I]->getType();
88-
// TODO: Vectors can also be supported.
89-
if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
90-
SemaRef.Diag(Args[I]->getBeginLoc(),
91-
diag::err_typecheck_cond_expect_int_float)
92-
<< ArgTys[I] << Args[I]->getSourceRange();
93-
return true;
94-
}
95-
}
96-
if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
97-
return false;
98-
if (((ArgTys[0]->isUnsignedIntegerType() &&
99-
ArgTys[1]->isSignedIntegerType()) ||
100-
(ArgTys[0]->isSignedIntegerType() &&
101-
ArgTys[1]->isUnsignedIntegerType())) &&
102-
getASTContext().getTypeSize(ArgTys[0]) ==
103-
getASTContext().getTypeSize(ArgTys[1]))
104-
return false;
105-
SemaRef.Diag(Args[1]->getBeginLoc(),
106-
diag::err_typecheck_call_different_arg_types)
107-
<< ArgTys[0] << ArgTys[1];
108-
return true;
71+
return checkMovDPPFunctionCall(TheCall, 6, 2);
10972
}
11073
default:
11174
return false;
@@ -152,6 +115,44 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
152115
return false;
153116
}
154117

118+
bool SemaAMDGPU::checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs,
119+
unsigned NumDataArgs) {
120+
assert(NumDataArgs <= 2);
121+
if (SemaRef.checkArgCountRange(TheCall, NumArgs, NumArgs))
122+
return true;
123+
Expr *Args[2];
124+
QualType ArgTys[2];
125+
for (unsigned I = 0; I != NumDataArgs; ++I) {
126+
Args[I] = TheCall->getArg(I);
127+
ArgTys[I] = Args[I]->getType();
128+
// TODO: Vectors can also be supported.
129+
if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
130+
SemaRef.Diag(Args[I]->getBeginLoc(),
131+
diag::err_typecheck_cond_expect_int_float)
132+
<< ArgTys[I] << Args[I]->getSourceRange();
133+
return true;
134+
}
135+
}
136+
if (NumDataArgs < 2)
137+
return false;
138+
139+
if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
140+
return false;
141+
142+
if (((ArgTys[0]->isUnsignedIntegerType() &&
143+
ArgTys[1]->isSignedIntegerType()) ||
144+
(ArgTys[0]->isSignedIntegerType() &&
145+
ArgTys[1]->isUnsignedIntegerType())) &&
146+
getASTContext().getTypeSize(ArgTys[0]) ==
147+
getASTContext().getTypeSize(ArgTys[1]))
148+
return false;
149+
150+
SemaRef.Diag(Args[1]->getBeginLoc(),
151+
diag::err_typecheck_call_different_arg_types)
152+
<< ArgTys[0] << ArgTys[1];
153+
return true;
154+
}
155+
155156
static bool
156157
checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr,
157158
const AMDGPUFlatWorkGroupSizeAttr &Attr) {

clang/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1012 -emit-llvm -o - %s | FileCheck %s
55
// RUN: %clang_cc1 -triple spirv64-amd-amdhsa -emit-llvm -o - %s | FileCheck %s
66

7+
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
8+
79
typedef unsigned int uint;
810
typedef unsigned long ulong;
911

@@ -19,12 +21,64 @@ void test_permlanex16(global uint* out, uint a, uint b, uint c, uint d) {
1921
*out = __builtin_amdgcn_permlanex16(a, b, c, d, 0, 0);
2022
}
2123

22-
// CHECK-LABEL: @test_mov_dpp8(
23-
// CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.mov.dpp8.i32(i32 %a, i32 1)
24-
void test_mov_dpp8(global uint* out, uint a) {
24+
// CHECK-LABEL: @test_mov_dpp8_uint(
25+
// CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.mov.dpp8.i32(i32 %a, i32 1)
26+
// CHECK-NEXT: store i32 %0,
27+
void test_mov_dpp8_uint(global uint* out, uint a) {
28+
*out = __builtin_amdgcn_mov_dpp8(a, 1);
29+
}
30+
31+
// CHECK-LABEL: @test_mov_dpp8_long(
32+
// CHECK: {{.*}}call{{.*}} i64 @llvm.amdgcn.mov.dpp8.i64(i64 %a, i32 1)
33+
// CHECK-NEXT: store i64 %0,
34+
void test_mov_dpp8_long(global long* out, long a) {
2535
*out = __builtin_amdgcn_mov_dpp8(a, 1);
2636
}
2737

38+
// CHECK-LABEL: @test_mov_dpp8_float(
39+
// CHECK: %0 = bitcast float %a to i32
40+
// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.mov.dpp8.i32(i32 %0, i32 1)
41+
// CHECK-NEXT: store i32 %1,
42+
void test_mov_dpp8_float(global float* out, float a) {
43+
*out = __builtin_amdgcn_mov_dpp8(a, 1);
44+
}
45+
46+
// CHECK-LABEL: @test_mov_dpp8_double
47+
// CHECK: %0 = bitcast double %x to i64
48+
// CHECK-NEXT: %1 = tail call{{.*}} i64 @llvm.amdgcn.mov.dpp8.i64(i64 %0, i32 1)
49+
// CHECK-NEXT: store i64 %1,
50+
void test_mov_dpp8_double(double x, global double *p) {
51+
*p = __builtin_amdgcn_mov_dpp8(x, 1);
52+
}
53+
54+
// CHECK-LABEL: @test_mov_dpp8_short
55+
// CHECK: %0 = zext i16 %x to i32
56+
// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.mov.dpp8.i32(i32 %0, i32 1)
57+
// CHECK-NEXT: %2 = trunc i32 %1 to i16
58+
// CHECK-NEXT: store i16 %2,
59+
void test_mov_dpp8_short(short x, global short *p) {
60+
*p = __builtin_amdgcn_mov_dpp8(x, 1);
61+
}
62+
63+
// CHECK-LABEL: @test_mov_dpp8_char
64+
// CHECK: %0 = zext i8 %x to i32
65+
// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.mov.dpp8.i32(i32 %0, i32 1)
66+
// CHECK-NEXT: %2 = trunc i32 %1 to i8
67+
// CHECK-NEXT: store i8 %2,
68+
void test_mov_dpp8_char(char x, global char *p) {
69+
*p = __builtin_amdgcn_mov_dpp8(x, 1);
70+
}
71+
72+
// CHECK-LABEL: @test_mov_dpp8_half
73+
// CHECK: %0 = load i16,
74+
// CHECK: %1 = zext i16 %0 to i32
75+
// CHECK-NEXT: %2 = tail call{{.*}} i32 @llvm.amdgcn.mov.dpp8.i32(i32 %1, i32 1)
76+
// CHECK-NEXT: %3 = trunc i32 %2 to i16
77+
// CHECK-NEXT: store i16 %3,
78+
void test_mov_dpp8_half(half *x, global half *p) {
79+
*p = __builtin_amdgcn_mov_dpp8(*x, 1);
80+
}
81+
2882
// CHECK-LABEL: @test_s_memtime
2983
// CHECK: {{.*}}call{{.*}} i64 @llvm.amdgcn.s.memtime()
3084
void test_s_memtime(global ulong* out)

clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,30 @@
55
// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx900 -verify -S -o - %s
66
// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx908 -verify -S -o - %s
77

8+
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
9+
810
typedef unsigned int uint;
11+
typedef int int2 __attribute__((ext_vector_type(2)));
912

13+
struct S {
14+
int x;
15+
};
1016

1117
void test(global uint* out, uint a, uint b, uint c, uint d) {
1218
*out = __builtin_amdgcn_permlane16(a, b, c, d, 1, 1); // expected-error {{'__builtin_amdgcn_permlane16' needs target feature gfx10-insts}}
1319
*out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, 1); // expected-error {{'__builtin_amdgcn_permlanex16' needs target feature gfx10-insts}}
1420
*out = __builtin_amdgcn_mov_dpp8(a, 1); // expected-error {{'__builtin_amdgcn_mov_dpp8' needs target feature gfx10-insts}}
1521
}
22+
23+
void test_mov_dpp8(global int* out, int src, int i, int2 i2, struct S s, float _Complex fc)
24+
{
25+
*out = __builtin_amdgcn_mov_dpp8(src, i); // expected-error{{argument to '__builtin_amdgcn_mov_dpp8' must be a constant integer}}
26+
*out = __builtin_amdgcn_mov_dpp8(src, 0.1); // expected-error{{argument to '__builtin_amdgcn_mov_dpp8' must be a constant integer}}
27+
*out = __builtin_amdgcn_mov_dpp8(src); // expected-error{{too few arguments to function call, expected 2, have 1}}
28+
*out = __builtin_amdgcn_mov_dpp8(src, 0, 0); // expected-error{{too many arguments to function call, expected at most 2, have 3}}
29+
*out = __builtin_amdgcn_mov_dpp8(out, 0); // expected-error{{used type '__global int *__private' where integer or floating point type is required}}
30+
*out = __builtin_amdgcn_mov_dpp8("aa", 0); // expected-error{{used type '__constant char[3]' where integer or floating point type is required}}
31+
*out = __builtin_amdgcn_mov_dpp8(i2, 0); // expected-error{{used type '__private int2' (vector of 2 'int' values) where integer or floating point type is required}}
32+
*out = __builtin_amdgcn_mov_dpp8(s, 0); // expected-error{{used type '__private struct S' where integer or floating point type is required}}
33+
*out = __builtin_amdgcn_mov_dpp8(fc, 0); // expected-error{{used type '__private _Complex float' where integer or floating point type is required}}
34+
}

0 commit comments

Comments
 (0)