[llvm] 3eaa53e - Reapply "[IRBuilder] Virtualize IRBuilder"

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 17 10:18:06 PST 2020


Author: Nikita Popov
Date: 2020-02-17T19:04:11+01:00
New Revision: 3eaa53e80543813a2274391956e91d275950fbf8

URL: https://github.com/llvm/llvm-project/commit/3eaa53e80543813a2274391956e91d275950fbf8
DIFF: https://github.com/llvm/llvm-project/commit/3eaa53e80543813a2274391956e91d275950fbf8.diff

LOG: Reapply "[IRBuilder] Virtualize IRBuilder"

Relative to the original commit, this fixes some warnings,
and is based on the deletion of the IRBuilder copy constructor
in D74693. The automatic copy constructor would no longer be
safe.

-----

Related llvm-dev thread:
http://lists.llvm.org/pipermail/llvm-dev/2020-February/138951.html

This patch moves the IRBuilder from templating over the constant
folder and inserter towards making both of these virtual.
There are a couple of motivations for this:

1. It's not possible to share code between use-sites that use
different IRBuilder folders/inserters (short of templating the code
and moving it into headers).
2. Methods currently defined on IRBuilderBase (which is not templated)
do not use the custom inserter, resulting in subtle bugs (e.g.
incorrect InstCombine worklist management). It would be possible to
move those into the templated IRBuilder, but...
3. The vast majority of the IRBuilder implementation has to live
in the header, because it depends on the template arguments.
4. We have many unnecessary dependencies on IRBuilder.h,
because it is not easy to forward-declare. (Significant parts of
the backend depend on it via TargetLowering.h, for example.)

This patch addresses the issue by making the following changes:

* IRBuilderDefaultInserter::InsertHelper becomes virtual.
  IRBuilderBase accepts a reference to it.
* IRBuilderFolder is introduced as a virtual base class. It is
 implemented by ConstantFolder (default), NoFolder and TargetFolder.
  IRBuilderBase has a reference to this as well.
* All the logic is moved from IRBuilder to IRBuilderBase. This means
  that methods can in the future replace their IRBuilder<> & uses
  (or other specific IRBuilder types) with IRBuilderBase & and thus
  be usable with different IRBuilders.
* The IRBuilder class is now a thin wrapper around IRBuilderBase.
  Essentially it only stores the folder and inserter and takes care
  of constructing the base builder.

What this patch doesn't do, but should be simple followups after this change:

* Fixing use of the inserter for creation methods originally defined
  on IRBuilderBase.
* Replacing IRBuilder<> uses in arguments with IRBuilderBase, where useful.
* Moving code from the IRBuilder header to the source file.

>From the user perspective, these changes should be mostly transparent:
The only thing that consumers using a custom inserted may need to do is
inherit from IRBuilderDefaultInserter publicly and mark their InsertHelper
as public.

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

Added: 
    llvm/include/llvm/IR/IRBuilderFolder.h

Modified: 
    clang/lib/CodeGen/CGBuilder.h
    llvm/include/llvm/Analysis/TargetFolder.h
    llvm/include/llvm/IR/ConstantFolder.h
    llvm/include/llvm/IR/IRBuilder.h
    llvm/include/llvm/IR/NoFolder.h
    llvm/lib/Analysis/ConstantFolding.cpp
    llvm/lib/IR/IRBuilder.cpp
    llvm/lib/Transforms/Scalar/SROA.cpp
    polly/include/polly/CodeGen/IRBuilder.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h
index 7687f7990d99..38e96c0f4ee6 100644
--- a/clang/lib/CodeGen/CGBuilder.h
+++ b/clang/lib/CodeGen/CGBuilder.h
@@ -22,16 +22,15 @@ class CodeGenFunction;
 /// This is an IRBuilder insertion helper that forwards to
 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
 /// instructions.
-class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter {
+class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
 public:
   CGBuilderInserter() = default;
   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
 
-protected:
   /// This forwards to CodeGenFunction::InsertHelper.
   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
                     llvm::BasicBlock *BB,
-                    llvm::BasicBlock::iterator InsertPt) const;
+                    llvm::BasicBlock::iterator InsertPt) const override;
 private:
   CodeGenFunction *CGF = nullptr;
 };

diff  --git a/llvm/include/llvm/Analysis/TargetFolder.h b/llvm/include/llvm/Analysis/TargetFolder.h
index 7ab6562be440..712c1a2e8118 100644
--- a/llvm/include/llvm/Analysis/TargetFolder.h
+++ b/llvm/include/llvm/Analysis/TargetFolder.h
@@ -22,13 +22,14 @@
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/IRBuilderFolder.h"
 
 namespace llvm {
 
 class DataLayout;
 
 /// TargetFolder - Create constants with target dependent folding.
-class TargetFolder {
+class TargetFolder final : public IRBuilderFolder {
   const DataLayout &DL;
 
   /// Fold - Fold the constant using target specific information.
@@ -38,6 +39,8 @@ class TargetFolder {
     return C;
   }
 
+  virtual void anchor();
+
 public:
   explicit TargetFolder(const DataLayout &DL) : DL(DL) {}
 
@@ -46,66 +49,70 @@ class TargetFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateAdd(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW));
   }
-  Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFAdd(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getFAdd(LHS, RHS));
   }
   Constant *CreateSub(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW));
   }
-  Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFSub(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getFSub(LHS, RHS));
   }
   Constant *CreateMul(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW));
   }
-  Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFMul(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getFMul(LHS, RHS));
   }
-  Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{
+  Constant *CreateUDiv(Constant *LHS, Constant *RHS,
+                       bool isExact = false) const override {
     return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact));
   }
-  Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{
+  Constant *CreateSDiv(Constant *LHS, Constant *RHS,
+                       bool isExact = false) const override {
     return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact));
   }
-  Constant *CreateFDiv(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFDiv(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getFDiv(LHS, RHS));
   }
-  Constant *CreateURem(Constant *LHS, Constant *RHS) const {
+  Constant *CreateURem(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getURem(LHS, RHS));
   }
-  Constant *CreateSRem(Constant *LHS, Constant *RHS) const {
+  Constant *CreateSRem(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getSRem(LHS, RHS));
   }
-  Constant *CreateFRem(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFRem(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getFRem(LHS, RHS));
   }
   Constant *CreateShl(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW));
   }
-  Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{
+  Constant *CreateLShr(Constant *LHS, Constant *RHS,
+                       bool isExact = false) const override {
     return Fold(ConstantExpr::getLShr(LHS, RHS, isExact));
   }
-  Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{
+  Constant *CreateAShr(Constant *LHS, Constant *RHS,
+                       bool isExact = false) const override {
     return Fold(ConstantExpr::getAShr(LHS, RHS, isExact));
   }
-  Constant *CreateAnd(Constant *LHS, Constant *RHS) const {
+  Constant *CreateAnd(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getAnd(LHS, RHS));
   }
-  Constant *CreateOr(Constant *LHS, Constant *RHS) const {
+  Constant *CreateOr(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getOr(LHS, RHS));
   }
-  Constant *CreateXor(Constant *LHS, Constant *RHS) const {
+  Constant *CreateXor(Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::getXor(LHS, RHS));
   }
 
   Constant *CreateBinOp(Instruction::BinaryOps Opc,
-                        Constant *LHS, Constant *RHS) const {
+                        Constant *LHS, Constant *RHS) const override {
     return Fold(ConstantExpr::get(Opc, LHS, RHS));
   }
 
@@ -114,17 +121,17 @@ class TargetFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateNeg(Constant *C,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW));
   }
-  Constant *CreateFNeg(Constant *C) const {
+  Constant *CreateFNeg(Constant *C) const override {
     return Fold(ConstantExpr::getFNeg(C));
   }
-  Constant *CreateNot(Constant *C) const {
+  Constant *CreateNot(Constant *C) const override {
     return Fold(ConstantExpr::getNot(C));
   }
 
-  Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const {
+  Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override {
     return Fold(ConstantExpr::get(Opc, C));
   }
 
@@ -133,33 +140,34 @@ class TargetFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
-                                ArrayRef<Constant *> IdxList) const {
+                                ArrayRef<Constant *> IdxList) const override {
     return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList));
   }
-  Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
+  Constant *CreateGetElementPtr(Type *Ty, Constant *C,
+                                Constant *Idx) const override {
     // This form of the function only exists to avoid ambiguous overload
     // warnings about whether to convert Idx to ArrayRef<Constant *> or
     // ArrayRef<Value *>.
     return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx));
   }
   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
-                                ArrayRef<Value *> IdxList) const {
+                                ArrayRef<Value *> IdxList) const override {
     return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList));
   }
 
-  Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        ArrayRef<Constant *> IdxList) const {
+  Constant *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const override {
     return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList));
   }
   Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        Constant *Idx) const {
+                                        Constant *Idx) const override {
     // This form of the function only exists to avoid ambiguous overload
     // warnings about whether to convert Idx to ArrayRef<Constant *> or
     // ArrayRef<Value *>.
     return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx));
   }
-  Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        ArrayRef<Value *> IdxList) const {
+  Constant *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const override {
     return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList));
   }
 
@@ -168,54 +176,54 @@ class TargetFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateCast(Instruction::CastOps Op, Constant *C,
-                       Type *DestTy) const {
+                       Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getCast(Op, C, DestTy));
   }
   Constant *CreateIntCast(Constant *C, Type *DestTy,
-                          bool isSigned) const {
+                          bool isSigned) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned));
   }
-  Constant *CreatePointerCast(Constant *C, Type *DestTy) const {
+  Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getPointerCast(C, DestTy));
   }
-  Constant *CreateFPCast(Constant *C, Type *DestTy) const {
+  Constant *CreateFPCast(Constant *C, Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getFPCast(C, DestTy));
   }
-  Constant *CreateBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateBitCast(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::BitCast, C, DestTy);
   }
-  Constant *CreateIntToPtr(Constant *C, Type *DestTy) const {
+  Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::IntToPtr, C, DestTy);
   }
-  Constant *CreatePtrToInt(Constant *C, Type *DestTy) const {
+  Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::PtrToInt, C, DestTy);
   }
-  Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy));
   }
-  Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy));
   }
-  Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy));
   }
 
   Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
-                                                Type *DestTy) const {
+                                                Type *DestTy) const override {
     if (C->getType() == DestTy)
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy));
@@ -226,11 +234,11 @@ class TargetFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS,
-                       Constant *RHS) const {
+                       Constant *RHS) const override {
     return Fold(ConstantExpr::getCompare(P, LHS, RHS));
   }
   Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
-                       Constant *RHS) const {
+                       Constant *RHS) const override {
     return Fold(ConstantExpr::getCompare(P, LHS, RHS));
   }
 
@@ -238,31 +246,32 @@ class TargetFolder {
   // Other Instructions
   //===--------------------------------------------------------------------===//
 
-  Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const {
+  Constant *CreateSelect(Constant *C, Constant *True,
+                         Constant *False) const override {
     return Fold(ConstantExpr::getSelect(C, True, False));
   }
 
-  Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const {
+  Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const override {
     return Fold(ConstantExpr::getExtractElement(Vec, Idx));
   }
 
   Constant *CreateInsertElement(Constant *Vec, Constant *NewElt,
-                                Constant *Idx) const {
+                                Constant *Idx) const override {
     return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx));
   }
 
   Constant *CreateShuffleVector(Constant *V1, Constant *V2,
-                                Constant *Mask) const {
+                                Constant *Mask) const override {
     return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask));
   }
 
   Constant *CreateExtractValue(Constant *Agg,
-                               ArrayRef<unsigned> IdxList) const {
+                               ArrayRef<unsigned> IdxList) const override {
     return Fold(ConstantExpr::getExtractValue(Agg, IdxList));
   }
 
   Constant *CreateInsertValue(Constant *Agg, Constant *Val,
-                              ArrayRef<unsigned> IdxList) const {
+                              ArrayRef<unsigned> IdxList) const override {
     return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList));
   }
 };

diff  --git a/llvm/include/llvm/IR/ConstantFolder.h b/llvm/include/llvm/IR/ConstantFolder.h
index 5a5cabfd0206..32939e79cd1d 100644
--- a/llvm/include/llvm/IR/ConstantFolder.h
+++ b/llvm/include/llvm/IR/ConstantFolder.h
@@ -20,11 +20,14 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
+#include "llvm/IR/IRBuilderFolder.h"
 
 namespace llvm {
 
 /// ConstantFolder - Create constants with minimum, target independent, folding.
-class ConstantFolder {
+class ConstantFolder final : public IRBuilderFolder {
+  virtual void anchor();
+
 public:
   explicit ConstantFolder() = default;
 
@@ -33,87 +36,87 @@ class ConstantFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateAdd(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW);
   }
 
-  Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFAdd(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getFAdd(LHS, RHS);
   }
 
   Constant *CreateSub(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW);
   }
 
-  Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFSub(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getFSub(LHS, RHS);
   }
 
   Constant *CreateMul(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW);
   }
 
-  Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFMul(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getFMul(LHS, RHS);
   }
 
   Constant *CreateUDiv(Constant *LHS, Constant *RHS,
-                       bool isExact = false) const {
+                               bool isExact = false) const override {
     return ConstantExpr::getUDiv(LHS, RHS, isExact);
   }
 
   Constant *CreateSDiv(Constant *LHS, Constant *RHS,
-                       bool isExact = false) const {
+                               bool isExact = false) const override {
     return ConstantExpr::getSDiv(LHS, RHS, isExact);
   }
 
-  Constant *CreateFDiv(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFDiv(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getFDiv(LHS, RHS);
   }
 
-  Constant *CreateURem(Constant *LHS, Constant *RHS) const {
+  Constant *CreateURem(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getURem(LHS, RHS);
   }
 
-  Constant *CreateSRem(Constant *LHS, Constant *RHS) const {
+  Constant *CreateSRem(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getSRem(LHS, RHS);
   }
 
-  Constant *CreateFRem(Constant *LHS, Constant *RHS) const {
+  Constant *CreateFRem(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getFRem(LHS, RHS);
   }
 
   Constant *CreateShl(Constant *LHS, Constant *RHS,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW);
   }
 
   Constant *CreateLShr(Constant *LHS, Constant *RHS,
-                       bool isExact = false) const {
+                       bool isExact = false) const override {
     return ConstantExpr::getLShr(LHS, RHS, isExact);
   }
 
   Constant *CreateAShr(Constant *LHS, Constant *RHS,
-                       bool isExact = false) const {
+                       bool isExact = false) const override {
     return ConstantExpr::getAShr(LHS, RHS, isExact);
   }
 
-  Constant *CreateAnd(Constant *LHS, Constant *RHS) const {
+  Constant *CreateAnd(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getAnd(LHS, RHS);
   }
 
-  Constant *CreateOr(Constant *LHS, Constant *RHS) const {
+  Constant *CreateOr(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getOr(LHS, RHS);
   }
 
-  Constant *CreateXor(Constant *LHS, Constant *RHS) const {
+  Constant *CreateXor(Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::getXor(LHS, RHS);
   }
 
   Constant *CreateBinOp(Instruction::BinaryOps Opc,
-                        Constant *LHS, Constant *RHS) const {
+                        Constant *LHS, Constant *RHS) const override {
     return ConstantExpr::get(Opc, LHS, RHS);
   }
 
@@ -122,19 +125,19 @@ class ConstantFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateNeg(Constant *C,
-                      bool HasNUW = false, bool HasNSW = false) const {
+                      bool HasNUW = false, bool HasNSW = false) const override {
     return ConstantExpr::getNeg(C, HasNUW, HasNSW);
   }
 
-  Constant *CreateFNeg(Constant *C) const {
+  Constant *CreateFNeg(Constant *C) const override {
     return ConstantExpr::getFNeg(C);
   }
 
-  Constant *CreateNot(Constant *C) const {
+  Constant *CreateNot(Constant *C) const override {
     return ConstantExpr::getNot(C);
   }
 
-  Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const {
+  Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override {
     return ConstantExpr::get(Opc, C);
   }
 
@@ -143,11 +146,12 @@ class ConstantFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
-                                ArrayRef<Constant *> IdxList) const {
+                                ArrayRef<Constant *> IdxList) const override {
     return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
   }
 
-  Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
+  Constant *CreateGetElementPtr(Type *Ty, Constant *C,
+                                Constant *Idx) const override {
     // This form of the function only exists to avoid ambiguous overload
     // warnings about whether to convert Idx to ArrayRef<Constant *> or
     // ArrayRef<Value *>.
@@ -155,25 +159,25 @@ class ConstantFolder {
   }
 
   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
-                                ArrayRef<Value *> IdxList) const {
+                                ArrayRef<Value *> IdxList) const override {
     return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
   }
 
-  Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        ArrayRef<Constant *> IdxList) const {
+  Constant *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const override {
     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
   }
 
   Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        Constant *Idx) const {
+                                        Constant *Idx) const override {
     // This form of the function only exists to avoid ambiguous overload
     // warnings about whether to convert Idx to ArrayRef<Constant *> or
     // ArrayRef<Value *>.
     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx);
   }
 
-  Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        ArrayRef<Value *> IdxList) const {
+  Constant *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const override {
     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
   }
 
@@ -182,49 +186,49 @@ class ConstantFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateCast(Instruction::CastOps Op, Constant *C,
-                       Type *DestTy) const {
+                       Type *DestTy) const override {
     return ConstantExpr::getCast(Op, C, DestTy);
   }
 
-  Constant *CreatePointerCast(Constant *C, Type *DestTy) const {
+  Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
     return ConstantExpr::getPointerCast(C, DestTy);
   }
 
   Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
-                                                Type *DestTy) const {
+                                                Type *DestTy) const override {
     return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy);
   }
 
   Constant *CreateIntCast(Constant *C, Type *DestTy,
-                          bool isSigned) const {
+                          bool isSigned) const override {
     return ConstantExpr::getIntegerCast(C, DestTy, isSigned);
   }
 
-  Constant *CreateFPCast(Constant *C, Type *DestTy) const {
+  Constant *CreateFPCast(Constant *C, Type *DestTy) const override {
     return ConstantExpr::getFPCast(C, DestTy);
   }
 
-  Constant *CreateBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateBitCast(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::BitCast, C, DestTy);
   }
 
-  Constant *CreateIntToPtr(Constant *C, Type *DestTy) const {
+  Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::IntToPtr, C, DestTy);
   }
 
-  Constant *CreatePtrToInt(Constant *C, Type *DestTy) const {
+  Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::PtrToInt, C, DestTy);
   }
 
-  Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
     return ConstantExpr::getZExtOrBitCast(C, DestTy);
   }
 
-  Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
     return ConstantExpr::getSExtOrBitCast(C, DestTy);
   }
 
-  Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const {
+  Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
     return ConstantExpr::getTruncOrBitCast(C, DestTy);
   }
 
@@ -233,12 +237,12 @@ class ConstantFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS,
-                       Constant *RHS) const {
+                       Constant *RHS) const override {
     return ConstantExpr::getCompare(P, LHS, RHS);
   }
 
   Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
-                       Constant *RHS) const {
+                       Constant *RHS) const override {
     return ConstantExpr::getCompare(P, LHS, RHS);
   }
 
@@ -246,31 +250,32 @@ class ConstantFolder {
   // Other Instructions
   //===--------------------------------------------------------------------===//
 
-  Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const {
+  Constant *CreateSelect(Constant *C, Constant *True,
+                         Constant *False) const override {
     return ConstantExpr::getSelect(C, True, False);
   }
 
-  Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const {
+  Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const override {
     return ConstantExpr::getExtractElement(Vec, Idx);
   }
 
   Constant *CreateInsertElement(Constant *Vec, Constant *NewElt,
-                                Constant *Idx) const {
+                                Constant *Idx) const override {
     return ConstantExpr::getInsertElement(Vec, NewElt, Idx);
   }
 
   Constant *CreateShuffleVector(Constant *V1, Constant *V2,
-                                Constant *Mask) const {
+                                Constant *Mask) const override {
     return ConstantExpr::getShuffleVector(V1, V2, Mask);
   }
 
   Constant *CreateExtractValue(Constant *Agg,
-                               ArrayRef<unsigned> IdxList) const {
+                               ArrayRef<unsigned> IdxList) const override {
     return ConstantExpr::getExtractValue(Agg, IdxList);
   }
 
   Constant *CreateInsertValue(Constant *Agg, Constant *Val,
-                              ArrayRef<unsigned> IdxList) const {
+                              ArrayRef<unsigned> IdxList) const override {
     return ConstantExpr::getInsertValue(Agg, Val, IdxList);
   }
 };

diff  --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index c9ae136f4d6c..825a2426b742 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -59,9 +59,12 @@ class Use;
 ///
 /// By default, this inserts the instruction at the insertion point.
 class IRBuilderDefaultInserter {
-protected:
-  void InsertHelper(Instruction *I, const Twine &Name,
-                    BasicBlock *BB, BasicBlock::iterator InsertPt) const {
+public:
+  virtual ~IRBuilderDefaultInserter();
+
+  virtual void InsertHelper(Instruction *I, const Twine &Name,
+                            BasicBlock *BB,
+                            BasicBlock::iterator InsertPt) const {
     if (BB) BB->getInstList().insert(InsertPt, I);
     I->setName(Name);
   }
@@ -69,16 +72,18 @@ class IRBuilderDefaultInserter {
 
 /// Provides an 'InsertHelper' that calls a user-provided callback after
 /// performing the default insertion.
-class IRBuilderCallbackInserter : IRBuilderDefaultInserter {
+class IRBuilderCallbackInserter : public IRBuilderDefaultInserter {
   std::function<void(Instruction *)> Callback;
 
 public:
+  virtual ~IRBuilderCallbackInserter();
+
   IRBuilderCallbackInserter(std::function<void(Instruction *)> Callback)
       : Callback(std::move(Callback)) {}
 
-protected:
   void InsertHelper(Instruction *I, const Twine &Name,
-                    BasicBlock *BB, BasicBlock::iterator InsertPt) const {
+                    BasicBlock *BB,
+                    BasicBlock::iterator InsertPt) const override {
     IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt);
     Callback(I);
   }
@@ -92,6 +97,8 @@ class IRBuilderBase {
   BasicBlock *BB;
   BasicBlock::iterator InsertPt;
   LLVMContext &Context;
+  const IRBuilderFolder &Folder;
+  const IRBuilderDefaultInserter &Inserter;
 
   MDNode *DefaultFPMathTag;
   FastMathFlags FMF;
@@ -103,15 +110,37 @@ class IRBuilderBase {
   ArrayRef<OperandBundleDef> DefaultOperandBundles;
 
 public:
-  IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr,
-                ArrayRef<OperandBundleDef> OpBundles = None)
-      : Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false),
+  IRBuilderBase(LLVMContext &context, const IRBuilderFolder &Folder,
+                const IRBuilderDefaultInserter &Inserter,
+                MDNode *FPMathTag, ArrayRef<OperandBundleDef> OpBundles)
+      : Context(context), Folder(Folder), Inserter(Inserter),
+        DefaultFPMathTag(FPMathTag), IsFPConstrained(false),
         DefaultConstrainedExcept(fp::ebStrict),
         DefaultConstrainedRounding(fp::rmDynamic),
         DefaultOperandBundles(OpBundles) {
     ClearInsertionPoint();
   }
 
+  /// Insert and return the specified instruction.
+  template<typename InstTy>
+  InstTy *Insert(InstTy *I, const Twine &Name = "") const {
+    Inserter.InsertHelper(I, Name, BB, InsertPt);
+    SetInstDebugLocation(I);
+    return I;
+  }
+
+  /// No-op overload to handle constants.
+  Constant *Insert(Constant *C, const Twine& = "") const {
+    return C;
+  }
+
+  Value *Insert(Value *V, const Twine& = "") const {
+    if (Instruction *I = dyn_cast<Instruction>(V))
+      return Insert(I);
+    assert(isa<Constant>(V));
+    return V;
+  }
+
   //===--------------------------------------------------------------------===//
   // Builder configuration methods
   //===--------------------------------------------------------------------===//
@@ -920,89 +949,6 @@ class IRBuilderBase {
                                   const Twine &Name = "");
 
   Value *getCastedInt8PtrValue(Value *Ptr);
-};
-
-/// This provides a uniform API for creating instructions and inserting
-/// them into a basic block: either at the end of a BasicBlock, or at a specific
-/// iterator location in a block.
-///
-/// Note that the builder does not expose the full generality of LLVM
-/// instructions.  For access to extra instruction properties, use the mutators
-/// (e.g. setVolatile) on the instructions after they have been
-/// created. Convenience state exists to specify fast-math flags and fp-math
-/// tags.
-///
-/// The first template argument specifies a class to use for creating constants.
-/// This defaults to creating minimally folded constants.  The second template
-/// argument allows clients to specify custom insertion hooks that are called on
-/// every newly created insertion.
-template <typename T = ConstantFolder,
-          typename Inserter = IRBuilderDefaultInserter>
-class IRBuilder : public IRBuilderBase, public Inserter {
-  T Folder;
-
-public:
-  IRBuilder(LLVMContext &C, const T &F, Inserter I = Inserter(),
-            MDNode *FPMathTag = nullptr,
-            ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(C, FPMathTag, OpBundles), Inserter(std::move(I)),
-        Folder(F) {}
-
-  explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr,
-                     ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(C, FPMathTag, OpBundles) {}
-
-  explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = nullptr,
-                     ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles), Folder(F) {
-    SetInsertPoint(TheBB);
-  }
-
-  explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr,
-                     ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles) {
-    SetInsertPoint(TheBB);
-  }
-
-  explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr,
-                     ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(IP->getContext(), FPMathTag, OpBundles) {
-    SetInsertPoint(IP);
-  }
-
-  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T &F,
-            MDNode *FPMathTag = nullptr,
-            ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles), Folder(F) {
-    SetInsertPoint(TheBB, IP);
-  }
-
-  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
-            MDNode *FPMathTag = nullptr,
-            ArrayRef<OperandBundleDef> OpBundles = None)
-      : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles) {
-    SetInsertPoint(TheBB, IP);
-  }
-
-  /// Avoid copying the full IRBuilder. Prefer using InsertPointGuard
-  /// or FastMathFlagGuard instead.
-  IRBuilder(const IRBuilder &) = delete;
-
-  /// Get the constant folder being used.
-  const T &getFolder() { return Folder; }
-
-  /// Insert and return the specified instruction.
-  template<typename InstTy>
-  InstTy *Insert(InstTy *I, const Twine &Name = "") const {
-    this->InsertHelper(I, Name, BB, InsertPt);
-    this->SetInstDebugLocation(I);
-    return I;
-  }
-
-  /// No-op overload to handle constants.
-  Constant *Insert(Constant *C, const Twine& = "") const {
-    return C;
-  }
 
   //===--------------------------------------------------------------------===//
   // Instruction creation methods: Terminators
@@ -2980,6 +2926,83 @@ class IRBuilder : public IRBuilderBase, public Inserter {
   }
 };
 
+/// This provides a uniform API for creating instructions and inserting
+/// them into a basic block: either at the end of a BasicBlock, or at a specific
+/// iterator location in a block.
+///
+/// Note that the builder does not expose the full generality of LLVM
+/// instructions.  For access to extra instruction properties, use the mutators
+/// (e.g. setVolatile) on the instructions after they have been
+/// created. Convenience state exists to specify fast-math flags and fp-math
+/// tags.
+///
+/// The first template argument specifies a class to use for creating constants.
+/// This defaults to creating minimally folded constants.  The second template
+/// argument allows clients to specify custom insertion hooks that are called on
+/// every newly created insertion.
+template <typename FolderTy = ConstantFolder,
+          typename InserterTy = IRBuilderDefaultInserter>
+class IRBuilder : public IRBuilderBase {
+private:
+  FolderTy Folder;
+  InserterTy Inserter;
+
+public:
+  IRBuilder(LLVMContext &C, FolderTy Folder, InserterTy Inserter = InserterTy(),
+            MDNode *FPMathTag = nullptr,
+            ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles),
+        Folder(Folder), Inserter(Inserter) {}
+
+  explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr,
+                     ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles) {}
+
+  explicit IRBuilder(BasicBlock *TheBB, FolderTy Folder,
+                     MDNode *FPMathTag = nullptr,
+                     ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
+                      FPMathTag, OpBundles), Folder(Folder) {
+    SetInsertPoint(TheBB);
+  }
+
+  explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr,
+                     ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
+                      FPMathTag, OpBundles) {
+    SetInsertPoint(TheBB);
+  }
+
+  explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr,
+                     ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(IP->getContext(), this->Folder, this->Inserter,
+                      FPMathTag, OpBundles) {
+    SetInsertPoint(IP);
+  }
+
+  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, FolderTy Folder,
+            MDNode *FPMathTag = nullptr,
+            ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
+                      FPMathTag, OpBundles), Folder(Folder) {
+    SetInsertPoint(TheBB, IP);
+  }
+
+  IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
+            MDNode *FPMathTag = nullptr,
+            ArrayRef<OperandBundleDef> OpBundles = None)
+      : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
+                      FPMathTag, OpBundles) {
+    SetInsertPoint(TheBB, IP);
+  }
+
+  /// Avoid copying the full IRBuilder. Prefer using InsertPointGuard
+  /// or FastMathFlagGuard instead.
+  IRBuilder(const IRBuilder &) = delete;
+
+  InserterTy &getInserter() { return Inserter; }
+};
+
 // Create wrappers for C Binding types (see CBindingWrapping.h).
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef)
 

diff  --git a/llvm/include/llvm/IR/IRBuilderFolder.h b/llvm/include/llvm/IR/IRBuilderFolder.h
new file mode 100644
index 000000000000..a77a5213dcea
--- /dev/null
+++ b/llvm/include/llvm/IR/IRBuilderFolder.h
@@ -0,0 +1,141 @@
+//===- IRBuilderFolder.h - Const folder interface for IRBuilder -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines for constant folding interface used by IRBuilder.
+// It is implemented by ConstantFolder (default), TargetFolder and NoFoler.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_IRBUILDERFOLDER_H
+#define LLVM_IR_IRBUILDERFOLDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
+
+namespace llvm {
+
+/// IRBuilderFolder - Interface for constant folding in IRBuilder.
+class IRBuilderFolder {
+public:
+  virtual ~IRBuilderFolder();
+
+  //===--------------------------------------------------------------------===//
+  // Binary Operators
+  //===--------------------------------------------------------------------===//
+
+  virtual Value *CreateAdd(Constant *LHS, Constant *RHS,
+                           bool HasNUW = false, bool HasNSW = false) const = 0;
+  virtual Value *CreateFAdd(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateSub(Constant *LHS, Constant *RHS,
+                           bool HasNUW = false, bool HasNSW = false) const = 0;
+  virtual Value *CreateFSub(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateMul(Constant *LHS, Constant *RHS,
+                           bool HasNUW = false, bool HasNSW = false) const = 0;
+  virtual Value *CreateFMul(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateUDiv(Constant *LHS, Constant *RHS,
+                            bool isExact = false) const = 0;
+  virtual Value *CreateSDiv(Constant *LHS, Constant *RHS,
+                            bool isExact = false) const = 0;
+  virtual Value *CreateFDiv(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateURem(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateSRem(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateFRem(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateShl(Constant *LHS, Constant *RHS,
+                           bool HasNUW = false, bool HasNSW = false) const = 0;
+  virtual Value *CreateLShr(Constant *LHS, Constant *RHS,
+                            bool isExact = false) const = 0;
+  virtual Value *CreateAShr(Constant *LHS, Constant *RHS,
+                            bool isExact = false) const = 0;
+  virtual Value *CreateAnd(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateOr(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateXor(Constant *LHS, Constant *RHS) const = 0;
+  virtual Value *CreateBinOp(Instruction::BinaryOps Opc,
+                             Constant *LHS, Constant *RHS) const = 0;
+
+  //===--------------------------------------------------------------------===//
+  // Unary Operators
+  //===--------------------------------------------------------------------===//
+
+  virtual Value *CreateNeg(Constant *C,
+                           bool HasNUW = false, bool HasNSW = false) const = 0;
+  virtual Value *CreateFNeg(Constant *C) const = 0;
+  virtual Value *CreateNot(Constant *C) const = 0;
+  virtual Value *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const = 0;
+
+  //===--------------------------------------------------------------------===//
+  // Memory Instructions
+  //===--------------------------------------------------------------------===//
+
+  virtual Value *CreateGetElementPtr(Type *Ty, Constant *C,
+                                     ArrayRef<Constant *> IdxList) const = 0;
+  // This form of the function only exists to avoid ambiguous overload
+  // warnings about whether to convert Idx to ArrayRef<Constant *> or
+  // ArrayRef<Value *>.
+  virtual Value *CreateGetElementPtr(Type *Ty, Constant *C,
+                                     Constant *Idx) const = 0;
+  virtual Value *CreateGetElementPtr(Type *Ty, Constant *C,
+                                     ArrayRef<Value *> IdxList) const = 0;
+  virtual Value *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const = 0;
+  // This form of the function only exists to avoid ambiguous overload
+  // warnings about whether to convert Idx to ArrayRef<Constant *> or
+  // ArrayRef<Value *>.
+  virtual Value *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
+                                             Constant *Idx) const = 0;
+  virtual Value *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const = 0;
+
+  //===--------------------------------------------------------------------===//
+  // Cast/Conversion Operators
+  //===--------------------------------------------------------------------===//
+
+  virtual Value *CreateCast(Instruction::CastOps Op, Constant *C,
+                            Type *DestTy) const = 0;
+  virtual Value *CreatePointerCast(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
+                                                     Type *DestTy) const = 0;
+  virtual Value *CreateIntCast(Constant *C, Type *DestTy,
+                               bool isSigned) const = 0;
+  virtual Value *CreateFPCast(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreateBitCast(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreateIntToPtr(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreatePtrToInt(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreateZExtOrBitCast(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreateSExtOrBitCast(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreateTruncOrBitCast(Constant *C, Type *DestTy) const = 0;
+
+  //===--------------------------------------------------------------------===//
+  // Compare Instructions
+  //===--------------------------------------------------------------------===//
+
+  virtual Value *CreateICmp(CmpInst::Predicate P, Constant *LHS,
+                            Constant *RHS) const = 0;
+  virtual Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
+                            Constant *RHS) const = 0;
+
+  //===--------------------------------------------------------------------===//
+  // Other Instructions
+  //===--------------------------------------------------------------------===//
+
+  virtual Value *CreateSelect(Constant *C, Constant *True,
+                              Constant *False) const = 0;
+  virtual Value *CreateExtractElement(Constant *Vec, Constant *Idx) const = 0;
+  virtual Value *CreateInsertElement(Constant *Vec, Constant *NewElt,
+                                     Constant *Idx) const = 0;
+  virtual Value *CreateShuffleVector(Constant *V1, Constant *V2,
+                                     Constant *Mask) const = 0;
+  virtual Value *CreateExtractValue(Constant *Agg,
+                                    ArrayRef<unsigned> IdxList) const = 0;
+  virtual Value *CreateInsertValue(Constant *Agg, Constant *Val,
+                                   ArrayRef<unsigned> IdxList) const = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_IR_IRBUILDERFOLDER_H

diff  --git a/llvm/include/llvm/IR/NoFolder.h b/llvm/include/llvm/IR/NoFolder.h
index c03cdee1eb83..1e35cfe096eb 100644
--- a/llvm/include/llvm/IR/NoFolder.h
+++ b/llvm/include/llvm/IR/NoFolder.h
@@ -26,11 +26,14 @@
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/IRBuilderFolder.h"
 
 namespace llvm {
 
 /// NoFolder - Create "constants" (actually, instructions) with no folding.
-class NoFolder {
+class NoFolder final : public IRBuilderFolder {
+  virtual void anchor();
+
 public:
   explicit NoFolder() = default;
 
@@ -39,73 +42,76 @@ class NoFolder {
   //===--------------------------------------------------------------------===//
 
   Instruction *CreateAdd(Constant *LHS, Constant *RHS,
-                         bool HasNUW = false, bool HasNSW = false) const {
+                         bool HasNUW = false,
+                         bool HasNSW = false) const override {
     BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS);
     if (HasNUW) BO->setHasNoUnsignedWrap();
     if (HasNSW) BO->setHasNoSignedWrap();
     return BO;
   }
 
-  Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateFAdd(LHS, RHS);
   }
 
   Instruction *CreateSub(Constant *LHS, Constant *RHS,
-                         bool HasNUW = false, bool HasNSW = false) const {
+                         bool HasNUW = false,
+                         bool HasNSW = false) const override {
     BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS);
     if (HasNUW) BO->setHasNoUnsignedWrap();
     if (HasNSW) BO->setHasNoSignedWrap();
     return BO;
   }
 
-  Instruction *CreateFSub(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateFSub(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateFSub(LHS, RHS);
   }
 
   Instruction *CreateMul(Constant *LHS, Constant *RHS,
-                         bool HasNUW = false, bool HasNSW = false) const {
+                         bool HasNUW = false,
+                         bool HasNSW = false) const override {
     BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS);
     if (HasNUW) BO->setHasNoUnsignedWrap();
     if (HasNSW) BO->setHasNoSignedWrap();
     return BO;
   }
 
-  Instruction *CreateFMul(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateFMul(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateFMul(LHS, RHS);
   }
 
   Instruction *CreateUDiv(Constant *LHS, Constant *RHS,
-                          bool isExact = false) const {
+                          bool isExact = false) const override {
     if (!isExact)
       return BinaryOperator::CreateUDiv(LHS, RHS);
     return BinaryOperator::CreateExactUDiv(LHS, RHS);
   }
 
   Instruction *CreateSDiv(Constant *LHS, Constant *RHS,
-                          bool isExact = false) const {
+                          bool isExact = false) const override {
     if (!isExact)
       return BinaryOperator::CreateSDiv(LHS, RHS);
     return BinaryOperator::CreateExactSDiv(LHS, RHS);
   }
 
-  Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateFDiv(LHS, RHS);
   }
 
-  Instruction *CreateURem(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateURem(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateURem(LHS, RHS);
   }
 
-  Instruction *CreateSRem(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateSRem(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateSRem(LHS, RHS);
   }
 
-  Instruction *CreateFRem(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateFRem(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateFRem(LHS, RHS);
   }
 
   Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false,
-                         bool HasNSW = false) const {
+                         bool HasNSW = false) const override {
     BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS);
     if (HasNUW) BO->setHasNoUnsignedWrap();
     if (HasNSW) BO->setHasNoSignedWrap();
@@ -113,33 +119,33 @@ class NoFolder {
   }
 
   Instruction *CreateLShr(Constant *LHS, Constant *RHS,
-                          bool isExact = false) const {
+                          bool isExact = false) const override {
     if (!isExact)
       return BinaryOperator::CreateLShr(LHS, RHS);
     return BinaryOperator::CreateExactLShr(LHS, RHS);
   }
 
   Instruction *CreateAShr(Constant *LHS, Constant *RHS,
-                          bool isExact = false) const {
+                          bool isExact = false) const override {
     if (!isExact)
       return BinaryOperator::CreateAShr(LHS, RHS);
     return BinaryOperator::CreateExactAShr(LHS, RHS);
   }
 
-  Instruction *CreateAnd(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateAnd(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateAnd(LHS, RHS);
   }
 
-  Instruction *CreateOr(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateOr(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateOr(LHS, RHS);
   }
 
-  Instruction *CreateXor(Constant *LHS, Constant *RHS) const {
+  Instruction *CreateXor(Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::CreateXor(LHS, RHS);
   }
 
   Instruction *CreateBinOp(Instruction::BinaryOps Opc,
-                           Constant *LHS, Constant *RHS) const {
+                           Constant *LHS, Constant *RHS) const override {
     return BinaryOperator::Create(Opc, LHS, RHS);
   }
 
@@ -148,22 +154,24 @@ class NoFolder {
   //===--------------------------------------------------------------------===//
 
   Instruction *CreateNeg(Constant *C,
-                         bool HasNUW = false, bool HasNSW = false) const {
+                         bool HasNUW = false,
+                         bool HasNSW = false) const override {
     BinaryOperator *BO = BinaryOperator::CreateNeg(C);
     if (HasNUW) BO->setHasNoUnsignedWrap();
     if (HasNSW) BO->setHasNoSignedWrap();
     return BO;
   }
 
-  Instruction *CreateFNeg(Constant *C) const {
+  Instruction *CreateFNeg(Constant *C) const override {
     return UnaryOperator::CreateFNeg(C);
   }
 
-  Instruction *CreateNot(Constant *C) const {
+  Instruction *CreateNot(Constant *C) const override {
     return BinaryOperator::CreateNot(C);
   }
 
-  Instruction *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const {
+  Instruction *CreateUnOp(Instruction::UnaryOps Opc,
+                          Constant *C) const override {
     return UnaryOperator::Create(Opc, C);
   }
 
@@ -172,11 +180,12 @@ class NoFolder {
   //===--------------------------------------------------------------------===//
 
   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
-                                ArrayRef<Constant *> IdxList) const {
+                                ArrayRef<Constant *> IdxList) const override {
     return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
   }
 
-  Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
+  Constant *CreateGetElementPtr(Type *Ty, Constant *C,
+                                Constant *Idx) const override {
     // This form of the function only exists to avoid ambiguous overload
     // warnings about whether to convert Idx to ArrayRef<Constant *> or
     // ArrayRef<Value *>.
@@ -184,25 +193,25 @@ class NoFolder {
   }
 
   Instruction *CreateGetElementPtr(Type *Ty, Constant *C,
-                                   ArrayRef<Value *> IdxList) const {
+                                   ArrayRef<Value *> IdxList) const override {
     return GetElementPtrInst::Create(Ty, C, IdxList);
   }
 
-  Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        ArrayRef<Constant *> IdxList) const {
+  Constant *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const override {
     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
   }
 
   Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                        Constant *Idx) const {
+                                        Constant *Idx) const override {
     // This form of the function only exists to avoid ambiguous overload
     // warnings about whether to convert Idx to ArrayRef<Constant *> or
     // ArrayRef<Value *>.
     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx);
   }
 
-  Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
-                                           ArrayRef<Value *> IdxList) const {
+  Instruction *CreateInBoundsGetElementPtr(
+      Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const override {
     return GetElementPtrInst::CreateInBounds(Ty, C, IdxList);
   }
 
@@ -211,49 +220,49 @@ class NoFolder {
   //===--------------------------------------------------------------------===//
 
   Instruction *CreateCast(Instruction::CastOps Op, Constant *C,
-                    Type *DestTy) const {
+                          Type *DestTy) const override {
     return CastInst::Create(Op, C, DestTy);
   }
 
-  Instruction *CreatePointerCast(Constant *C, Type *DestTy) const {
+  Instruction *CreatePointerCast(Constant *C, Type *DestTy) const override {
     return CastInst::CreatePointerCast(C, DestTy);
   }
 
   Instruction *CreatePointerBitCastOrAddrSpaceCast(
-      Constant *C, Type *DestTy) const {
+      Constant *C, Type *DestTy) const override {
     return CastInst::CreatePointerBitCastOrAddrSpaceCast(C, DestTy);
   }
 
   Instruction *CreateIntCast(Constant *C, Type *DestTy,
-                       bool isSigned) const {
+                             bool isSigned) const override {
     return CastInst::CreateIntegerCast(C, DestTy, isSigned);
   }
 
-  Instruction *CreateFPCast(Constant *C, Type *DestTy) const {
+  Instruction *CreateFPCast(Constant *C, Type *DestTy) const override {
     return CastInst::CreateFPCast(C, DestTy);
   }
 
-  Instruction *CreateBitCast(Constant *C, Type *DestTy) const {
+  Instruction *CreateBitCast(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::BitCast, C, DestTy);
   }
 
-  Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const {
+  Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::IntToPtr, C, DestTy);
   }
 
-  Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const {
+  Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::PtrToInt, C, DestTy);
   }
 
-  Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const {
+  Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
     return CastInst::CreateZExtOrBitCast(C, DestTy);
   }
 
-  Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const {
+  Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
     return CastInst::CreateSExtOrBitCast(C, DestTy);
   }
 
-  Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const {
+  Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
     return CastInst::CreateTruncOrBitCast(C, DestTy);
   }
 
@@ -262,12 +271,12 @@ class NoFolder {
   //===--------------------------------------------------------------------===//
 
   Instruction *CreateICmp(CmpInst::Predicate P,
-                          Constant *LHS, Constant *RHS) const {
+                          Constant *LHS, Constant *RHS) const override {
     return new ICmpInst(P, LHS, RHS);
   }
 
   Instruction *CreateFCmp(CmpInst::Predicate P,
-                          Constant *LHS, Constant *RHS) const {
+                          Constant *LHS, Constant *RHS) const override {
     return new FCmpInst(P, LHS, RHS);
   }
 
@@ -276,31 +285,32 @@ class NoFolder {
   //===--------------------------------------------------------------------===//
 
   Instruction *CreateSelect(Constant *C,
-                            Constant *True, Constant *False) const {
+                            Constant *True, Constant *False) const override {
     return SelectInst::Create(C, True, False);
   }
 
-  Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const {
+  Instruction *CreateExtractElement(Constant *Vec,
+                                    Constant *Idx) const override {
     return ExtractElementInst::Create(Vec, Idx);
   }
 
   Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt,
-                                   Constant *Idx) const {
+                                   Constant *Idx) const override {
     return InsertElementInst::Create(Vec, NewElt, Idx);
   }
 
   Instruction *CreateShuffleVector(Constant *V1, Constant *V2,
-                                   Constant *Mask) const {
+                                   Constant *Mask) const override {
     return new ShuffleVectorInst(V1, V2, Mask);
   }
 
   Instruction *CreateExtractValue(Constant *Agg,
-                                  ArrayRef<unsigned> IdxList) const {
+                                  ArrayRef<unsigned> IdxList) const override {
     return ExtractValueInst::Create(Agg, IdxList);
   }
 
   Instruction *CreateInsertValue(Constant *Agg, Constant *Val,
-                                 ArrayRef<unsigned> IdxList) const {
+                                 ArrayRef<unsigned> IdxList) const override {
     return InsertValueInst::Create(Agg, Val, IdxList);
   }
 };

diff  --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 0e4828d912dc..059bf9a53275 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/TargetFolder.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/Analysis/VectorUtils.h"
@@ -2660,3 +2661,5 @@ bool llvm::isMathLibCallNoop(const CallBase *Call,
 
   return false;
 }
+
+void TargetFolder::anchor() {}

diff  --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index 0dd78f2f2d4b..457255b157cc 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -24,6 +24,7 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Operator.h"
+#include "llvm/IR/NoFolder.h"
 #include "llvm/IR/Statepoint.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
@@ -784,3 +785,9 @@ CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
   Function *Fn = Intrinsic::getDeclaration(M, ID, Types);
   return createCallHelper(Fn, Args, this, Name, FMFSource);
 }
+
+IRBuilderDefaultInserter::~IRBuilderDefaultInserter() {}
+IRBuilderCallbackInserter::~IRBuilderCallbackInserter() {}
+IRBuilderFolder::~IRBuilderFolder() {}
+void ConstantFolder::anchor() {}
+void NoFolder::anchor() {}

diff  --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 0038ac5038ca..c65244c1045d 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -129,7 +129,7 @@ namespace {
 
 /// A custom IRBuilder inserter which prefixes all names, but only in
 /// Assert builds.
-class IRBuilderPrefixedInserter : public IRBuilderDefaultInserter {
+class IRBuilderPrefixedInserter final : public IRBuilderDefaultInserter {
   std::string Prefix;
 
   const Twine getNameWithPrefix(const Twine &Name) const {
@@ -139,9 +139,8 @@ class IRBuilderPrefixedInserter : public IRBuilderDefaultInserter {
 public:
   void SetNamePrefix(const Twine &P) { Prefix = P.str(); }
 
-protected:
   void InsertHelper(Instruction *I, const Twine &Name, BasicBlock *BB,
-                    BasicBlock::iterator InsertPt) const {
+                    BasicBlock::iterator InsertPt) const override {
     IRBuilderDefaultInserter::InsertHelper(I, getNameWithPrefix(Name), BB,
                                            InsertPt);
   }
@@ -2368,7 +2367,8 @@ class llvm::sroa::AllocaSliceRewriter
     Instruction *OldUserI = cast<Instruction>(OldUse->getUser());
     IRB.SetInsertPoint(OldUserI);
     IRB.SetCurrentDebugLocation(OldUserI->getDebugLoc());
-    IRB.SetNamePrefix(Twine(NewAI.getName()) + "." + Twine(BeginOffset) + ".");
+    IRB.getInserter().SetNamePrefix(
+        Twine(NewAI.getName()) + "." + Twine(BeginOffset) + ".");
 
     CanSROA &= visit(cast<Instruction>(OldUse->getUser()));
     if (VecTy || IntTy)

diff  --git a/polly/include/polly/CodeGen/IRBuilder.h b/polly/include/polly/CodeGen/IRBuilder.h
index 8aeef3856a07..fb5d14a8b88b 100644
--- a/polly/include/polly/CodeGen/IRBuilder.h
+++ b/polly/include/polly/CodeGen/IRBuilder.h
@@ -131,15 +131,14 @@ class ScopAnnotator {
 ///
 /// This is used to add additional items such as e.g. the llvm.loop.parallel
 /// metadata.
-class IRInserter : protected llvm::IRBuilderDefaultInserter {
+class IRInserter final : public llvm::IRBuilderDefaultInserter {
 public:
   IRInserter() = default;
   IRInserter(class ScopAnnotator &A) : Annotator(&A) {}
 
-protected:
   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
                     llvm::BasicBlock *BB,
-                    llvm::BasicBlock::iterator InsertPt) const {
+                    llvm::BasicBlock::iterator InsertPt) const override {
     llvm::IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt);
     if (Annotator)
       Annotator->annotate(I);


        


More information about the llvm-commits mailing list