[PATCH] D53023: Prototype OpenCL BIFs using Tablegen

2018-11-01 Thread Joey Gouly via Phabricator via cfe-commits
joey updated this revision to Diff 172122.
joey added a comment.

I re-worked where the builtins are actually inserted, now it's in a similar 
place to the "normal" clang builtins.

I addressed the issue of putting the return type also into the args type (could 
rename this to signature/proto table to make it more obvious).

I'm planning to write an RFC to get buy-in from the rest of the community 
before doing too much else to the patch.


https://reviews.llvm.org/D53023

Files:
  include/clang/Basic/CMakeLists.txt
  include/clang/Basic/OpenCLBuiltins.td
  lib/Sema/SemaLookup.cpp
  test/SemaOpenCL/builtin-new.cl
  utils/TableGen/CMakeLists.txt
  utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
  utils/TableGen/TableGen.cpp
  utils/TableGen/TableGenBackends.h

Index: utils/TableGen/TableGenBackends.h
===
--- utils/TableGen/TableGenBackends.h
+++ utils/TableGen/TableGenBackends.h
@@ -78,6 +78,7 @@
 void EmitTestPragmaAttributeSupportedAttributes(llvm::RecordKeeper &Records,
 llvm::raw_ostream &OS);
 
+void EmitClangOpenCLBuiltins(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 } // end namespace clang
 
 #endif
Index: utils/TableGen/TableGen.cpp
===
--- utils/TableGen/TableGen.cpp
+++ utils/TableGen/TableGen.cpp
@@ -61,7 +61,8 @@
   GenDiagDocs,
   GenOptDocs,
   GenDataCollectors,
-  GenTestPragmaAttributeSupportedAttributes
+  GenTestPragmaAttributeSupportedAttributes,
+  GenClangOpenCLBuiltins,
 };
 
 namespace {
@@ -161,7 +162,9 @@
 clEnumValN(GenTestPragmaAttributeSupportedAttributes,
"gen-clang-test-pragma-attribute-supported-attributes",
"Generate a list of attributes supported by #pragma clang "
-   "attribute for testing purposes")));
+   "attribute for testing purposes"),
+clEnumValN(GenClangOpenCLBuiltins, "gen-clang-opencl-builtins",
+   "Generate OpenCL builtin handlers")));
 
 cl::opt
 ClangComponent("clang-component",
@@ -288,6 +291,9 @@
   case GenTestPragmaAttributeSupportedAttributes:
 EmitTestPragmaAttributeSupportedAttributes(Records, OS);
 break;
+  case GenClangOpenCLBuiltins:
+EmitClangOpenCLBuiltins(Records, OS);
+break;
   }
 
   return false;
Index: utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
===
--- /dev/null
+++ utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -0,0 +1,189 @@
+//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling
+//=-*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This tablegen backend emits Clang OpenCL Builtin checking code.
+//
+//===--===//
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+#include 
+
+using namespace llvm;
+
+namespace {
+class BuiltinNameEmitter {
+public:
+  BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS)
+  : Records(Records), OS(OS) {}
+
+  void Emit();
+
+private:
+  RecordKeeper &Records;
+  raw_ostream &OS;
+
+  void EmitDeclarations();
+  void EmitTable();
+  void GetOverloads();
+
+  MapVector>>
+  OverloadInfo;
+  std::vector, unsigned>> ArgTypesSet;
+};
+} // namespace
+
+void BuiltinNameEmitter::GetOverloads() {
+  unsigned CumulativeArgIndex = 0;
+  std::vector Builtins = Records.getAllDerivedDefinitions("Builtin");
+  for (const auto *B : Builtins) {
+StringRef BName = B->getValueAsString("name");
+
+if (OverloadInfo.find(BName) == OverloadInfo.end()) {
+  OverloadInfo.insert(std::make_pair(
+  BName, std::vector>{}));
+}
+
+auto Args = B->getValueAsListOfDefs("args");
+auto it =
+std::find_if(ArgTypesSet.begin(), ArgTypesSet.end(),
+ [&](const std::pair, unsigned> &a) {
+   return a.first == Args;
+ });
+unsigned ArgIndex;
+if (it == ArgTypesSet.end()) {
+  ArgTypesSet.push_back(std::make_pair(Args, CumulativeArgIndex));
+  ArgIndex = CumulativeArgIndex;
+  CumulativeArgIndex += Args.size();
+} else {
+  ArgIndex = it->second;
+}
+OverloadInfo[BName].push_back(std::make_pair(B, ArgIndex));
+  }
+}
+
+void B

[PATCH] D53023: Prototype OpenCL BIFs using Tablegen

2018-10-11 Thread Joey Gouly via Phabricator via cfe-commits
joey updated this revision to Diff 169182.
joey added a comment.

Re-uploading the patch. The previous version of the patch was missing the 
include and lib prefixes.


https://reviews.llvm.org/D53023

Files:
  include/clang/Basic/CMakeLists.txt
  include/clang/Basic/OpenCLBuiltins.td
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  test/SemaOpenCL/builtin-new.cl
  utils/TableGen/CMakeLists.txt
  utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
  utils/TableGen/TableGen.cpp
  utils/TableGen/TableGenBackends.h

Index: utils/TableGen/TableGenBackends.h
===
--- utils/TableGen/TableGenBackends.h
+++ utils/TableGen/TableGenBackends.h
@@ -81,6 +81,7 @@
 void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
 raw_ostream &OS);
 
+void EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS);
 } // end namespace clang
 
 #endif
Index: utils/TableGen/TableGen.cpp
===
--- utils/TableGen/TableGen.cpp
+++ utils/TableGen/TableGen.cpp
@@ -61,7 +61,8 @@
   GenDiagDocs,
   GenOptDocs,
   GenDataCollectors,
-  GenTestPragmaAttributeSupportedAttributes
+  GenTestPragmaAttributeSupportedAttributes,
+  GenClangOpenCLBuiltins,
 };
 
 namespace {
@@ -161,7 +162,9 @@
 clEnumValN(GenTestPragmaAttributeSupportedAttributes,
"gen-clang-test-pragma-attribute-supported-attributes",
"Generate a list of attributes supported by #pragma clang "
-   "attribute for testing purposes")));
+   "attribute for testing purposes"),
+clEnumValN(GenClangOpenCLBuiltins, "gen-clang-opencl-builtins",
+   "Generate OpenCL builtin handlers")));
 
 cl::opt
 ClangComponent("clang-component",
@@ -288,6 +291,9 @@
   case GenTestPragmaAttributeSupportedAttributes:
 EmitTestPragmaAttributeSupportedAttributes(Records, OS);
 break;
+  case GenClangOpenCLBuiltins:
+EmitClangOpenCLBuiltins(Records, OS);
+break;
   }
 
   return false;
Index: utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
===
--- /dev/null
+++ utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -0,0 +1,195 @@
+//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling
+//=-*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This tablegen backend emits Clang OpenCL Builtin checking code.
+//
+//===--===//
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+#include 
+
+using namespace llvm;
+
+namespace {
+class BuiltinNameEmitter {
+public:
+  BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS)
+  : Records(Records), OS(OS) {}
+
+  void Emit();
+
+private:
+  RecordKeeper &Records;
+  raw_ostream &OS;
+
+  void EmitDeclarations();
+  void EmitTable();
+  void GetOverloads();
+
+  MapVector>>
+  OverloadInfo;
+  std::vector, unsigned>> ArgTypesSet;
+};
+} // namespace
+
+void BuiltinNameEmitter::GetOverloads() {
+  unsigned CumulativeArgIndex = 0;
+  std::vector Builtins = Records.getAllDerivedDefinitions("Builtin");
+  for (const auto *B : Builtins) {
+StringRef BName = B->getValueAsString("name");
+
+if (OverloadInfo.find(BName) == OverloadInfo.end()) {
+  OverloadInfo.insert(std::make_pair(
+  BName, std::vector>{}));
+}
+
+auto Args = B->getValueAsListOfDefs("args");
+auto it =
+std::find_if(ArgTypesSet.begin(), ArgTypesSet.end(),
+ [&](const std::pair, unsigned> &a) {
+   return a.first == Args;
+ });
+unsigned ArgIndex;
+if (it == ArgTypesSet.end()) {
+  ArgTypesSet.push_back(std::make_pair(Args, CumulativeArgIndex));
+  ArgIndex = CumulativeArgIndex;
+  CumulativeArgIndex += Args.size();
+} else {
+  ArgIndex = it->second;
+}
+OverloadInfo[BName].push_back(std::make_pair(B, ArgIndex));
+  }
+}
+
+void BuiltinNameEmitter::EmitDeclarations() {
+  OS << "enum OpenCLTypeID {\n";
+  std::vector Types = Records.getAllDerivedDefinitions("Type");
+  StringMap TypesSeen;
+  for (const auto *T : Types) {
+if (TypesSeen.find(T->getValueAsString("name")) == TypesSeen.end())
+  OS

[PATCH] D53023: Prototype OpenCL BIFs using Tablegen

2018-10-09 Thread Joey Gouly via Phabricator via cfe-commits
joey created this revision.
joey added reviewers: asavonic, Anastasia.
Herald added subscribers: cfe-commits, yaxunl, mgorny.

This is the prototype for the approach that was mentioned by Anastasia in 
http://lists.llvm.org/pipermail/cfe-dev/2018-September/059529.html

The tablegen file describes the BIFs and all their overloads, in hopefully a 
concise manner.

There are 3 things generated from the OpenCLBuiltins.td file.

1. OpenCLArgTypes[], this is a table containing all the different types of 
overloads. This is a separate table so it can be shared by the BIFs.
2. OpenCLBuiltins[], this is a table that contains all the overloads for the 
BIFs.
3. isOpenCLBuiltin, this is a function that uses a trie-like switch/case to 
determine if a StringRef is the name of a BIF.

Just a quick snippet of the above:

  OpenCLType OpenCLArgTypes[] = {
  // 0
  { OCLT_float, 0, 0, clang::LangAS::Default, },
  // 1
  { OCLT_float, 2, 0, clang::LangAS::Default, },

  OpenCLBuiltinDecl OpenCLBuiltins[] = {
  // acos
{ { OCLT_float, 0, 0, clang::LangAS::Default, }, 1, 0, "", 100,  },
{ { OCLT_float, 2, 0, clang::LangAS::Default, }, 1, 1, "", 100,  },

  std::pair isOpenCLBuiltin(llvm::StringRef name) {
switch (name.size()) {
default: break;
case 3:  // 1 string to match.
  if (memcmp(name.data()+0, "foo", 3) != 0)
break;
  return std::make_pair(707, 2);   // "foo"

While it's a prototype, I have tried to keep it as clean as possible.

TODO:

1. Bit-pack the tables to reduce the size.
2. Include the return type in the ArgTypes table to reduce the size.
3. Measure the performance / size impact
4. Auto-generate parts of OCL2Qual, to reduce repeated typing
5. OCL2Qual does not support pointers-to-pointers currently, but I believe no 
BIFs use that.
6. InsertBuiltinDeclarations builds up an AST function declaration manually, 
perhaps there is a helper function for this.
7. There is a FIXME in SemaDecl.cpp that needs to be implemented.


Repository:
  rC Clang

https://reviews.llvm.org/D53023

Files:
  Sema/SemaDecl.cpp
  Sema/SemaExpr.cpp
  SemaOpenCL/builtin-new.cl
  TableGen/CMakeLists.txt
  TableGen/ClangOpenCLBuiltinEmitter.cpp
  TableGen/TableGen.cpp
  TableGen/TableGenBackends.h
  clang/Basic/CMakeLists.txt
  clang/Basic/OpenCLBuiltins.td

Index: TableGen/TableGenBackends.h
===
--- TableGen/TableGenBackends.h
+++ TableGen/TableGenBackends.h
@@ -81,6 +81,7 @@
 void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
 raw_ostream &OS);
 
+void EmitClangOpenCLBuiltins(RecordKeeper &Records, raw_ostream &OS);
 } // end namespace clang
 
 #endif
Index: TableGen/TableGen.cpp
===
--- TableGen/TableGen.cpp
+++ TableGen/TableGen.cpp
@@ -61,7 +61,8 @@
   GenDiagDocs,
   GenOptDocs,
   GenDataCollectors,
-  GenTestPragmaAttributeSupportedAttributes
+  GenTestPragmaAttributeSupportedAttributes,
+  GenClangOpenCLBuiltins,
 };
 
 namespace {
@@ -161,7 +162,9 @@
 clEnumValN(GenTestPragmaAttributeSupportedAttributes,
"gen-clang-test-pragma-attribute-supported-attributes",
"Generate a list of attributes supported by #pragma clang "
-   "attribute for testing purposes")));
+   "attribute for testing purposes"),
+clEnumValN(GenClangOpenCLBuiltins, "gen-clang-opencl-builtins",
+   "Generate OpenCL builtin handlers")));
 
 cl::opt
 ClangComponent("clang-component",
@@ -288,6 +291,9 @@
   case GenTestPragmaAttributeSupportedAttributes:
 EmitTestPragmaAttributeSupportedAttributes(Records, OS);
 break;
+  case GenClangOpenCLBuiltins:
+EmitClangOpenCLBuiltins(Records, OS);
+break;
   }
 
   return false;
Index: TableGen/ClangOpenCLBuiltinEmitter.cpp
===
--- /dev/null
+++ TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -0,0 +1,195 @@
+//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling
+//=-*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This tablegen backend emits Clang OpenCL Builtin checking code.
+//
+//===--===//
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm

[PATCH] D33945: [OpenCL] Add support for missing sub_group functions.

2017-08-09 Thread Joey Gouly via Phabricator via cfe-commits
joey closed this revision.
joey added a comment.

I committed all the parts separately:  r309567 (with r309571 to fix a test), 
r309678 and r310477.


https://reviews.llvm.org/D33945



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33945: [OpenCL] Add support for missing sub_group functions.

2017-07-27 Thread Joey Gouly via Phabricator via cfe-commits
joey updated this revision to Diff 108452.
joey added a comment.

Updated all the comments you made and rebased.

Sorry for the long delay.


https://reviews.llvm.org/D33945

Files:
  CodeGen/CGBuiltin.cpp
  CodeGenOpenCL/cl20-device-side-enqueue.cl
  CodeGenOpenCL/pipe_builtin.cl
  Sema/SemaChecking.cpp
  SemaOpenCL/cl20-device-side-enqueue.cl
  SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
  clang/Basic/Builtins.def

Index: SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
===
--- SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
+++ SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
 
+#pragma OPENCL EXTENSION cl_khr_subgroups : enable
+
 void test1(read_only pipe int p, global int* ptr){
   int tmp;
   reserve_id_t rid;
Index: SemaOpenCL/cl20-device-side-enqueue.cl
===
--- SemaOpenCL/cl20-device-side-enqueue.cl
+++ SemaOpenCL/cl20-device-side-enqueue.cl
@@ -209,3 +209,35 @@
   size = get_kernel_preferred_work_group_size_multiple(1); // expected-error{{expected block argument}}
   size = get_kernel_preferred_work_group_size_multiple(block_A, 1); // expected-error{{too many arguments to function call, expected 1, have 2}}
 }
+
+#pragma OPENCL EXTENSION cl_khr_subgroups : enable
+
+kernel void foo(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){});
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(0, ^(){}); // expected-error{{illegal call to 'get_kernel_max_sub_group_size_for_ndrange', expected 'ndrange_t' argument type}}
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, 1); // expected-error{{illegal call to 'get_kernel_max_sub_group_size_for_ndrange', expected block argument type}}
+}
+
+kernel void bar(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){});
+  buf[0] = get_kernel_sub_group_count_for_ndrange(0, ^(){}); // expected-error{{illegal call to 'get_kernel_sub_group_count_for_ndrange', expected 'ndrange_t' argument type}}
+  buf[0] = get_kernel_sub_group_count_for_ndrange(n, 1); // expected-error{{illegal call to 'get_kernel_sub_group_count_for_ndrange', expected block argument type}}
+}
+
+#pragma OPENCL EXTENSION cl_khr_subgroups : disable
+
+kernel void foo1(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_max_sub_group_size_for_ndrange' requires cl_khr_subgroups extension to be enabled}}
+}
+
+kernel void bar1(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_sub_group_count_for_ndrange' requires cl_khr_subgroups extension to be enabled}}
+}
Index: CodeGenOpenCL/pipe_builtin.cl
===
--- CodeGenOpenCL/pipe_builtin.cl
+++ CodeGenOpenCL/pipe_builtin.cl
@@ -3,6 +3,8 @@
 // CHECK: %opencl.pipe_t = type opaque
 // CHECK: %opencl.reserve_id_t = type opaque
 
+#pragma OPENCL EXTENSION cl_khr_subgroups : enable
+
 void test1(read_only pipe int p, global int *ptr) {
   // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
   read_pipe(p, ptr);
Index: CodeGenOpenCL/cl20-device-side-enqueue.cl
===
--- CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - -triple "spir-unknown-unknown" | FileCheck %s --check-prefix=COMMON --check-prefix=B32
 // RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" | FileCheck %s --check-prefix=COMMON --check-prefix=B64
 
+#pragma OPENCL EXTENSION cl_khr_subgroups : enable
+
 typedef void (^bl_t)(local void *);
 typedef struct {int a;} ndrange_t;
 
@@ -138,4 +140,9 @@
   size = get_kernel_preferred_work_group_size_multiple(block_A);
   // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
   size = get_kernel_preferred_work_group_size_multiple(block_G);
+
+  // COMMON: call i32 @__get_kernel_max_sub_group_size_for_ndrange_impl(%struct.ndrange_t* {{.*}}, i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* } addrspace(1)* {{.*}} to i8 addrspace(1)*) to i8 addrspace(4)*))
+  size = get_kernel_max_sub_group_size_for_ndrange(ndrange, ^(){});
+  // COMMON: call i32 @__get_kernel_sub_group_count_for_ndrange_impl(%struct.ndrange_t* {{.*}}, i8 addrspace(4)* addrspacecast (i8 addrs

[PATCH] D34948: [OpenCL] Generalise err_opencl_enqueue_kernel_expected_type to be used with other builtins

2017-07-03 Thread Joey Gouly via Phabricator via cfe-commits
joey added a comment.

In https://reviews.llvm.org/D34948#798332, @bader wrote:

> LGTM.
>  Do you have another built-in in mind which can use this diagnostic message?
>  If so, it would make sense to re-use it in the same patch.


This is split off from https://reviews.llvm.org/D33945, which I will be 
rebasing/re-uploading once this patch is committed.


https://reviews.llvm.org/D34948



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D34948: [OpenCL] Generalise err_opencl_enqueue_kernel_expected_type to be used with other builtins

2017-07-03 Thread Joey Gouly via Phabricator via cfe-commits
joey created this revision.
Herald added subscribers: Anastasia, yaxunl.

Refactor err_opencl_enqueue_kernel_expected_type so that other builtins can use 
the same diagnostic.


https://reviews.llvm.org/D34948

Files:
  Sema/SemaChecking.cpp
  SemaOpenCL/cl20-device-side-enqueue.cl
  clang/Basic/DiagnosticSemaKinds.td

Index: SemaOpenCL/cl20-device-side-enqueue.cl
===
--- SemaOpenCL/cl20-device-side-enqueue.cl
+++ SemaOpenCL/cl20-device-side-enqueue.cl
@@ -19,19 +19,19 @@
 return 0;
   });
 
-  enqueue_kernel(vptr, flags, ndrange, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected 'queue_t' argument type}}
+  enqueue_kernel(vptr, flags, ndrange, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected 'queue_t' argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, vptr, ndrange, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected 'kernel_enqueue_flags_t' (i.e. uint) argument type}}
+  enqueue_kernel(default_queue, vptr, ndrange, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected 'kernel_enqueue_flags_t' (i.e. uint) argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, flags, vptr, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected 'ndrange_t' argument type}}
+  enqueue_kernel(default_queue, flags, vptr, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected 'ndrange_t' argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, flags, ndrange, vptr); // expected-error{{illegal call to enqueue_kernel, expected block argument}}
+  enqueue_kernel(default_queue, flags, ndrange, vptr); // expected-error{{illegal call to 'enqueue_kernel', expected block argument}}
 
   enqueue_kernel(default_queue, flags, ndrange, ^(int i) { // expected-error{{blocks with parameters are not accepted in this prototype of enqueue_kernel call}}
 return 0;
@@ -46,21 +46,21 @@
return 0;
  });
 
-  enqueue_kernel(default_queue, flags, ndrange, vptr, &event_wait_list, &evt, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected integer argument type}}
+  enqueue_kernel(default_queue, flags, ndrange, vptr, &event_wait_list, &evt, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected integer argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, flags, ndrange, 1, vptr, &evt, ^(void) // expected-error{{illegal call to enqueue_kernel, expected 'clk_event_t *' argument type}}
+  enqueue_kernel(default_queue, flags, ndrange, 1, vptr, &evt, ^(void) // expected-error{{illegal call to 'enqueue_kernel', expected 'clk_event_t *' argument type}}
{
  return 0;
});
 
-  enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, vptr, ^(void) // expected-error{{illegal call to enqueue_kernel, expected 'clk_event_t *' argument type}}
+  enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, vptr, ^(void) // expected-error{{illegal call to 'enqueue_kernel', expected 'clk_event_t *' argument type}}
{
  return 0;
});
 
-  enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, &evt, vptr); // expected-error{{illegal call to enqueue_kernel, expected block argument}}
+  enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, &evt, vptr); // expected-error{{illegal call to 'enqueue_kernel', expected block argument}}
 
   // Testing the third overload type
   enqueue_kernel(default_queue, flags, ndrange,
Index: Sema/SemaChecking.cpp
===
--- Sema/SemaChecking.cpp
+++ Sema/SemaChecking.cpp
@@ -309,7 +309,8 @@
   Expr *BlockArg = TheCall->getArg(0);
   if (!isBlockPointer(BlockArg)) {
 S.Diag(BlockArg->getLocStart(),
-   diag::err_opencl_enqueue_kernel_expected_type) << "block";
+   diag::err_opencl_builtin_expected_type)
+<< TheCall->getDirectCallee() << "block";
 return true;
   }
   return checkOpenCLBlockArgs(S, BlockArg);
@@ -394,34 +395,34 @@
   // First argument always needs to be a queue_t type.
   if (!Arg0->getType()->isQueueT()) {
 S.Diag(TheCall->getArg(0)->getLocStart(),
-   diag::err_opencl_enqueue_kernel_expected_type)
-<< S.Context.OCLQueueTy;
+   diag::err_opencl_builtin_expected_type)
+<< TheCall->getDirectCallee() << S.Context.OCLQueueTy;
 return true;
   }
 
   /

[PATCH] D34871: [OpenCL] Add function name to extension diagnostic

2017-06-30 Thread Joey Gouly via Phabricator via cfe-commits
joey added a comment.

Thanks!

Making that change, going to re-run the tests and then I'll commit.


https://reviews.llvm.org/D34871



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D34871: [OpenCL] Add function name to extension diagnostic

2017-06-30 Thread Joey Gouly via Phabricator via cfe-commits
joey created this revision.
Herald added subscribers: Anastasia, yaxunl.

Slightly improve the diagnostic by including the function name.

This has been separated out from https://reviews.llvm.org/D33945.


https://reviews.llvm.org/D34871

Files:
  Sema/Sema.cpp
  SemaOpenCL/extension-begin.cl
  clang/Basic/DiagnosticSemaKinds.td
  clang/Sema/Sema.h


Index: SemaOpenCL/extension-begin.cl
===
--- SemaOpenCL/extension-begin.cl
+++ SemaOpenCL/extension-begin.cl
@@ -46,7 +46,7 @@
   const struct A test_A_local; // expected-error {{use of type 'struct A' 
requires my_ext extension to be enabled}}
   TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 
'struct A') requires my_ext extension to be enabled}}
   PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 
'const struct A *') requires my_ext extension to be enabled}}
-  f(); // expected-error {{use of declaration requires my_ext extension to be 
enabled}}
+  f(); // expected-error {{use of declaration 'f' requires my_ext extension to 
be enabled}}
   g(0); // expected-error {{no matching function for call to 'g'}}
 // expected-note@-26 {{candidate disabled due to OpenCL extension}}
 // expected-note@-22 {{candidate function not viable: requires 0 
arguments, but 1 was provided}}
Index: Sema/Sema.cpp
===
--- Sema/Sema.cpp
+++ Sema/Sema.cpp
@@ -1688,7 +1688,8 @@
QT, OpenCLTypeExtMap);
 }
 
-bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
-  return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
+bool Sema::checkOpenCLDisabledDecl(const FunctionDecl &D, const Expr &E) {
+  IdentifierInfo *FnName = D.getIdentifier();
+  return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName,
OpenCLDeclExtMap, 1, 
D.getSourceRange());
 }
Index: clang/Sema/Sema.h
===
--- clang/Sema/Sema.h
+++ clang/Sema/Sema.h
@@ -8432,7 +8432,7 @@
   /// is disabled due to required OpenCL extensions being disabled. If so,
   /// emit diagnostics.
   /// \return true if type is disabled.
-  bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E);
+  bool checkOpenCLDisabledDecl(const FunctionDecl &D, const Expr &E);
 
   
//======//
   // OpenMP directives and clauses.
Index: clang/Basic/DiagnosticSemaKinds.td
===
--- clang/Basic/DiagnosticSemaKinds.td
+++ clang/Basic/DiagnosticSemaKinds.td
@@ -8404,7 +8404,7 @@
 def err_opencl_variadic_function : Error<
   "invalid prototype, variadic arguments are not allowed in OpenCL">;
 def err_opencl_requires_extension : Error<
-  "use of %select{type |declaration}0%1 requires %2 extension to be enabled">;
+  "use of %select{type|declaration}0 %1 requires %2 extension to be enabled">;
 
 // OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
 def err_opencl_builtin_pipe_first_arg : Error<


Index: SemaOpenCL/extension-begin.cl
===
--- SemaOpenCL/extension-begin.cl
+++ SemaOpenCL/extension-begin.cl
@@ -46,7 +46,7 @@
   const struct A test_A_local; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
   TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 'struct A') requires my_ext extension to be enabled}}
   PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}}
-  f(); // expected-error {{use of declaration requires my_ext extension to be enabled}}
+  f(); // expected-error {{use of declaration 'f' requires my_ext extension to be enabled}}
   g(0); // expected-error {{no matching function for call to 'g'}}
 // expected-note@-26 {{candidate disabled due to OpenCL extension}}
 // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
Index: Sema/Sema.cpp
===
--- Sema/Sema.cpp
+++ Sema/Sema.cpp
@@ -1688,7 +1688,8 @@
QT, OpenCLTypeExtMap);
 }
 
-bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
-  return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
+bool Sema::checkOpenCLDisabledDecl(const FunctionDecl &D, const Expr &E) {
+  IdentifierInfo *FnName = D.getIdentifier();
+  return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName,
OpenCLDeclExtMap, 1, D.getSourceRange());
 }
Index: clang/Sema/Sema.h
===
--- clang/Sema/Sema.h
+++ clang/Sema/Sema.h
@@ -8432,7 +8432,7 @@
   /// i

[PATCH] D33945: [OpenCL] Add support for missing sub_group functions.

2017-06-06 Thread Joey Gouly via Phabricator via cfe-commits
joey created this revision.
Herald added subscribers: Anastasia, yaxunl.

This adds get_kernel_max_sub_group_size_for_ndrange and 
get_kernel_sub_group_count_for_ndrange.

Note this also changes err_opencl_requires_extension to print the name of the 
function that the diagnostic is warning about.


https://reviews.llvm.org/D33945

Files:
  CodeGen/CGBuiltin.cpp
  CodeGenOpenCL/cl20-device-side-enqueue.cl
  CodeGenOpenCL/pipe_builtin.cl
  Sema/Sema.cpp
  Sema/SemaChecking.cpp
  SemaOpenCL/cl20-device-side-enqueue.cl
  SemaOpenCL/extension-begin.cl
  SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
  SemaOpenCL/sub-group-bifs.cl
  clang/Basic/Builtins.def
  clang/Basic/DiagnosticSemaKinds.td
  clang/Sema/Sema.h

Index: SemaOpenCL/sub-group-bifs.cl
===
--- /dev/null
+++ SemaOpenCL/sub-group-bifs.cl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0
+
+#pragma OPENCL EXTENSION cl_khr_subgroups : enable
+
+typedef struct {} ndrange_t;
+
+kernel void foo(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){});
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(0, ^(){}); // expected-error{{illegal call to 'get_kernel_max_sub_group_size_for_ndrange', expected 'ndrange_t' argument type}}
+}
+
+kernel void bar(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){});
+  buf[0] = get_kernel_sub_group_count_for_ndrange(0, ^(){}); // expected-error{{illegal call to 'get_kernel_sub_group_count_for_ndrange', expected 'ndrange_t' argument type}}
+}
+
+#pragma OPENCL EXTENSION cl_khr_subgroups : disable
+
+kernel void foo1(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_max_sub_group_size_for_ndrange' requires cl_khr_subgroups extension to be enabled}}
+}
+
+kernel void bar1(global int *buf)
+{
+  ndrange_t n;
+  buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_sub_group_count_for_ndrange' requires cl_khr_subgroups extension to be enabled}}
+}
Index: SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
===
--- SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
+++ SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
 
+#pragma OPENCL EXTENSION cl_khr_subgroups : enable
+
 void test1(read_only pipe int p, global int* ptr){
   int tmp;
   reserve_id_t rid;
Index: SemaOpenCL/extension-begin.cl
===
--- SemaOpenCL/extension-begin.cl
+++ SemaOpenCL/extension-begin.cl
@@ -46,7 +46,7 @@
   const struct A test_A_local; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
   TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 'struct A') requires my_ext extension to be enabled}}
   PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}}
-  f(); // expected-error {{use of declaration requires my_ext extension to be enabled}}
+  f(); // expected-error {{use of declaration 'f' requires my_ext extension to be enabled}}
   g(0); // expected-error {{no matching function for call to 'g'}}
 // expected-note@-26 {{candidate disabled due to OpenCL extension}}
 // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
Index: SemaOpenCL/cl20-device-side-enqueue.cl
===
--- SemaOpenCL/cl20-device-side-enqueue.cl
+++ SemaOpenCL/cl20-device-side-enqueue.cl
@@ -19,19 +19,19 @@
 return 0;
   });
 
-  enqueue_kernel(vptr, flags, ndrange, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected 'queue_t' argument type}}
+  enqueue_kernel(vptr, flags, ndrange, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected 'queue_t' argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, vptr, ndrange, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected 'kernel_enqueue_flags_t' (i.e. uint) argument type}}
+  enqueue_kernel(default_queue, vptr, ndrange, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected 'kernel_enqueue_flags_t' (i.e. uint) argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, flags, vptr, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected 'ndrange_t' argument type}}
+  enqueue_kernel(default_queue, flags, vptr, ^(void) { // expected-error{{illegal call to 'enqueue_kernel', expected 'ndrange_t' argument type}}
 return 0;
   });
 
-  enqueue_kernel(default_queue, flags, ndrange, vptr); // expected-error{{illegal call to enqueue_kernel, expected block argument}}

[PATCH] D29718: [libclang] [OpenCL] Expose half type

2017-02-10 Thread Joey Gouly via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL294754: [libclang] [OpenCL] Expose half type. (authored by 
joey).

Changed prior to commit:
  https://reviews.llvm.org/D29718?vs=87654&id=88002#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D29718

Files:
  cfe/trunk/bindings/python/clang/cindex.py
  cfe/trunk/include/clang-c/Index.h
  cfe/trunk/test/Index/opencl-types.cl
  cfe/trunk/tools/libclang/CXType.cpp


Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -3011,8 +3011,9 @@
   CXType_ObjCClass = 28,
   CXType_ObjCSel = 29,
   CXType_Float128 = 30,
+  CXType_Half = 31,
   CXType_FirstBuiltin = CXType_Void,
-  CXType_LastBuiltin  = CXType_ObjCSel,
+  CXType_LastBuiltin  = CXType_Half,
 
   CXType_Complex = 100,
   CXType_Pointer = 101,
Index: cfe/trunk/test/Index/opencl-types.cl
===
--- cfe/trunk/test/Index/opencl-types.cl
+++ cfe/trunk/test/Index/opencl-types.cl
@@ -0,0 +1,24 @@
+// RUN: c-index-test -test-print-type %s | FileCheck %s
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+typedef half half4 __attribute__((ext_vector_type(4)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+
+void kernel testFloatTypes() {
+  half scalarHalf;
+  half4 vectorHalf;
+  float scalarFloat;
+  float4 vectorFloat;
+  double scalarDouble;
+  double4 vectorDouble;
+}
+
+// CHECK: VarDecl=scalarHalf:11:8 (Definition) [type=half] [typekind=Half] 
[isPOD=1]
+// CHECK: VarDecl=vectorHalf:12:9 (Definition) [type=half4] [typekind=Typedef] 
[canonicaltype=half __attribute__((ext_vector_type(4)))] 
[canonicaltypekind=Unexposed] [isPOD=1]
+// CHECK: VarDecl=scalarFloat:13:9 (Definition) [type=float] [typekind=Float] 
[isPOD=1]
+// CHECK: VarDecl=vectorFloat:14:10 (Definition) [type=float4] 
[typekind=Typedef] [canonicaltype=float __attribute__((ext_vector_type(4)))] 
[canonicaltypekind=Unexposed] [isPOD=1]
+// CHECK: VarDecl=scalarDouble:15:10 (Definition) [type=double] 
[typekind=Double] [isPOD=1]
+// CHECK: VarDecl=vectorDouble:16:11 (Definition) [type=double4] 
[typekind=Typedef] [canonicaltype=double __attribute__((ext_vector_type(4)))] 
[canonicaltypekind=Unexposed] [isPOD=1]
Index: cfe/trunk/tools/libclang/CXType.cpp
===
--- cfe/trunk/tools/libclang/CXType.cpp
+++ cfe/trunk/tools/libclang/CXType.cpp
@@ -48,6 +48,7 @@
 BTCASE(Long);
 BTCASE(LongLong);
 BTCASE(Int128);
+BTCASE(Half);
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
@@ -503,6 +504,7 @@
 TKIND(Long);
 TKIND(LongLong);
 TKIND(Int128);
+TKIND(Half);
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
Index: cfe/trunk/bindings/python/clang/cindex.py
===
--- cfe/trunk/bindings/python/clang/cindex.py
+++ cfe/trunk/bindings/python/clang/cindex.py
@@ -1887,6 +1887,7 @@
 TypeKind.OBJCCLASS = TypeKind(28)
 TypeKind.OBJCSEL = TypeKind(29)
 TypeKind.FLOAT128 = TypeKind(30)
+TypeKind.HALF = TypeKind(31)
 TypeKind.COMPLEX = TypeKind(100)
 TypeKind.POINTER = TypeKind(101)
 TypeKind.BLOCKPOINTER = TypeKind(102)


Index: cfe/trunk/include/clang-c/Index.h
===
--- cfe/trunk/include/clang-c/Index.h
+++ cfe/trunk/include/clang-c/Index.h
@@ -3011,8 +3011,9 @@
   CXType_ObjCClass = 28,
   CXType_ObjCSel = 29,
   CXType_Float128 = 30,
+  CXType_Half = 31,
   CXType_FirstBuiltin = CXType_Void,
-  CXType_LastBuiltin  = CXType_ObjCSel,
+  CXType_LastBuiltin  = CXType_Half,
 
   CXType_Complex = 100,
   CXType_Pointer = 101,
Index: cfe/trunk/test/Index/opencl-types.cl
===
--- cfe/trunk/test/Index/opencl-types.cl
+++ cfe/trunk/test/Index/opencl-types.cl
@@ -0,0 +1,24 @@
+// RUN: c-index-test -test-print-type %s | FileCheck %s
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+typedef half half4 __attribute__((ext_vector_type(4)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+
+void kernel testFloatTypes() {
+  half scalarHalf;
+  half4 vectorHalf;
+  float scalarFloat;
+  float4 vectorFloat;
+  double scalarDouble;
+  double4 vectorDouble;
+}
+
+// CHECK: VarDecl=scalarHalf:11:8 (Definition) [type=half] [typekind=Half] [isPOD=1]
+// CHECK: VarDecl=vectorHalf:12:9 (Definition) [type=half4] [typekind=Typedef] [canonicaltype=half __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
+// CHECK: VarDecl=scalarFloat:13:9 (Definition) [type=float] [typekind=Float] [isPO

[PATCH] D27049: [OpenCL] Refactor out ReadPipe/WritePipe

2016-12-01 Thread Joey Gouly via Phabricator via cfe-commits
joey closed this revision.
joey added a comment.

Committed in r288332. Thanks Yaron!


Repository:
  rL LLVM

https://reviews.llvm.org/D27049



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27049: [OpenCL] Refactor out ReadPipe/WritePipe

2016-11-28 Thread Joey Gouly via Phabricator via cfe-commits
joey updated this revision to Diff 79399.
joey added a comment.

Pipe types cannot be merged by ASTContext::mergeTypes.


Repository:
  rL LLVM

https://reviews.llvm.org/D27049

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Type.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/SemaOpenCL/invalid-pipes-cl2.0.cl

Index: test/SemaOpenCL/invalid-pipes-cl2.0.cl
===
--- test/SemaOpenCL/invalid-pipes-cl2.0.cl
+++ test/SemaOpenCL/invalid-pipes-cl2.0.cl
@@ -20,3 +20,12 @@
 
 typedef pipe int pipe_int_t;
 pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'read_only pipe int') is not allowed}}
+
+// Tests ASTContext::mergeTypes rejects this.
+int f(pipe int x, int y);
+int f(x, y)
+pipe short x;
+int y;
+{
+return y;
+}
Index: lib/Serialization/ASTWriter.cpp
===
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -516,10 +516,8 @@
 void
 ASTTypeWriter::VisitPipeType(const PipeType *T) {
   Record.AddTypeRef(T->getElementType());
-  if (T->isReadOnly())
-Code = TYPE_READ_PIPE;
-  else
-Code = TYPE_WRITE_PIPE;
+  Record.push_back(T->isReadOnly());
+  Code = TYPE_PIPE;
 }
 
 namespace {
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -5793,27 +5793,21 @@
 return Context.getAtomicType(ValueType);
   }
 
-  case TYPE_READ_PIPE: {
-if (Record.size() != 1) {
+  case TYPE_PIPE: {
+if (Record.size() != 2) {
   Error("Incorrect encoding of pipe type");
   return QualType();
 }
 
 // Reading the pipe element type.
 QualType ElementType = readType(*Loc.F, Record, Idx);
-return Context.getReadPipeType(ElementType);
+unsigned ReadOnly = Record[1];
+if (ReadOnly)
+  return Context.getReadPipeType(ElementType);
+else
+  return Context.getWritePipeType(ElementType);
   }
 
-  case TYPE_WRITE_PIPE: {
-if (Record.size() != 1) {
-  Error("Incorrect encoding of pipe type");
-  return QualType();
-}
-
-// Reading the pipe element type.
-QualType ElementType = readType(*Loc.F, Record, Idx);
-return Context.getWritePipeType(ElementType);
-  }
   }
   llvm_unreachable("Invalid TypeCode!");
 }
Index: lib/AST/ASTContext.cpp
===
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -3338,54 +3338,37 @@
   return QualType(FTP, 0);
 }
 
-QualType ASTContext::getReadPipeType(QualType T) const {
+QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const {
   llvm::FoldingSetNodeID ID;
-  ReadPipeType::Profile(ID, T);
+  PipeType::Profile(ID, T, ReadOnly);
 
   void *InsertPos = 0;
-  if (ReadPipeType *PT = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos))
+  if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
 return QualType(PT, 0);
 
   // If the pipe element type isn't canonical, this won't be a canonical type
   // either, so fill in the canonical type field.
   QualType Canonical;
   if (!T.isCanonical()) {
-Canonical = getReadPipeType(getCanonicalType(T));
+Canonical = getPipeType(getCanonicalType(T), ReadOnly);
 
 // Get the new insert position for the node we care about.
-ReadPipeType *NewIP = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos);
+PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
 assert(!NewIP && "Shouldn't be in the map!");
 (void)NewIP;
   }
-  ReadPipeType *New = new (*this, TypeAlignment) ReadPipeType(T, Canonical);
+  PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly);
   Types.push_back(New);
-  ReadPipeTypes.InsertNode(New, InsertPos);
+  PipeTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
 }
 
-QualType ASTContext::getWritePipeType(QualType T) const {
-  llvm::FoldingSetNodeID ID;
-  WritePipeType::Profile(ID, T);
-
-  void *InsertPos = 0;
-  if (WritePipeType *PT = WritePipeTypes.FindNodeOrInsertPos(ID, InsertPos))
-return QualType(PT, 0);
-
-  // If the pipe element type isn't canonical, this won't be a canonical type
-  // either, so fill in the canonical type field.
-  QualType Canonical;
-  if (!T.isCanonical()) {
-Canonical = getWritePipeType(getCanonicalType(T));
+QualType ASTContext::getReadPipeType(QualType T) const {
+  return getPipeType(T, true);
+}
 
-// Get the new insert position for the node we care about.
-WritePipeType *NewIP = WritePipeTypes.FindNodeOrInsertPos(ID, InsertPos);
-assert(!NewIP && "Shouldn't be in the map!");
-(void)NewIP;
-  }
-  WritePipeType *New = new (*this, TypeAlignment) WritePipeType(T, Canonical);
-  Types.push_back(New);
-  WritePipeTypes.InsertNode(New