[AMDGPU] Transform __read_pipe_* and __write_pipe_*

When packet size equals packet align and is power of 2, transform
__read_pipe* and __write_pipe* to specialized library function.

Differential Revision: https://reviews.llvm.org/D36831

llvm-svn: 312598
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibFunc.h b/llvm/lib/Target/AMDGPU/AMDGPULibFunc.h
index bb8724a..8f4297b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULibFunc.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPULibFunc.h
@@ -18,7 +18,7 @@
 class Function;
 class Module;
 
-class AMDGPULibFunc {
+class AMDGPULibFuncBase {
 public:
   enum EFuncId {
     EI_NONE,
@@ -26,6 +26,14 @@
     // IMPORTANT: enums below should go in ascending by 1 value order
     // because they are used as indexes in the mangling rules table.
     // don't use explicit value assignment.
+    //
+    // There are two types of library functions: those with mangled
+    // name and those with unmangled name. The enums for the library
+    // functions with mangled name are defined before enums for the
+    // library functions with unmangled name. The enum for the last
+    // library function with mangled name is EI_LAST_MANGLED.
+    //
+    // Library functions with mangled name.
     EI_ABS,
     EI_ABS_DIFF,
     EI_ACOS,
@@ -144,7 +152,6 @@
     EI_POWR,
     EI_PREFETCH,
     EI_RADIANS,
-    EI_READ_PIPE,
     EI_RECIP,
     EI_REMAINDER,
     EI_REMQUO,
@@ -212,7 +219,6 @@
     EI_WRITE_IMAGEF,
     EI_WRITE_IMAGEI,
     EI_WRITE_IMAGEUI,
-    EI_WRITE_PIPE,
     EI_NCOS,
     EI_NEXP2,
     EI_NFMA,
@@ -225,6 +231,14 @@
     EI_FLDEXP,
     EI_CLASS,
     EI_RCBRT,
+    EI_LAST_MANGLED =
+        EI_RCBRT, /* The last library function with mangled name */
+
+    // Library functions with unmangled name.
+    EI_READ_PIPE_2,
+    EI_READ_PIPE_4,
+    EI_WRITE_PIPE_2,
+    EI_WRITE_PIPE_4,
 
     EX_INTRINSICS_COUNT
   };
@@ -298,51 +312,144 @@
     template <typename Stream>
     void mangleItanium(Stream& os);
   };
-
-public:
-  static bool      parse(StringRef mangledName, AMDGPULibFunc &iInfo);
-
-  AMDGPULibFunc();
-  AMDGPULibFunc(EFuncId id, const AMDGPULibFunc& copyFrom);
-
-  ENamePrefix   getPrefix() const { return FKind; }
-  EFuncId  getId() const { return FuncId; }
-
-  std::string   getName() const;
-  unsigned      getNumArgs() const;
-
-  FunctionType* getFunctionType(Module& M) const;
-
-  std::string   mangle() const;
-
-  void setPrefix(ENamePrefix pfx) { FKind = pfx; }
-  void setId(EFuncId id) { FuncId = id; }
-
-  static Function* getFunction(llvm::Module *M, const AMDGPULibFunc& fInfo);
-
-  static Function* getOrInsertFunction(llvm::Module *M,
-                                       const AMDGPULibFunc& fInfo);
-
-  static StringRef getUnmangledName(const StringRef& mangledName);
-
-  Param         Leads[2];
-
-private:
-  EFuncId       FuncId;
-  ENamePrefix   FKind;
-  std::string   Name;
-
-  void          reset();
-
-  std::string   mangleNameItanium() const;
-  bool          parseItanuimName(StringRef& mangledName);
-
-  std::string   mangleName(const StringRef& name) const;
-  bool          parseName(const StringRef& mangledName);
-
-  template <typename Stream>
-  void          writeName(Stream& OS) const;
+  static bool isMangled(EFuncId Id) {
+    return static_cast<unsigned>(Id) <= static_cast<unsigned>(EI_LAST_MANGLED);
+  }
 };
 
+class AMDGPULibFuncImpl : public AMDGPULibFuncBase {
+public:
+  AMDGPULibFuncImpl() {}
+  virtual ~AMDGPULibFuncImpl() {}
+
+  /// Get unmangled name for mangled library function and name for unmangled
+  /// library function.
+  virtual std::string getName() const = 0;
+  virtual unsigned getNumArgs() const = 0;
+  EFuncId getId() const { return FuncId; }
+  ENamePrefix getPrefix() const { return FKind; }
+
+  bool isMangled() const { return AMDGPULibFuncBase::isMangled(FuncId); }
+
+  void setId(EFuncId id) { FuncId = id; }
+  virtual bool parseFuncName(StringRef &mangledName) = 0;
+
+  /// \return The mangled function name for mangled library functions
+  /// and unmangled function name for unmangled library functions.
+  virtual std::string mangle() const = 0;
+
+  void setName(StringRef N) { Name = N; }
+  void setPrefix(ENamePrefix pfx) { FKind = pfx; }
+
+  virtual FunctionType *getFunctionType(Module &M) const = 0;
+
+protected:
+  EFuncId FuncId;
+  std::string Name;
+  ENamePrefix FKind;
+};
+
+/// Wrapper class for AMDGPULIbFuncImpl
+class AMDGPULibFunc : public AMDGPULibFuncBase {
+public:
+  explicit AMDGPULibFunc() : Impl(std::unique_ptr<AMDGPULibFuncImpl>()) {}
+  AMDGPULibFunc(const AMDGPULibFunc &F);
+  /// Clone a mangled library func with the Id \p Id and argument info from \p
+  /// CopyFrom.
+  explicit AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom);
+  /// Construct an unmangled library function on the fly.
+  explicit AMDGPULibFunc(StringRef FName, FunctionType *FT);
+
+  AMDGPULibFunc &operator=(const AMDGPULibFunc &F);
+
+  /// Get unmangled name for mangled library function and name for unmangled
+  /// library function.
+  std::string getName() const { return Impl->getName(); }
+  unsigned getNumArgs() const { return Impl->getNumArgs(); }
+  EFuncId getId() const { return Impl->getId(); }
+  ENamePrefix getPrefix() const { return Impl->getPrefix(); }
+  /// Get leading parameters for mangled lib functions.
+  Param *getLeads();
+  const Param *getLeads() const;
+
+  bool isMangled() const { return Impl->isMangled(); }
+  void setId(EFuncId Id) { Impl->setId(Id); }
+  bool parseFuncName(StringRef &MangledName) {
+    return Impl->parseFuncName(MangledName);
+  }
+
+  /// \return The mangled function name for mangled library functions
+  /// and unmangled function name for unmangled library functions.
+  std::string mangle() const { return Impl->mangle(); }
+
+  void setName(StringRef N) { Impl->setName(N); }
+  void setPrefix(ENamePrefix PFX) { Impl->setPrefix(PFX); }
+
+  FunctionType *getFunctionType(Module &M) const {
+    return Impl->getFunctionType(M);
+  }
+  static Function *getFunction(llvm::Module *M, const AMDGPULibFunc &fInfo);
+
+  static Function *getOrInsertFunction(llvm::Module *M,
+                                       const AMDGPULibFunc &fInfo);
+  static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr);
+
+private:
+  /// Initialize as a mangled library function.
+  void initMangled();
+  std::unique_ptr<AMDGPULibFuncImpl> Impl;
+};
+
+class AMDGPUMangledLibFunc : public AMDGPULibFuncImpl {
+public:
+  Param Leads[2];
+
+  explicit AMDGPUMangledLibFunc();
+  explicit AMDGPUMangledLibFunc(EFuncId id,
+                                const AMDGPUMangledLibFunc &copyFrom);
+
+  std::string getName() const override;
+  unsigned getNumArgs() const override;
+  FunctionType *getFunctionType(Module &M) const override;
+  static StringRef getUnmangledName(StringRef MangledName);
+
+  bool parseFuncName(StringRef &mangledName) override;
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static bool classof(const AMDGPULibFuncImpl *F) { return F->isMangled(); }
+
+  std::string mangle() const override;
+
+private:
+  std::string mangleNameItanium() const;
+
+  std::string mangleName(StringRef Name) const;
+  bool parseUnmangledName(StringRef MangledName);
+
+  template <typename Stream> void writeName(Stream &OS) const;
+};
+
+class AMDGPUUnmangledLibFunc : public AMDGPULibFuncImpl {
+  FunctionType *FuncTy;
+
+public:
+  explicit AMDGPUUnmangledLibFunc();
+  explicit AMDGPUUnmangledLibFunc(StringRef FName, FunctionType *FT) {
+    Name = FName;
+    FuncTy = FT;
+  }
+  std::string getName() const override { return Name; }
+  unsigned getNumArgs() const override;
+  FunctionType *getFunctionType(Module &M) const override { return FuncTy; }
+
+  bool parseFuncName(StringRef &Name) override;
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static bool classof(const AMDGPULibFuncImpl *F) { return !F->isMangled(); }
+
+  std::string mangle() const override { return Name; }
+
+  void setFunctionType(FunctionType *FT) { FuncTy = FT; }
+};
 }
 #endif // _AMDGPU_LIBFUNC_H_