From 3a3b332ab57891b8699a270019f8ebbf29df5b2e Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Tue, 16 Jul 2019 17:24:33 +0000 Subject: [PATCH 1/7] fix unnamed fiefield issue and add tests for __builtin_preserve_access_index intrinsic The original commit is r366076. It is temporarily reverted (r366155) due to test failure. This resubmit makes test more robust by accepting regex instead of hardcoded names/references in several places. This is a followup patch for https://reviews.llvm.org/D61809. Handle unnamed bitfield properly and add more test cases. Fixed the unnamed bitfield issue. The unnamed bitfield is ignored by debug info, so we need to ignore such a struct/union member when we try to get the member index in the debug info. D61809 contains two test cases but not enough as it does not checking generated IRs in the fine grain level, and also it does not have semantics checking tests. This patch added unit tests for both code gen and semantics checking for the new intrinsic. Signed-off-by: Yonghong Song git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366231 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExpr.cpp | 21 ++- lib/CodeGen/CodeGenFunction.h | 3 + test/CodeGen/builtin-preserve-access-index.c | 177 +++++++++++++++++++ test/Sema/builtin-preserve-access-index.c | 13 ++ 4 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/builtin-preserve-access-index.c create mode 100644 test/Sema/builtin-preserve-access-index.c diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 4d19a12e5cb0..5a4b1188b711 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -3892,6 +3892,23 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) { return EmitLValueForField(LambdaLV, Field); } +/// Get the field index in the debug info. The debug info structure/union +/// will ignore the unnamed bitfields. +unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec, + unsigned FieldIndex) { + unsigned I = 0, Skipped = 0; + + for (auto F : Rec->getDefinition()->fields()) { + if (I == FieldIndex) + break; + if (F->isUnnamedBitfield()) + Skipped++; + I++; + } + + return FieldIndex - Skipped; +} + /// Get the address of a zero-sized field within a record. The resulting /// address doesn't necessarily have the right type. static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base, @@ -3931,7 +3948,7 @@ static Address emitPreserveStructAccess(CodeGenFunction &CGF, Address base, CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); return CGF.Builder.CreatePreserveStructAccessIndex( - base, idx, field->getFieldIndex(), DbgInfo); + base, idx, CGF.getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo); } static bool hasAnyVptr(const QualType Type, const ASTContext &Context) { @@ -4048,7 +4065,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, getContext().getRecordType(rec), rec->getLocation()); addr = Address( Builder.CreatePreserveUnionAccessIndex( - addr.getPointer(), field->getFieldIndex(), DbgInfo), + addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), addr.getAlignment()); } } else { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index bd9e14206a09..06ef2dff7e9f 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2652,6 +2652,9 @@ class CodeGenFunction : public CodeGenTypeCache { /// Converts Location to a DebugLoc, if debug information is enabled. llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location); + /// Get the record field index as represented in debug info. + unsigned getDebugInfoFIndex(const RecordDecl *Rec, unsigned FieldIndex); + //===--------------------------------------------------------------------===// // Declaration Emission diff --git a/test/CodeGen/builtin-preserve-access-index.c b/test/CodeGen/builtin-preserve-access-index.c new file mode 100644 index 000000000000..954a3b827d25 --- /dev/null +++ b/test/CodeGen/builtin-preserve-access-index.c @@ -0,0 +1,177 @@ +// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s + +#define _(x) (__builtin_preserve_access_index(x)) + +const void *unit1(const void *arg) { + return _(arg); +} +// CHECK: define dso_local i8* @unit1 +// CHECK-NOT: llvm.preserve.array.access.index +// CHECK-NOT: llvm.preserve.struct.access.index +// CHECK-NOT: llvm.preserve.union.access.index + +const void *unit2(void) { + return _((const void *)0xffffffffFFFF0000ULL); +} +// CHECK: define dso_local i8* @unit2 +// CHECK-NOT: llvm.preserve.array.access.index +// CHECK-NOT: llvm.preserve.struct.access.index +// CHECK-NOT: llvm.preserve.union.access.index + +const void *unit3(const int *arg) { + return _(arg + 1); +} +// CHECK: define dso_local i8* @unit3 +// CHECK-NOT: llvm.preserve.array.access.index +// CHECK-NOT: llvm.preserve.struct.access.index +// CHECK-NOT: llvm.preserve.union.access.index + +const void *unit4(const int *arg) { + return _(&arg[1]); +} +// CHECK: define dso_local i8* @unit4 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1) + +const void *unit5(const int *arg[5]) { + return _(&arg[1][2]); +} +// CHECK: define dso_local i8* @unit5 +// CHECK-NOT: getelementptr +// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2) + +struct s1 { + char a; + int b; +}; + +struct s2 { + char a1:1; + char a2:1; + int b; +}; + +struct s3 { + char a1:1; + char a2:1; + char :6; + int b; +}; + +const void *unit6(struct s1 *arg) { + return _(&arg->a); +} +// CHECK: define dso_local i8* @unit6 +// CHECK-NOT: getelementptr +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] + +const void *unit7(struct s1 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit7 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1]] + +const void *unit8(struct s2 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit8 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] + +const void *unit9(struct s3 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit9 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S3:[0-9]+]] + +union u1 { + char a; + int b; +}; + +union u2 { + char a; + int :32; + int b; +}; + +const void *unit10(union u1 *arg) { + return _(&arg->a); +} +// CHECK: define dso_local i8* @unit10 +// CHECK-NOT: getelementptr +// CHECK: call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1:[0-9]+]] + +const void *unit11(union u1 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit11 +// CHECK-NOT: getelementptr +// CHECK: call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1]] + +const void *unit12(union u2 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit12 +// CHECK-NOT: getelementptr +// CHECK: call %union.u2* @llvm.preserve.union.access.index.p0s_union.u2s.p0s_union.u2s(%union.u2* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U2:[0-9]+]] + +struct s4 { + char d; + union u { + int b[4]; + char a; + } c; +}; + +union u3 { + struct s { + int b[4]; + } c; + char a; +}; + +const void *unit13(struct s4 *arg) { + return _(&arg->c.b[2]); +} +// CHECK: define dso_local i8* @unit13 +// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]] +// CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) + +const void *unit14(union u3 *arg) { + return _(&arg->c.b[2]); +} +// CHECK: define dso_local i8* @unit14 +// CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3:[0-9]+]] +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) + +const void *unit15(struct s4 *arg) { + return _(&arg[2].c.a); +} +// CHECK: define dso_local i8* @unit15 +// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4]] +// CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U]] + +const void *unit16(union u3 *arg) { + return _(&arg[2].a); +} +// CHECK: define dso_local i8* @unit16 +// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3]] + +// CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" +// CHECK: ![[STRUCT_S2]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s2" +// CHECK: ![[STRUCT_S3]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s3" +// CHECK: ![[UNION_U1]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u1" +// CHECK: ![[UNION_U2]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u2" +// CHECK: ![[STRUCT_S4]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s4" +// CHECK: ![[UNION_I_U]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u" +// CHECK: ![[UNION_U3]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u3" +// CHECK: ![[STRUCT_I_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s" diff --git a/test/Sema/builtin-preserve-access-index.c b/test/Sema/builtin-preserve-access-index.c new file mode 100644 index 000000000000..c10ceb5145b8 --- /dev/null +++ b/test/Sema/builtin-preserve-access-index.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s + +const void *invalid1(const int *arg) { + return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}} +} + +void *invalid2(const int *arg) { + return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const void *' from a function with result type 'void *' discards qualifiers}} +} + +const void *invalid3(const int *arg) { + return __builtin_preserve_access_index(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *'}} +} From 34ac8add980e2e9b0a30ef72d8003a039b40757e Mon Sep 17 00:00:00 2001 From: Ben Hamilton Date: Tue, 16 Jul 2019 21:29:40 +0000 Subject: [PATCH 2/7] [clang-format] Don't detect call to ObjC class method as C++11 attribute specifier Summary: Previously, clang-format detected something like the following as a C++11 attribute specifier. @[[NSArray class]] instead of an array with an Objective-C method call inside. In general, when the attribute specifier checking runs, if it sees 2 identifiers in a row, it decides that the square brackets represent an Objective-C method call. However, here, `class` is tokenized as a keyword instead of an identifier, so this check fails. To fix this, the attribute specifier first checks whether the first square bracket has an "@" before it. If it does, then that square bracket is not the start of a attribute specifier because it is an Objective-C array literal. (The assumption is that @[[.*]] is not valid C/C++.) Contributed by rkgibson2. Reviewers: benhamilton Reviewed By: benhamilton Subscribers: aaron.ballman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64632 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366267 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 6 +++++- unittests/Format/FormatTest.cpp | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 6b698e24b5e5..490c4f46135e 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -388,6 +388,10 @@ class AnnotatingParser { bool isCpp11AttributeSpecifier(const FormatToken &Tok) { if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square)) return false; + // The first square bracket is part of an ObjC array literal + if (Tok.Previous && Tok.Previous->is(tok::at)) { + return false; + } const FormatToken *AttrTok = Tok.Next->Next; if (!AttrTok) return false; @@ -400,7 +404,7 @@ class AnnotatingParser { while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) { // ObjC message send. We assume nobody will use : in a C++11 attribute // specifier parameter, although this is technically valid: - // [[foo(:)]] + // [[foo(:)]]. if (AttrTok->is(tok::colon) || AttrTok->startsSequence(tok::identifier, tok::identifier) || AttrTok->startsSequence(tok::r_paren, tok::identifier)) diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index c4abad228d0a..c1cec110137b 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -7027,6 +7027,12 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) { // On the other hand, we still need to correctly find array subscripts. verifyFormat("int a = std::vector{1, 2, 3}[0];"); + // Make sure that we do not mistake Objective-C method inside array literals + // as attributes, even if those method names are also keywords. + verifyFormat("@[ [foo bar] ];"); + verifyFormat("@[ [NSArray class] ];"); + verifyFormat("@[ [foo enum] ];"); + // Make sure we do not parse attributes as lambda introducers. FormatStyle MultiLineFunctions = getLLVMStyle(); MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; From c0300437e347c1c5f86cc19b671b331a42ee6377 Mon Sep 17 00:00:00 2001 From: Guanzhong Chen Date: Tue, 16 Jul 2019 22:00:45 +0000 Subject: [PATCH 3/7] [WebAssembly] Implement thread-local storage (local-exec model) Summary: Thread local variables are placed inside a `.tdata` segment. Their symbols are offsets from the start of the segment. The address of a thread local variable is computed as `__tls_base` + the offset from the start of the segment. `.tdata` segment is a passive segment and `memory.init` is used once per thread to initialize the thread local storage. `__tls_base` is a wasm global. Since each thread has its own wasm instance, it is effectively thread local. Currently, `__tls_base` must be initialized at thread startup, and so cannot be used with dynamic libraries. `__tls_base` is to be initialized with a new linker-synthesized function, `__wasm_init_tls`, which takes as an argument a block of memory to use as the storage for thread locals. It then initializes the block of memory and sets `__tls_base`. As `__wasm_init_tls` will handle the memory initialization, the memory does not have to be zeroed. To help allocating memory for thread-local storage, a new compiler intrinsic is introduced: `__builtin_wasm_tls_size()`. This instrinsic function returns the size of the thread-local storage for the current function. The expected usage is to run something like the following upon thread startup: __wasm_init_tls(malloc(__builtin_wasm_tls_size())); Reviewers: tlively, aheejin, kripken, sbc100 Subscribers: dschuff, jgravelle-google, hiraditya, sunfish, jfb, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D64537 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366272 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsWebAssembly.def | 3 +++ lib/CodeGen/CGBuiltin.cpp | 5 +++++ test/CodeGen/builtins-wasm.c | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def index 57ebb27ab469..63177f016ac7 100644 --- a/include/clang/Basic/BuiltinsWebAssembly.def +++ b/include/clang/Basic/BuiltinsWebAssembly.def @@ -29,6 +29,9 @@ BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n") TARGET_BUILTIN(__builtin_wasm_memory_init, "vIUiIUiv*UiUi", "", "bulk-memory") TARGET_BUILTIN(__builtin_wasm_data_drop, "vIUi", "", "bulk-memory") +// Thread-local storage +TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory") + // Floating point min/max BUILTIN(__builtin_wasm_min_f32, "fff", "nc") BUILTIN(__builtin_wasm_max_f32, "fff", "nc") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index acaa81ae8a9a..1658be5a88e0 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -13913,6 +13913,11 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_data_drop); return Builder.CreateCall(Callee, {Arg}); } + case WebAssembly::BI__builtin_wasm_tls_size: { + llvm::Type *ResultType = ConvertType(E->getType()); + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_size, ResultType); + return Builder.CreateCall(Callee); + } case WebAssembly::BI__builtin_wasm_throw: { Value *Tag = EmitScalarExpr(E->getArg(0)); Value *Obj = EmitScalarExpr(E->getArg(1)); diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c index 4784d6ff86eb..8a17fb39641b 100644 --- a/test/CodeGen/builtins-wasm.c +++ b/test/CodeGen/builtins-wasm.c @@ -38,6 +38,12 @@ void data_drop() { // WEBASSEMBLY64: call void @llvm.wasm.data.drop(i32 3) } +__SIZE_TYPE__ tls_size() { + return __builtin_wasm_tls_size(); + // WEBASSEMBLY32: call i32 @llvm.wasm.tls.size.i32() + // WEBASSEMBLY64: call i64 @llvm.wasm.tls.size.i64() +} + void throw(void *obj) { return __builtin_wasm_throw(0, obj); // WEBASSEMBLY32: call void @llvm.wasm.throw(i32 0, i8* %{{.*}}) From d4ab953bb6d15ddfc74e23f9b318d5666eaef367 Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Tue, 16 Jul 2019 22:32:17 +0000 Subject: [PATCH 4/7] Fix a typo in target features There was a slight typo in r364352 that ended up causing our backend to complain on some x86 Android builds. This CL fixes that. Differential Revision: https://reviews.llvm.org/D64781 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366276 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Arch/X86.cpp | 2 +- test/Driver/clang-translation.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp index 2e75039bf0d6..34be226b69e9 100644 --- a/lib/Driver/ToolChains/Arch/X86.cpp +++ b/lib/Driver/ToolChains/Arch/X86.cpp @@ -135,7 +135,7 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, if (ArchType == llvm::Triple::x86_64) { Features.push_back("+sse4.2"); Features.push_back("+popcnt"); - Features.push_back("+mcx16"); + Features.push_back("+cx16"); } else Features.push_back("+ssse3"); } diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c index 0054535115aa..766e77938269 100644 --- a/test/Driver/clang-translation.c +++ b/test/Driver/clang-translation.c @@ -318,7 +318,7 @@ // ANDROID-X86_64: "-target-cpu" "x86-64" // ANDROID-X86_64: "-target-feature" "+sse4.2" // ANDROID-X86_64: "-target-feature" "+popcnt" -// ANDROID-X86_64: "-target-feature" "+mcx16" +// ANDROID-X86_64: "-target-feature" "+cx16" // RUN: %clang -target mips-linux-gnu -### -S %s 2>&1 | \ // RUN: FileCheck -check-prefix=MIPS %s From a8f93529603ebb5459b312229e83f275b0e8032a Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 16 Jul 2019 23:38:05 +0000 Subject: [PATCH 5/7] Fix darwin-ld.c if dsymutil.exe exists on PATH git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366282 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/darwin-ld.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c index f01eeb4ea28e..eb357a9819ff 100644 --- a/test/Driver/darwin-ld.c +++ b/test/Driver/darwin-ld.c @@ -5,9 +5,9 @@ // Make sure we run dsymutil on source input files. // RUN: %clang -target i386-apple-darwin9 -### -g %s -o BAR 2> %t.log -// RUN: grep '".*dsymutil" "-o" "BAR.dSYM" "BAR"' %t.log +// RUN: grep '".*dsymutil\(.exe\)\?" "-o" "BAR.dSYM" "BAR"' %t.log // RUN: %clang -target i386-apple-darwin9 -### -g -filelist FOO %s -o BAR 2> %t.log -// RUN: grep '".*dsymutil" "-o" "BAR.dSYM" "BAR"' %t.log +// RUN: grep '".*dsymutil\(.exe\)\?" "-o" "BAR.dSYM" "BAR"' %t.log // Check linker changes that came with new linkedit format. // RUN: touch %t.o From 9999ed4f4df6817ed2890d7d69b90aa17390412a Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 16 Jul 2019 23:44:33 +0000 Subject: [PATCH 6/7] Fix OpenCLCXX test on 32-bit Windows where thiscall is present git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366284 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaOpenCLCXX/address-space-deduction.cl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/SemaOpenCLCXX/address-space-deduction.cl b/test/SemaOpenCLCXX/address-space-deduction.cl index f66d224e2541..08668951dbca 100644 --- a/test/SemaOpenCLCXX/address-space-deduction.cl +++ b/test/SemaOpenCLCXX/address-space-deduction.cl @@ -30,8 +30,8 @@ struct c2 { template struct x1 { -//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &) __generic' -//CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &) __generic' +//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &){{( __attribute__.*)?}} __generic' +//CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &){{( __attribute__.*)?}} __generic' x1& operator=(const x1& xx) { y = xx.y; return *this; @@ -41,8 +41,8 @@ struct x1 { template struct x2 { -//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *) __generic' -//CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *) __generic' +//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *){{( __attribute__.*)?}} __generic' +//CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *){{( __attribute__.*)?}} __generic' void foo(x1* xx) { m[0] = *xx; } @@ -57,9 +57,9 @@ void bar(__global x1 *xx, __global x2 *bar) { template class x3 : public T { public: - //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &) __generic' + //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic' x3(const x3 &t); }; -//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &) __generic' +//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic' template x3::x3(const x3 &t) {} From 28d7aae8af895a4b60fd8b44efdd659957ef6642 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 17 Jul 2019 00:01:03 +0000 Subject: [PATCH 7/7] AMDGPU: Add some missing builtins git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366286 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsAMDGPU.def | 17 +++++ lib/CodeGen/CGBuiltin.cpp | 6 ++ test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl | 24 +++++++ test/CodeGenOpenCL/builtins-amdgcn.cl | 64 +++++++++++++++++++ .../builtins-amdgcn-error-gfx10-param.cl | 18 ++++++ .../SemaOpenCL/builtins-amdgcn-error-gfx10.cl | 15 +++++ 6 files changed, 144 insertions(+) create mode 100644 test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl create mode 100644 test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl create mode 100644 test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def index e882d3b87c66..2f8fb9000a76 100644 --- a/include/clang/Basic/BuiltinsAMDGPU.def +++ b/include/clang/Basic/BuiltinsAMDGPU.def @@ -108,6 +108,16 @@ BUILTIN(__builtin_amdgcn_ds_fminf, "ff*3fIiIiIb", "n") BUILTIN(__builtin_amdgcn_ds_fmaxf, "ff*3fIiIiIb", "n") BUILTIN(__builtin_amdgcn_ds_append, "ii*3", "n") BUILTIN(__builtin_amdgcn_ds_consume, "ii*3", "n") +BUILTIN(__builtin_amdgcn_alignbit, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_alignbyte, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_ubfe, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_sbfe, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_cvt_pkrtz, "E2hff", "nc") +BUILTIN(__builtin_amdgcn_cvt_pknorm_i16, "E2sff", "nc") +BUILTIN(__builtin_amdgcn_cvt_pknorm_u16, "E2Usff", "nc") +BUILTIN(__builtin_amdgcn_cvt_pk_i16, "E2sii", "nc") +BUILTIN(__builtin_amdgcn_cvt_pk_u16, "E2UsUiUi", "nc") +BUILTIN(__builtin_amdgcn_cvt_pk_u8_f32, "UifUiUi", "nc") //===----------------------------------------------------------------------===// // CI+ only builtins. @@ -162,6 +172,13 @@ TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dot2-insts") TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot1-insts") TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot2-insts") +//===----------------------------------------------------------------------===// +// GFX10+ only builtins. +//===----------------------------------------------------------------------===// +TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") +TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") +TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts") + //===----------------------------------------------------------------------===// // Special builtins. //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 1658be5a88e0..a300bab49f9c 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -12679,6 +12679,8 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_ds_swizzle: return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_ds_swizzle); + case AMDGPU::BI__builtin_amdgcn_mov_dpp8: + return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_mov_dpp8); case AMDGPU::BI__builtin_amdgcn_mov_dpp: case AMDGPU::BI__builtin_amdgcn_update_dpp: { llvm::SmallVector Args; @@ -12744,6 +12746,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_fract); case AMDGPU::BI__builtin_amdgcn_lerp: return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_lerp); + case AMDGPU::BI__builtin_amdgcn_ubfe: + return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_ubfe); + case AMDGPU::BI__builtin_amdgcn_sbfe: + return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_sbfe); case AMDGPU::BI__builtin_amdgcn_uicmp: case AMDGPU::BI__builtin_amdgcn_uicmpl: case AMDGPU::BI__builtin_amdgcn_sicmp: diff --git a/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl b/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl new file mode 100644 index 000000000000..3921cb90c3a5 --- /dev/null +++ b/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl @@ -0,0 +1,24 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1010 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1011 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1012 -S -emit-llvm -o - %s | FileCheck %s + +typedef unsigned int uint; + +// CHECK-LABEL: @test_permlane16( +// CHECK: call i32 @llvm.amdgcn.permlane16(i32 %a, i32 %b, i32 %c, i32 %d, i1 true, i1 true) +void test_permlane16(global uint* out, uint a, uint b, uint c, uint d) { + *out = __builtin_amdgcn_permlane16(a, b, c, d, 1, 1); +} + +// CHECK-LABEL: @test_permlanex16( +// CHECK: call i32 @llvm.amdgcn.permlanex16(i32 %a, i32 %b, i32 %c, i32 %d, i1 true, i1 true) +void test_permlanex16(global uint* out, uint a, uint b, uint c, uint d) { + *out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, 1); +} + +// CHECK-LABEL: @test_mov_dpp8( +// CHECK: call i32 @llvm.amdgcn.mov.dpp8.i32(i32 %a, i32 1) +void test_mov_dpp8(global uint* out, uint a) { + *out = __builtin_amdgcn_mov_dpp8(a, 1); +} diff --git a/test/CodeGenOpenCL/builtins-amdgcn.cl b/test/CodeGenOpenCL/builtins-amdgcn.cl index e4c40d92266f..bbae5ea24be0 100644 --- a/test/CodeGenOpenCL/builtins-amdgcn.cl +++ b/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -5,6 +5,10 @@ typedef unsigned long ulong; typedef unsigned int uint; +typedef unsigned short ushort; +typedef half __attribute__((ext_vector_type(2))) half2; +typedef short __attribute__((ext_vector_type(2))) short2; +typedef ushort __attribute__((ext_vector_type(2))) ushort2; // CHECK-LABEL: @test_div_scale_f64 // CHECK: call { double, i1 } @llvm.amdgcn.div.scale.f64(double %a, double %b, i1 true) @@ -590,6 +594,66 @@ kernel void test_mbcnt_hi(global uint* out, uint src0, uint src1) { *out = __builtin_amdgcn_mbcnt_hi(src0, src1); } +// CHECK-LABEL: @test_alignbit( +// CHECK: tail call i32 @llvm.amdgcn.alignbit(i32 %src0, i32 %src1, i32 %src2) +kernel void test_alignbit(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_alignbit(src0, src1, src2); +} + +// CHECK-LABEL: @test_alignbyte( +// CHECK: tail call i32 @llvm.amdgcn.alignbyte(i32 %src0, i32 %src1, i32 %src2) +kernel void test_alignbyte(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_alignbyte(src0, src1, src2); +} + +// CHECK-LABEL: @test_ubfe( +// CHECK: tail call i32 @llvm.amdgcn.ubfe.i32(i32 %src0, i32 %src1, i32 %src2) +kernel void test_ubfe(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_ubfe(src0, src1, src2); +} + +// CHECK-LABEL: @test_sbfe( +// CHECK: tail call i32 @llvm.amdgcn.sbfe.i32(i32 %src0, i32 %src1, i32 %src2) +kernel void test_sbfe(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_sbfe(src0, src1, src2); +} + +// CHECK-LABEL: @test_cvt_pkrtz( +// CHECK: tail call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %src0, float %src1) +kernel void test_cvt_pkrtz(global half2* out, float src0, float src1) { + *out = __builtin_amdgcn_cvt_pkrtz(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pknorm_i16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pknorm.i16(float %src0, float %src1) +kernel void test_cvt_pknorm_i16(global short2* out, float src0, float src1) { + *out = __builtin_amdgcn_cvt_pknorm_i16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pknorm_u16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pknorm.u16(float %src0, float %src1) +kernel void test_cvt_pknorm_u16(global ushort2* out, float src0, float src1) { + *out = __builtin_amdgcn_cvt_pknorm_u16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pk_i16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pk.i16(i32 %src0, i32 %src1) +kernel void test_cvt_pk_i16(global short2* out, int src0, int src1) { + *out = __builtin_amdgcn_cvt_pk_i16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pk_u16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pk.u16(i32 %src0, i32 %src1) +kernel void test_cvt_pk_u16(global ushort2* out, uint src0, uint src1) { + *out = __builtin_amdgcn_cvt_pk_u16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pk_u8_f32 +// CHECK: tail call i32 @llvm.amdgcn.cvt.pk.u8.f32(float %src0, i32 %src1, i32 %src2) +kernel void test_cvt_pk_u8_f32(global uint* out, float src0, uint src1, uint src2) { + *out = __builtin_amdgcn_cvt_pk_u8_f32(src0, src1, src2); +} + // CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024} // CHECK-DAG: attributes #[[$NOUNWIND_READONLY:[0-9]+]] = { nounwind readonly } // CHECK-DAG: attributes #[[$READ_EXEC_ATTRS]] = { convergent } diff --git a/test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl b/test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl new file mode 100644 index 000000000000..75d9cd3831c5 --- /dev/null +++ b/test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx1010 -verify -S -o - %s + +typedef unsigned int uint; + + +void test_permlane16(global uint* out, uint a, uint b, uint c, uint d, uint e) { + *out = __builtin_amdgcn_permlane16(a, b, c, d, e, 1); // expected-error{{argument to '__builtin_amdgcn_permlane16' must be a constant integer}} + *out = __builtin_amdgcn_permlane16(a, b, c, d, 1, e); // expected-error{{argument to '__builtin_amdgcn_permlane16' must be a constant integer}} +} + +void test_permlanex16(global uint* out, uint a, uint b, uint c, uint d, uint e) { + *out = __builtin_amdgcn_permlanex16(a, b, c, d, e, 1); // expected-error{{argument to '__builtin_amdgcn_permlanex16' must be a constant integer}} + *out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, e); // expected-error{{argument to '__builtin_amdgcn_permlanex16' must be a constant integer}} +} + +void test_mov_dpp8(global uint* out, uint a, uint b) { + *out = __builtin_amdgcn_mov_dpp8(a, b); // expected-error{{argument to '__builtin_amdgcn_mov_dpp8' must be a constant integer}} +} diff --git a/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl b/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl new file mode 100644 index 000000000000..02c8dc8c1339 --- /dev/null +++ b/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl @@ -0,0 +1,15 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu hawaii -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu fiji -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx900 -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx908 -verify -S -o - %s + +typedef unsigned int uint; + + +void test(global uint* out, uint a, uint b, uint c, uint d) { + *out = __builtin_amdgcn_permlane16(a, b, c, d, 1, 1); // expected-error {{'__builtin_amdgcn_permlane16' needs target feature gfx10-insts}} + *out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, 1); // expected-error {{'__builtin_amdgcn_permlanex16' needs target feature gfx10-insts}} + *out = __builtin_amdgcn_mov_dpp8(a, 1); // expected-error {{'__builtin_amdgcn_mov_dpp8' needs target feature gfx10-insts}} +}