[clang] 0765d38 - [IRBuilder] Virtualize IRBuilder

Nikita Popov via cfe-commits cfe-commits at lists.llvm.org
Sun Feb 16 05:37:49 PST 2020


Author: Nikita Popov
Date: 2020-02-16T13:48:55+01:00
New Revision: 0765d3824d069f37596bc5a890399099b776c2a0

URL: https://github.com/llvm/llvm-project/commit/0765d3824d069f37596bc5a890399099b776c2a0
DIFF: https://github.com/llvm/llvm-project/commit/0765d3824d069f37596bc5a890399099b776c2a0.diff

LOG: [IRBuilder] Virtualize IRBuilder

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..19233f395b84 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 : 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 82cd0738ac28..47e6e6c3b059 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 {
+  virtual void anchor();
+
+public:
+  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,17 @@ 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;
+  virtual void anchor();
 
 public:
   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 +96,8 @@ class IRBuilderBase {
   BasicBlock *BB;
   BasicBlock::iterator InsertPt;
   LLVMContext &Context;
+  const IRBuilderFolder &Folder;
+  const IRBuilderDefaultInserter &Inserter;
 
   MDNode *DefaultFPMathTag;
   FastMathFlags FMF;
@@ -103,15 +109,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,85 +948,7 @@ 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);
-  }
-
-  /// 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
@@ -2976,6 +2926,79 @@ 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);
+  }
+
+  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..64290d75339e
--- /dev/null
+++ b/llvm/include/llvm/IR/IRBuilderFolder.h
@@ -0,0 +1,139 @@
+//===- 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:
+  //===--------------------------------------------------------------------===//
+  // 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..f6c8cd73c23c 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,8 @@ CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
   Function *Fn = Intrinsic::getDeclaration(M, ID, Types);
   return createCallHelper(Fn, Args, this, Name, FMFSource);
 }
+
+void IRBuilderDefaultInserter::anchor() {}
+void IRBuilderCallbackInserter::anchor() {}
+void ConstantFolder::anchor() {}
+void NoFolder::anchor() {}

diff  --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 6c9b62da5e79..866c5f00d4c3 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -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 8033ffafb7de..0d432039aba1 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 : 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 cfe-commits mailing list