Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20449,23 +20449,44 @@ RValue CodeGenFunction::EmitIntelFPGAMemBuiltin(const CallExpr *E) {
// Arguments
const Expr *PtrArg = E->getArg(0);
Value *PtrVal = EmitScalarExpr(PtrArg);
ASTContext &Ctx = getContext();

// Create the pointer annotation
Function *F =
CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, PtrVal->getType());
SmallString<256> AnnotStr;
llvm::raw_svector_ostream Out(AnnotStr);

Optional<llvm::APSInt> Params =
E->getArg(1)->getIntegerConstantExpr(getContext());
Optional<llvm::APSInt> Params = E->getArg(1)->getIntegerConstantExpr(Ctx);
assert(Params.hasValue() && "Constant arg isn't actually constant?");
Out << "{params:" << toString(*Params, 10) << "}";

Optional<llvm::APSInt> CacheSize =
E->getArg(2)->getIntegerConstantExpr(getContext());
Optional<llvm::APSInt> CacheSize = E->getArg(2)->getIntegerConstantExpr(Ctx);
assert(CacheSize.hasValue() && "Constant arg isn't actually constant?");
Out << "{cache-size:" << toString(*CacheSize, 10) << "}";

// There are four optional arguments with the following default values:
// const int32_t AnchorID = -1
// const int32_t TargetAnchor = 0
// const int32_t Type = 0
// const int32_t Cycle = 0
// Emit default values or use provided.
auto AddOptionalArgValue = [&E, &Ctx, &Out](int DefaultValue,
unsigned NumOfArg,
StringRef StringToAdd) {
Optional<llvm::APSInt> IntVal =
(E->getNumArgs() > NumOfArg)
? E->getArg(NumOfArg)->getIntegerConstantExpr(Ctx)
: APSInt::get(DefaultValue);
assert(IntVal.hasValue() && "Constant arg isn't actually constant?");
Out << "{" << StringToAdd << ":" << toString(*IntVal, 10) << "}";
};

AddOptionalArgValue(-1, 3, "anchor-id");
AddOptionalArgValue(0, 4, "target-anchor");
AddOptionalArgValue(0, 5, "type");
AddOptionalArgValue(0, 6, "cycle");
Comment on lines +20474 to +20488
Copy link
Contributor

@mlychkov mlychkov Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May we use AddOptionalArgValue for first two parameters as well (maybe to rename lambda to AddArgValue)?

Suggested change
auto AddOptionalArgValue = [&E, &Ctx, &Out](int DefaultValue,
unsigned NumOfArg,
StringRef StringToAdd) {
Optional<llvm::APSInt> IntVal =
(E->getNumArgs() > NumOfArg)
? E->getArg(NumOfArg)->getIntegerConstantExpr(Ctx)
: APSInt::get(DefaultValue);
assert(IntVal.hasValue() && "Constant arg isn't actually constant?");
Out << "{" << StringToAdd << ":" << toString(*IntVal, 10) << "}";
};
AddOptionalArgValue(-1, 3, "anchor-id");
AddOptionalArgValue(0, 4, "target-anchor");
AddOptionalArgValue(0, 5, "type");
AddOptionalArgValue(0, 6, "cycle");
auto AddArgValue = [&E, &Ctx, &Out](unsigned NumOfArg,
StringRef StringToAdd,
int DefaultValue = MIN_INT) {
Optional<llvm::APSInt> IntVal =
(E->getNumArgs() > NumOfArg)
? E->getArg(NumOfArg)->getIntegerConstantExpr(Ctx)
: APSInt::get(DefaultValue);
assert(IntVal.hasValue() && "Constant arg isn't actually constant?");
Out << "{" << StringToAdd << ":" << toString(*IntVal, 10) << "}";
};
AddArgValue(1, "params");
AddArgValue(2, "cache-size");
AddArgValue(3, "anchor-id", -1);
AddArgValue(4, "target-anchor", 0);
AddArgValue(5, "type", 0);
AddArgValue(6, "cycle", 0);


llvm::Value *Ann = EmitAnnotationCall(F, PtrVal, AnnotStr, SourceLocation());

cast<CallBase>(Ann)->addFnAttr(llvm::Attribute::ReadNone);
Expand Down
26 changes: 23 additions & 3 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4859,9 +4859,23 @@ bool Sema::CheckIntelFPGARegBuiltinFunctionCall(unsigned BuiltinID,
}

bool Sema::CheckIntelFPGAMemBuiltinFunctionCall(CallExpr *TheCall) {
// Make sure we have exactly 3 arguments
if (checkArgCount(*this, TheCall, 3))
return true;
const unsigned MinNumArgs = 3;
const unsigned MaxNumArgs = 7;
unsigned NumArgs = TheCall->getNumArgs();

// Make sure we have the minimum number of provided arguments.
if (NumArgs < MinNumArgs)
return Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_few_args_at_least)
<< 0 /* function call */ << MinNumArgs << NumArgs
<< TheCall->getSourceRange();

// Make sure we don't have too many arguments.
if (NumArgs > MaxNumArgs)
return Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_many_args_at_most)
<< 0 /*function call*/ << MaxNumArgs << NumArgs
<< TheCall->getSourceRange();

Expr *PointerArg = TheCall->getArg(0);
QualType PointerArgType = PointerArg->getType();
Expand Down Expand Up @@ -4897,6 +4911,12 @@ bool Sema::CheckIntelFPGAMemBuiltinFunctionCall(CallExpr *TheCall) {
return Diag(TheCall->getArg(2)->getBeginLoc(),
diag::err_intel_fpga_mem_arg_mismatch) << 1;

// The last four optional arguments must be signed constant integers.
for (unsigned I = MinNumArgs; I != NumArgs; ++I) {
if (SemaBuiltinConstantArg(TheCall, I, Result))
return true;
}

// Set the return type to be the same as the type of the first argument
// (pointer argument)
TheCall->setType(PointerArgType);
Expand Down
34 changes: 32 additions & 2 deletions clang/test/CodeGenSYCL/intel-fpga-mem-builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
#define PARAM_1 1U << 7
#define PARAM_2 1U << 8

// This test checks that using of __builtin_intel_fpga_mem results in correct
// generation of annotations in LLVM IR.

// CHECK: [[STRUCT:%.*]] = type { i32, float }
struct State {
int x;
float y;
};

// CHECK: [[ANN1:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:0}
// CHECK: [[ANN2:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:127}
// CHECK: [[ANN1:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:0}{anchor-id:-1}{target-anchor:0}{type:0}{cycle:0}
// CHECK: [[ANN2:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:127}{anchor-id:-1}{target-anchor:0}{type:0}{cycle:0}
// CHECK: [[ANN3:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:127}{anchor-id:10}{target-anchor:20}{type:30}{cycle:40}
// CHECK: [[ANN4:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:127}{anchor-id:11}{target-anchor:12}{type:0}{cycle:0}
// CHECK: [[ANN5:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:127}{anchor-id:100}{target-anchor:0}{type:0}{cycle:0}
// CHECK: [[ANN6:@.str[\.]*[0-9]*]] = {{.*}}{params:384}{cache-size:128}{anchor-id:4}{target-anchor:7}{type:8}{cycle:0}

// CHECK: define {{.*}}spir_func void @{{.*}}(float addrspace(4)* %A, i32 addrspace(4)* %B, [[STRUCT]] addrspace(4)* %C, [[STRUCT]] addrspace(4)*{{.*}}%D)
void foo(float *A, int *B, State *C, State &D) {
Expand Down Expand Up @@ -65,6 +72,29 @@ void foo(float *A, int *B, State *C, State &D) {
// CHECK-DAG: [[PTR8:%[0-9]+]] = call double addrspace(4)* @llvm.ptr.annotation{{.*}}[[F]]{{.*}}[[ANN2]]{{.*}}[[ATT:#[0-9]+]]
// CHECK-DAG: store double addrspace(4)* [[PTR8]], double addrspace(4)* addrspace(4)* [[f]]
f = __builtin_intel_fpga_mem(&F, PARAM_1 | PARAM_2, 127);

// CHECK-DAG: [[A3:%[0-9]+]] = load float addrspace(4)*, float addrspace(4)* addrspace(4)* [[Aaddr]]
// CHECK-DAG: [[PTR9:%[0-9]+]] = call float addrspace(4)* @llvm.ptr.annotation{{.*}}[[A3]]{{.*}}[[ANN3]]{{.*}}[[ATT:#[0-9]+]]
// CHECK-DAG: store float addrspace(4)* [[PTR9]], float addrspace(4)* addrspace(4)* %x
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 127, 10, 20, 30, 40);

// CHECK-DAG: [[A4:%[0-9]+]] = load float addrspace(4)*, float addrspace(4)* addrspace(4)* [[Aaddr]]
// CHECK-DAG: [[PTR10:%[0-9]+]] = call float addrspace(4)* @llvm.ptr.annotation{{.*}}[[A4]]{{.*}}[[ANN4]]{{.*}}[[ATT:#[0-9]+]]
// CHECK-DAG: store float addrspace(4)* [[PTR10]], float addrspace(4)* addrspace(4)* %x
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 127, 11, 12);

// CHECK-DAG: [[B3:%[0-9]+]] = load i32 addrspace(4)*, i32 addrspace(4)* addrspace(4)* [[Baddr]]
// CHECK-DAG: [[PTR11:%[0-9]+]] = call i32 addrspace(4)* @llvm.ptr.annotation{{.*}}[[B3]]{{.*}}[[ANN5]]{{.*}}[[ATT:#[0-9]+]]
// CHECK-DAG: store i32 addrspace(4)* [[PTR11]], i32 addrspace(4)* addrspace(4)* %y
y = __builtin_intel_fpga_mem(B, PARAM_1 | PARAM_2, 127, 100);

constexpr int TestVal1 = 7;
constexpr int TestVal2 = 8;

// CHECK-DAG: [[D1:%[0-9]+]] = load [[STRUCT]] addrspace(4)*, [[STRUCT]] addrspace(4)* addrspace(4)* [[Daddr]]
// CHECK-DAG: [[PTR12:%[0-9]+]] = call [[STRUCT]] addrspace(4)* @llvm.ptr.annotation{{.*}}[[D1]]{{.*}}[[ANN6]]{{.*}}[[ATT:#[0-9]+]]
// CHECK-DAG: store [[STRUCT]] addrspace(4)* [[PTR12]], [[STRUCT]] addrspace(4)* addrspace(4)* %z
z = __builtin_intel_fpga_mem(&D, PARAM_1 | PARAM_2, 128, 4, TestVal1, TestVal2);
}

// CHECK-DAG: attributes [[ATT]] = { readnone }
Expand Down
25 changes: 22 additions & 3 deletions clang/test/SemaSYCL/intel-fpga-mem-builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#define PARAM_1 1U << 7
#define PARAM_2 1U << 8

// This test makes sure that the compiler checks the semantics of
// __builtin_intel_fpga_mem built-in function arguments correctly.

#ifdef __SYCL_DEVICE_ONLY__
static_assert(__has_builtin(__builtin_intel_fpga_mem), "");
struct State {
Expand All @@ -29,9 +32,7 @@ void foo(float *A, int *B, State *C) {
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, -1);
// expected-error@-1{{builtin parameter must be a non-negative integer constant}}
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2);
// expected-error@-1{{too few arguments to function call, expected 3, have 2}}
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1);
// expected-error@-1{{too many arguments to function call, expected 3, have 4}}
// expected-error@-1{{too few arguments to function call, expected at least 3, have 2}}
y = __builtin_intel_fpga_mem(B, 0, i);
// expected-error@-1{{argument to '__builtin_intel_fpga_mem' must be a constant integer}}
z = __builtin_intel_fpga_mem(C, i, 0);
Expand All @@ -53,6 +54,24 @@ void foo(float *A, int *B, State *C) {
struct outer *iii;
struct outer *iv = __builtin_intel_fpga_mem(iii, 0, 0);
// expected-error@-1{{illegal field in type pointed to by pointer argument to __builtin_intel_fpga_mem; only pointers to a first class lvalue or to an rvalue are allowed}}

// Up to 7 parameters is ok.
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1);
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, 10);
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, 10, 20);
x = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, -1, 10, 20);

z = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, B, -1, 1, 1);
// expected-error@-1{{argument to '__builtin_intel_fpga_mem' must be a constant integer}}
z = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, U, 10, 20);
// expected-error@-1{{argument to '__builtin_intel_fpga_mem' must be a constant integer}}
z = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, -1, C, 300);
// expected-error@-1{{argument to '__builtin_intel_fpga_mem' must be a constant integer}}
z = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, -1, 1, i);
// expected-error@-1{{argument to '__builtin_intel_fpga_mem' must be a constant integer}}

y = __builtin_intel_fpga_mem(A, PARAM_1 | PARAM_2, 1, 1, -1, 10, 20, 30);
// expected-error@-1{{too many arguments to function call, expected at most 7, have 8}}
}

template <typename name, typename Func>
Expand Down