[llvm] r329596 - [GISel] Refactor MachineIRBuilder to allow transformations while

Aditya Nandakumar via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 9 10:30:56 PDT 2018


Author: aditya_nandakumar
Date: Mon Apr  9 10:30:56 2018
New Revision: 329596

URL: http://llvm.org/viewvc/llvm-project?rev=329596&view=rev
Log:
[GISel] Refactor MachineIRBuilder to allow transformations while
building.

https://reviews.llvm.org/D45067

This change attempts to do two things:
1) It separates out the state that is stored in the
MachineIRBuilder(InsertionPt, MF, MRI, InsertFunction etc) into a
separate object called MachineIRBuilderState.
2) Add the ability to constant fold operations while building instructions
(optionally). MachineIRBuilder is now refactored into a MachineIRBuilderBase
which contains lots of non foldable build methods and their implementation.
Instructions which can be constant folded/transformed are now in a class
called FoldableInstructionBuilder which uses CRTP to use the implementation
of the derived class for buildBinaryOps. Additionally buildInstr in the derived
class can be used to implement other kinds of transformations.

Also because of separation of state, given a MachineIRBuilder in an API,
if one wishes to use another MachineIRBuilder, a new one can be
constructed from the state locally. For eg,

void doFoo(MachineIRBuilder &B) {
  MyCustomBuilder CustomB(B.getState());
  // Use CustomB for building.
}

reviewed by : aemerson

Added:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
    llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
    llvm/trunk/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

Added: llvm/trunk/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h?rev=329596&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h (added)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h Mon Apr  9 10:30:56 2018
@@ -0,0 +1,134 @@
+//===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h  --*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements a version of MachineIRBuilder which does trivial
+/// constant folding.
+//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+
+namespace llvm {
+
+static Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1,
+                                         const unsigned Op2,
+                                         const MachineRegisterInfo &MRI) {
+  auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI);
+  auto MaybeOp2Cst = getConstantVRegVal(Op2, MRI);
+  if (MaybeOp1Cst && MaybeOp2Cst) {
+    LLT Ty = MRI.getType(Op1);
+    APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true);
+    APInt C2(Ty.getSizeInBits(), *MaybeOp2Cst, true);
+    switch (Opcode) {
+    default:
+      break;
+    case TargetOpcode::G_ADD:
+      return C1 + C2;
+    case TargetOpcode::G_AND:
+      return C1 & C2;
+    case TargetOpcode::G_ASHR:
+      return C1.ashr(C2);
+    case TargetOpcode::G_LSHR:
+      return C1.lshr(C2);
+    case TargetOpcode::G_MUL:
+      return C1 * C2;
+    case TargetOpcode::G_OR:
+      return C1 | C2;
+    case TargetOpcode::G_SHL:
+      return C1 << C2;
+    case TargetOpcode::G_SUB:
+      return C1 - C2;
+    case TargetOpcode::G_XOR:
+      return C1 ^ C2;
+    case TargetOpcode::G_UDIV:
+      if (!C2.getBoolValue())
+        break;
+      return C1.udiv(C2);
+    case TargetOpcode::G_SDIV:
+      if (!C2.getBoolValue())
+        break;
+      return C1.sdiv(C2);
+    case TargetOpcode::G_UREM:
+      if (!C2.getBoolValue())
+        break;
+      return C1.urem(C2);
+    case TargetOpcode::G_SREM:
+      if (!C2.getBoolValue())
+        break;
+      return C1.srem(C2);
+    }
+  }
+  return None;
+}
+
+/// An MIRBuilder which does trivial constant folding of binary ops.
+/// Calls to buildInstr will also try to constant fold binary ops.
+class ConstantFoldingMIRBuilder
+    : public FoldableInstructionsBuilder<ConstantFoldingMIRBuilder> {
+public:
+  // Pull in base class constructors.
+  using FoldableInstructionsBuilder<
+      ConstantFoldingMIRBuilder>::FoldableInstructionsBuilder;
+  // Unhide buildInstr
+  using FoldableInstructionsBuilder<ConstantFoldingMIRBuilder>::buildInstr;
+
+  // Implement buildBinaryOp required by FoldableInstructionsBuilder which
+  // tries to constant fold.
+  MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst,
+                                    unsigned Src0, unsigned Src1) {
+    validateBinaryOp(Dst, Src0, Src1);
+    auto MaybeCst = ConstantFoldBinOp(Opcode, Src0, Src1, getMF().getRegInfo());
+    if (MaybeCst)
+      return buildConstant(Dst, MaybeCst->getSExtValue());
+    return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1);
+  }
+
+  template <typename DstTy, typename UseArg1Ty, typename UseArg2Ty>
+  MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, UseArg1Ty &&Arg1,
+                                 UseArg2Ty &&Arg2) {
+    unsigned Dst = getDestFromArg(Ty);
+    return buildInstr(Opc, Dst, getRegFromArg(std::forward<UseArg1Ty>(Arg1)),
+                      getRegFromArg(std::forward<UseArg2Ty>(Arg2)));
+  }
+
+  // Try to provide an overload for buildInstr for binary ops in order to
+  // constant fold.
+  MachineInstrBuilder buildInstr(unsigned Opc, unsigned Dst, unsigned Src0,
+                                 unsigned Src1) {
+    switch (Opc) {
+    default:
+      break;
+    case TargetOpcode::G_ADD:
+    case TargetOpcode::G_AND:
+    case TargetOpcode::G_ASHR:
+    case TargetOpcode::G_LSHR:
+    case TargetOpcode::G_MUL:
+    case TargetOpcode::G_OR:
+    case TargetOpcode::G_SHL:
+    case TargetOpcode::G_SUB:
+    case TargetOpcode::G_XOR:
+    case TargetOpcode::G_UDIV:
+    case TargetOpcode::G_SDIV:
+    case TargetOpcode::G_UREM:
+    case TargetOpcode::G_SREM: {
+      return buildBinaryOp(Opc, Dst, Src0, Src1);
+    }
+    }
+    return buildInstr(Opc).addDef(Dst).addUse(Src0).addUse(Src1);
+  }
+
+  // Fallback implementation of buildInstr.
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
+                                 UseArgsTy &&... Args) {
+    auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
+    addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
+    return MIB;
+  }
+};
+} // namespace llvm

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=329596&r1=329595&r2=329596&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Mon Apr  9 10:30:56 2018
@@ -31,11 +31,10 @@ class MachineFunction;
 class MachineInstr;
 class TargetInstrInfo;
 
-/// Helper class to build MachineInstr.
-/// It keeps internally the insertion point and debug location for all
-/// the new instructions we want to create.
-/// This information can be modify via the related setters.
-class MachineIRBuilder {
+/// Class which stores all the state required in a MachineIRBuilder.
+/// Since MachineIRBuilders will only store state in this object, it allows
+/// to transfer BuilderState between different kinds of MachineIRBuilders.
+struct MachineIRBuilderState {
   /// MachineFunction under construction.
   MachineFunction *MF;
   /// Information used to access the description of the opcodes.
@@ -52,15 +51,23 @@ class MachineIRBuilder {
   /// @}
 
   std::function<void(MachineInstr *)> InsertedInstr;
+};
 
+/// Helper class to build MachineInstr.
+/// It keeps internally the insertion point and debug location for all
+/// the new instructions we want to create.
+/// This information can be modify via the related setters.
+class MachineIRBuilderBase {
+
+  MachineIRBuilderState State;
   const TargetInstrInfo &getTII() {
-    assert(TII && "TargetInstrInfo is not set");
-    return *TII;
+    assert(State.TII && "TargetInstrInfo is not set");
+    return *State.TII;
   }
 
   void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
-  MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Res, unsigned Op0, unsigned Op1);
 
+protected:
   unsigned getDestFromArg(unsigned Reg) { return Reg; }
   unsigned getDestFromArg(LLT Ty) {
     return getMF().getRegInfo().createGenericVirtualRegister(Ty);
@@ -88,30 +95,41 @@ class MachineIRBuilder {
     return MIB->getOperand(0).getReg();
   }
 
+  void validateBinaryOp(unsigned Dst, unsigned Src0, unsigned Src1);
+
 public:
   /// Some constructors for easy use.
-  MachineIRBuilder() = default;
-  MachineIRBuilder(MachineFunction &MF) { setMF(MF); }
-  MachineIRBuilder(MachineInstr &MI) : MachineIRBuilder(*MI.getMF()) {
+  MachineIRBuilderBase() = default;
+  MachineIRBuilderBase(MachineFunction &MF) { setMF(MF); }
+  MachineIRBuilderBase(MachineInstr &MI) : MachineIRBuilderBase(*MI.getMF()) {
     setInstr(MI);
   }
 
+  MachineIRBuilderBase(const MachineIRBuilderState &BState) : State(BState) {}
+
   /// Getter for the function we currently build.
   MachineFunction &getMF() {
-    assert(MF && "MachineFunction is not set");
-    return *MF;
+    assert(State.MF && "MachineFunction is not set");
+    return *State.MF;
   }
 
+  /// Getter for DebugLoc
+  const DebugLoc &getDL() { return State.DL; }
+
+  /// Getter for MRI
+  MachineRegisterInfo *getMRI() { return State.MRI; }
+
+  /// Getter for the State
+  MachineIRBuilderState &getState() { return State; }
+
   /// Getter for the basic block we currently build.
   MachineBasicBlock &getMBB() {
-    assert(MBB && "MachineBasicBlock is not set");
-    return *MBB;
+    assert(State.MBB && "MachineBasicBlock is not set");
+    return *State.MBB;
   }
 
   /// Current insertion point for new instructions.
-  MachineBasicBlock::iterator getInsertPt() {
-    return II;
-  }
+  MachineBasicBlock::iterator getInsertPt() { return State.II; }
 
   /// Set the insertion point before the specified position.
   /// \pre MBB must be in getMF().
@@ -141,10 +159,10 @@ public:
   /// @}
 
   /// Set the debug location to \p DL for all the next build instructions.
-  void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
+  void setDebugLoc(const DebugLoc &DL) { this->State.DL = DL; }
 
   /// Get the current instruction's debug location.
-  DebugLoc getDebugLoc() { return DL; }
+  DebugLoc getDebugLoc() { return State.DL; }
 
   /// Build and insert <empty> = \p Opcode <empty>.
   /// The insertion point is the one set by the last call of either
@@ -155,20 +173,6 @@ public:
   /// \return a MachineInstrBuilder for the newly created instruction.
   MachineInstrBuilder buildInstr(unsigned Opcode);
 
-  /// DAG like Generic method for building arbitrary instructions as above.
-  /// \Opc opcode for the instruction.
-  /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
-  /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
-  /// Uses of type MachineInstrBuilder will perform
-  /// getOperand(0).getReg() to convert to register.
-  template <typename DstTy, typename... UseArgsTy>
-  MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
-                                 UseArgsTy &&... Args) {
-    auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
-    addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
-    return MIB;
-  }
-
   /// Build but don't insert <empty> = \p Opcode <empty>.
   ///
   /// \pre setMF, setBasicBlock or setMI  must have been called.
@@ -226,59 +230,6 @@ public:
   /// \return a MachineInstrBuilder for the newly created instruction.
   MachineInstrBuilder buildGlobalValue(unsigned Res, const GlobalValue *GV);
 
-  /// Build and insert \p Res = G_ADD \p Op0, \p Op1
-  ///
-  /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
-  /// truncated to their width.
-  ///
-  /// \pre setBasicBlock or setMI must have been called.
-  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
-  ///      with the same (scalar or vector) type).
-  ///
-  /// \return a MachineInstrBuilder for the newly created instruction.
-  MachineInstrBuilder buildAdd(unsigned Res, unsigned Op0,
-                               unsigned Op1);
-  template <typename DstTy, typename... UseArgsTy>
-  MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
-    unsigned Res = getDestFromArg(Ty);
-    return buildAdd(Res, (getRegFromArg(UseArgs))...);
-  }
-
-  /// Build and insert \p Res = G_SUB \p Op0, \p Op1
-  ///
-  /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
-  /// truncated to their width.
-  ///
-  /// \pre setBasicBlock or setMI must have been called.
-  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
-  ///      with the same (scalar or vector) type).
-  ///
-  /// \return a MachineInstrBuilder for the newly created instruction.
-  template <typename DstTy, typename... UseArgsTy>
-  MachineInstrBuilder buildSub(DstTy &&Ty, UseArgsTy &&... UseArgs) {
-    unsigned Res = getDestFromArg(Ty);
-    return buildSub(Res, (getRegFromArg(UseArgs))...);
-  }
-  MachineInstrBuilder buildSub(unsigned Res, unsigned Op0,
-                               unsigned Op1);
-
-  /// Build and insert \p Res = G_MUL \p Op0, \p Op1
-  ///
-  /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
-  /// truncated to their width.
-  ///
-  /// \pre setBasicBlock or setMI must have been called.
-  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
-  ///      with the same (scalar or vector) type).
-  ///
-  /// \return a MachineInstrBuilder for the newly created instruction.
-  template <typename DstTy, typename... UseArgsTy>
-  MachineInstrBuilder buildMul(DstTy &&Ty, UseArgsTy &&... UseArgs) {
-    unsigned Res = getDestFromArg(Ty);
-    return buildMul(Res, (getRegFromArg(UseArgs))...);
-  }
-  MachineInstrBuilder buildMul(unsigned Res, unsigned Op0,
-                               unsigned Op1);
 
   /// Build and insert \p Res = G_GEP \p Op0, \p Op1
   ///
@@ -347,38 +298,6 @@ public:
   MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
                                  unsigned Op1, unsigned CarryIn);
 
-  /// Build and insert \p Res = G_AND \p Op0, \p Op1
-  ///
-  /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
-  /// Op1.
-  ///
-  /// \pre setBasicBlock or setMI must have been called.
-  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
-  ///      with the same (scalar or vector) type).
-  ///
-  /// \return a MachineInstrBuilder for the newly created instruction.
-  template <typename DstTy, typename... UseArgsTy>
-  MachineInstrBuilder buildAnd(DstTy &&Dst, UseArgsTy &&... UseArgs) {
-    return buildAnd(getDestFromArg(Dst), getRegFromArg(UseArgs)...);
-  }
-  MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
-                               unsigned Op1);
-
-  /// Build and insert \p Res = G_OR \p Op0, \p Op1
-  ///
-  /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
-  /// Op1.
-  ///
-  /// \pre setBasicBlock or setMI must have been called.
-  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
-  ///      with the same (scalar or vector) type).
-  ///
-  /// \return a MachineInstrBuilder for the newly created instruction.
-  template <typename DstTy, typename... UseArgsTy>
-  MachineInstrBuilder buildOr(DstTy &&Dst, UseArgsTy &&... UseArgs) {
-    return buildOr(getDestFromArg(Dst), getRegFromArg(UseArgs)...);
-  }
-  MachineInstrBuilder buildOr(unsigned Res, unsigned Op0, unsigned Op1);
 
   /// Build and insert \p Res = G_ANYEXT \p Op0
   ///
@@ -804,5 +723,140 @@ public:
                                          MachineMemOperand &MMO);
 };
 
+/// A CRTP class that contains methods for building instructions that can
+/// be constant folded. MachineIRBuilders that want to inherit from this will
+/// need to implement buildBinaryOp (for constant folding binary ops).
+/// Alternatively, they can implement buildInstr(Opc, Dst, Uses...) to perform
+/// additional folding for Opc.
+template <typename Base>
+class FoldableInstructionsBuilder : public MachineIRBuilderBase {
+  Base &base() { return static_cast<Base &>(*this); }
+
+public:
+  using MachineIRBuilderBase::MachineIRBuilderBase;
+  /// Build and insert \p Res = G_ADD \p Op0, \p Op1
+  ///
+  /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+  /// truncated to their width.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+  ///      with the same (scalar or vector) type).
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+
+  MachineInstrBuilder buildAdd(unsigned Dst, unsigned Src0, unsigned Src1) {
+    return base().buildBinaryOp(TargetOpcode::G_ADD, Dst, Src0, Src1);
+  }
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+    unsigned Res = base().getDestFromArg(Ty);
+    return base().buildAdd(Res, (base().getRegFromArg(UseArgs))...);
+  }
+
+  /// Build and insert \p Res = G_SUB \p Op0, \p Op1
+  ///
+  /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+  /// truncated to their width.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+  ///      with the same (scalar or vector) type).
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+
+  MachineInstrBuilder buildSub(unsigned Dst, unsigned Src0, unsigned Src1) {
+    return base().buildBinaryOp(TargetOpcode::G_SUB, Dst, Src0, Src1);
+  }
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildSub(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+    unsigned Res = base().getDestFromArg(Ty);
+    return base().buildSub(Res, (base().getRegFromArg(UseArgs))...);
+  }
+
+  /// Build and insert \p Res = G_MUL \p Op0, \p Op1
+  ///
+  /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+  /// truncated to their width.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+  ///      with the same (scalar or vector) type).
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildMul(unsigned Dst, unsigned Src0, unsigned Src1) {
+    return base().buildBinaryOp(TargetOpcode::G_MUL, Dst, Src0, Src1);
+  }
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildMul(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+    unsigned Res = base().getDestFromArg(Ty);
+    return base().buildMul(Res, (base().getRegFromArg(UseArgs))...);
+  }
+
+  /// Build and insert \p Res = G_AND \p Op0, \p Op1
+  ///
+  /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
+  /// Op1.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+  ///      with the same (scalar or vector) type).
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+
+  MachineInstrBuilder buildAnd(unsigned Dst, unsigned Src0, unsigned Src1) {
+    return base().buildBinaryOp(TargetOpcode::G_AND, Dst, Src0, Src1);
+  }
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildAnd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+    unsigned Res = base().getDestFromArg(Ty);
+    return base().buildAnd(Res, (base().getRegFromArg(UseArgs))...);
+  }
+
+  /// Build and insert \p Res = G_OR \p Op0, \p Op1
+  ///
+  /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
+  /// Op1.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+  ///      with the same (scalar or vector) type).
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildOr(unsigned Dst, unsigned Src0, unsigned Src1) {
+    return base().buildBinaryOp(TargetOpcode::G_OR, Dst, Src0, Src1);
+  }
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildOr(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+    unsigned Res = base().getDestFromArg(Ty);
+    return base().buildOr(Res, (base().getRegFromArg(UseArgs))...);
+  }
+};
+
+class MachineIRBuilder : public FoldableInstructionsBuilder<MachineIRBuilder> {
+public:
+  using FoldableInstructionsBuilder<
+      MachineIRBuilder>::FoldableInstructionsBuilder;
+  MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst,
+                                    unsigned Src0, unsigned Src1) {
+    validateBinaryOp(Dst, Src0, Src1);
+    return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1);
+  }
+  using FoldableInstructionsBuilder<MachineIRBuilder>::buildInstr;
+  /// DAG like Generic method for building arbitrary instructions as above.
+  /// \Opc opcode for the instruction.
+  /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
+  /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
+  /// Uses of type MachineInstrBuilder will perform
+  /// getOperand(0).getReg() to convert to register.
+  template <typename DstTy, typename... UseArgsTy>
+  MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
+                                 UseArgsTy &&... Args) {
+    auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
+    addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
+    return MIB;
+  }
+};
+
 } // End namespace llvm.
 #endif // LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=329596&r1=329595&r2=329596&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Mon Apr  9 10:30:56 2018
@@ -22,96 +22,99 @@
 
 using namespace llvm;
 
-void MachineIRBuilder::setMF(MachineFunction &MF) {
-  this->MF = &MF;
-  this->MBB = nullptr;
-  this->MRI = &MF.getRegInfo();
-  this->TII = MF.getSubtarget().getInstrInfo();
-  this->DL = DebugLoc();
-  this->II = MachineBasicBlock::iterator();
-  this->InsertedInstr = nullptr;
+void MachineIRBuilderBase::setMF(MachineFunction &MF) {
+  State.MF = &MF;
+  State.MBB = nullptr;
+  State.MRI = &MF.getRegInfo();
+  State.TII = MF.getSubtarget().getInstrInfo();
+  State.DL = DebugLoc();
+  State.II = MachineBasicBlock::iterator();
+  State.InsertedInstr = nullptr;
 }
 
-void MachineIRBuilder::setMBB(MachineBasicBlock &MBB) {
-  this->MBB = &MBB;
-  this->II = MBB.end();
+void MachineIRBuilderBase::setMBB(MachineBasicBlock &MBB) {
+  State.MBB = &MBB;
+  State.II = MBB.end();
   assert(&getMF() == MBB.getParent() &&
          "Basic block is in a different function");
 }
 
-void MachineIRBuilder::setInstr(MachineInstr &MI) {
+void MachineIRBuilderBase::setInstr(MachineInstr &MI) {
   assert(MI.getParent() && "Instruction is not part of a basic block");
   setMBB(*MI.getParent());
-  this->II = MI.getIterator();
+  State.II = MI.getIterator();
 }
 
-void MachineIRBuilder::setInsertPt(MachineBasicBlock &MBB,
-                                   MachineBasicBlock::iterator II) {
+void MachineIRBuilderBase::setInsertPt(MachineBasicBlock &MBB,
+                                       MachineBasicBlock::iterator II) {
   assert(MBB.getParent() == &getMF() &&
          "Basic block is in a different function");
-  this->MBB = &MBB;
-  this->II = II;
+  State.MBB = &MBB;
+  State.II = II;
 }
 
-void MachineIRBuilder::recordInsertions(
+void MachineIRBuilderBase::recordInsertions(
     std::function<void(MachineInstr *)> Inserted) {
-  InsertedInstr = std::move(Inserted);
+  State.InsertedInstr = std::move(Inserted);
 }
 
-void MachineIRBuilder::stopRecordingInsertions() {
-  InsertedInstr = nullptr;
+void MachineIRBuilderBase::stopRecordingInsertions() {
+  State.InsertedInstr = nullptr;
 }
 
 //------------------------------------------------------------------------------
 // Build instruction variants.
 //------------------------------------------------------------------------------
 
-MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode) {
+MachineInstrBuilder MachineIRBuilderBase::buildInstr(unsigned Opcode) {
   return insertInstr(buildInstrNoInsert(Opcode));
 }
 
-MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) {
-  MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode));
+MachineInstrBuilder MachineIRBuilderBase::buildInstrNoInsert(unsigned Opcode) {
+  MachineInstrBuilder MIB = BuildMI(getMF(), getDL(), getTII().get(Opcode));
   return MIB;
 }
 
-
-MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
+MachineInstrBuilder MachineIRBuilderBase::insertInstr(MachineInstrBuilder MIB) {
   getMBB().insert(getInsertPt(), MIB);
-  if (InsertedInstr)
-    InsertedInstr(MIB);
+  if (State.InsertedInstr)
+    State.InsertedInstr(MIB);
   return MIB;
 }
 
 MachineInstrBuilder
-MachineIRBuilder::buildDirectDbgValue(unsigned Reg, const MDNode *Variable,
-                                      const MDNode *Expr) {
+MachineIRBuilderBase::buildDirectDbgValue(unsigned Reg, const MDNode *Variable,
+                                          const MDNode *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
-  assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
-         "Expected inlined-at fields to agree");
-  return insertInstr(BuildMI(getMF(), DL, getTII().get(TargetOpcode::DBG_VALUE),
+  assert(
+      cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
+      "Expected inlined-at fields to agree");
+  return insertInstr(BuildMI(getMF(), getDL(),
+                             getTII().get(TargetOpcode::DBG_VALUE),
                              /*IsIndirect*/ false, Reg, Variable, Expr));
 }
 
-MachineInstrBuilder
-MachineIRBuilder::buildIndirectDbgValue(unsigned Reg, const MDNode *Variable,
-                                        const MDNode *Expr) {
+MachineInstrBuilder MachineIRBuilderBase::buildIndirectDbgValue(
+    unsigned Reg, const MDNode *Variable, const MDNode *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
-  assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
-         "Expected inlined-at fields to agree");
-  return insertInstr(BuildMI(getMF(), DL, getTII().get(TargetOpcode::DBG_VALUE),
+  assert(
+      cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
+      "Expected inlined-at fields to agree");
+  return insertInstr(BuildMI(getMF(), getDL(),
+                             getTII().get(TargetOpcode::DBG_VALUE),
                              /*IsIndirect*/ true, Reg, Variable, Expr));
 }
 
-MachineInstrBuilder MachineIRBuilder::buildFIDbgValue(int FI,
-                                                      const MDNode *Variable,
-                                                      const MDNode *Expr) {
+MachineInstrBuilder
+MachineIRBuilderBase::buildFIDbgValue(int FI, const MDNode *Variable,
+                                      const MDNode *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
-  assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
-         "Expected inlined-at fields to agree");
+  assert(
+      cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
+      "Expected inlined-at fields to agree");
   return buildInstr(TargetOpcode::DBG_VALUE)
       .addFrameIndex(FI)
       .addImm(0)
@@ -119,13 +122,13 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addMetadata(Expr);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildConstDbgValue(const Constant &C,
-                                                         const MDNode *Variable,
-                                                         const MDNode *Expr) {
+MachineInstrBuilder MachineIRBuilderBase::buildConstDbgValue(
+    const Constant &C, const MDNode *Variable, const MDNode *Expr) {
   assert(isa<DILocalVariable>(Variable) && "not a variable");
   assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
-  assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
-         "Expected inlined-at fields to agree");
+  assert(
+      cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
+      "Expected inlined-at fields to agree");
   auto MIB = buildInstr(TargetOpcode::DBG_VALUE);
   if (auto *CI = dyn_cast<ConstantInt>(&C)) {
     if (CI->getBitWidth() > 64)
@@ -142,17 +145,18 @@ MachineInstrBuilder MachineIRBuilder::bu
   return MIB.addImm(0).addMetadata(Variable).addMetadata(Expr);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildFrameIndex(unsigned Res, int Idx) {
-  assert(MRI->getType(Res).isPointer() && "invalid operand type");
+MachineInstrBuilder MachineIRBuilderBase::buildFrameIndex(unsigned Res,
+                                                          int Idx) {
+  assert(getMRI()->getType(Res).isPointer() && "invalid operand type");
   return buildInstr(TargetOpcode::G_FRAME_INDEX)
       .addDef(Res)
       .addFrameIndex(Idx);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildGlobalValue(unsigned Res,
-                                                       const GlobalValue *GV) {
-  assert(MRI->getType(Res).isPointer() && "invalid operand type");
-  assert(MRI->getType(Res).getAddressSpace() ==
+MachineInstrBuilder
+MachineIRBuilderBase::buildGlobalValue(unsigned Res, const GlobalValue *GV) {
+  assert(getMRI()->getType(Res).isPointer() && "invalid operand type");
+  assert(getMRI()->getType(Res).getAddressSpace() ==
              GV->getType()->getAddressSpace() &&
          "address space mismatch");
 
@@ -161,29 +165,20 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addGlobalAddress(GV);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildBinaryOp(unsigned Opcode, unsigned Res, unsigned Op0,
-                                               unsigned Op1) {
-  assert((MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()) &&
+void MachineIRBuilderBase::validateBinaryOp(unsigned Res, unsigned Op0,
+                                            unsigned Op1) {
+  assert((getMRI()->getType(Res).isScalar() ||
+          getMRI()->getType(Res).isVector()) &&
          "invalid operand type");
-  assert(MRI->getType(Res) == MRI->getType(Op0) &&
-         MRI->getType(Res) == MRI->getType(Op1) && "type mismatch");
-
-  return buildInstr(Opcode)
-      .addDef(Res)
-      .addUse(Op0)
-      .addUse(Op1);
-}
-
-MachineInstrBuilder MachineIRBuilder::buildAdd(unsigned Res, unsigned Op0,
-                                               unsigned Op1) {
-  return buildBinaryOp(TargetOpcode::G_ADD, Res, Op0, Op1);
+  assert(getMRI()->getType(Res) == getMRI()->getType(Op0) &&
+         getMRI()->getType(Res) == getMRI()->getType(Op1) && "type mismatch");
 }
 
-MachineInstrBuilder MachineIRBuilder::buildGEP(unsigned Res, unsigned Op0,
-                                               unsigned Op1) {
-  assert(MRI->getType(Res).isPointer() &&
-         MRI->getType(Res) == MRI->getType(Op0) && "type mismatch");
-  assert(MRI->getType(Op1).isScalar()  && "invalid offset type");
+MachineInstrBuilder MachineIRBuilderBase::buildGEP(unsigned Res, unsigned Op0,
+                                                   unsigned Op1) {
+  assert(getMRI()->getType(Res).isPointer() &&
+         getMRI()->getType(Res) == getMRI()->getType(Op0) && "type mismatch");
+  assert(getMRI()->getType(Op1).isScalar() && "invalid offset type");
 
   return buildInstr(TargetOpcode::G_GEP)
       .addDef(Res)
@@ -192,8 +187,8 @@ MachineInstrBuilder MachineIRBuilder::bu
 }
 
 Optional<MachineInstrBuilder>
-MachineIRBuilder::materializeGEP(unsigned &Res, unsigned Op0,
-                                 const LLT &ValueTy, uint64_t Value) {
+MachineIRBuilderBase::materializeGEP(unsigned &Res, unsigned Op0,
+                                     const LLT &ValueTy, uint64_t Value) {
   assert(Res == 0 && "Res is a result argument");
   assert(ValueTy.isScalar()  && "invalid offset type");
 
@@ -202,17 +197,18 @@ MachineIRBuilder::materializeGEP(unsigne
     return None;
   }
 
-  Res = MRI->createGenericVirtualRegister(MRI->getType(Op0));
-  unsigned TmpReg = MRI->createGenericVirtualRegister(ValueTy);
+  Res = getMRI()->createGenericVirtualRegister(getMRI()->getType(Op0));
+  unsigned TmpReg = getMRI()->createGenericVirtualRegister(ValueTy);
 
   buildConstant(TmpReg, Value);
   return buildGEP(Res, Op0, TmpReg);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildPtrMask(unsigned Res, unsigned Op0,
-                                                   uint32_t NumBits) {
-  assert(MRI->getType(Res).isPointer() &&
-         MRI->getType(Res) == MRI->getType(Op0) && "type mismatch");
+MachineInstrBuilder MachineIRBuilderBase::buildPtrMask(unsigned Res,
+                                                       unsigned Op0,
+                                                       uint32_t NumBits) {
+  assert(getMRI()->getType(Res).isPointer() &&
+         getMRI()->getType(Res) == getMRI()->getType(Op0) && "type mismatch");
 
   return buildInstr(TargetOpcode::G_PTR_MASK)
       .addDef(Res)
@@ -220,89 +216,70 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addImm(NumBits);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildSub(unsigned Res, unsigned Op0,
-                                               unsigned Op1) {
-  return buildBinaryOp(TargetOpcode::G_SUB, Res, Op0, Op1);
-}
-
-MachineInstrBuilder MachineIRBuilder::buildMul(unsigned Res, unsigned Op0,
-                                               unsigned Op1) {
-  return buildBinaryOp(TargetOpcode::G_MUL, Res, Op0, Op1);
-}
-
-MachineInstrBuilder MachineIRBuilder::buildAnd(unsigned Res, unsigned Op0,
-                                               unsigned Op1) {
-  return buildBinaryOp(TargetOpcode::G_AND, Res, Op0, Op1);
-}
-
-MachineInstrBuilder MachineIRBuilder::buildOr(unsigned Res, unsigned Op0,
-                                              unsigned Op1) {
-  return buildBinaryOp(TargetOpcode::G_OR, Res, Op0, Op1);
-}
-
-MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
+MachineInstrBuilder MachineIRBuilderBase::buildBr(MachineBasicBlock &Dest) {
   return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildBrIndirect(unsigned Tgt) {
-  assert(MRI->getType(Tgt).isPointer() && "invalid branch destination");
+MachineInstrBuilder MachineIRBuilderBase::buildBrIndirect(unsigned Tgt) {
+  assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
   return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
-  assert(MRI->getType(Res) == LLT() || MRI->getType(Op) == LLT() ||
-         MRI->getType(Res) == MRI->getType(Op));
+MachineInstrBuilder MachineIRBuilderBase::buildCopy(unsigned Res, unsigned Op) {
+  assert(getMRI()->getType(Res) == LLT() || getMRI()->getType(Op) == LLT() ||
+         getMRI()->getType(Res) == getMRI()->getType(Op));
   return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res,
-                                                    const ConstantInt &Val) {
-  LLT Ty = MRI->getType(Res);
+MachineInstrBuilder
+MachineIRBuilderBase::buildConstant(unsigned Res, const ConstantInt &Val) {
+  LLT Ty = getMRI()->getType(Res);
 
   assert((Ty.isScalar() || Ty.isPointer()) && "invalid operand type");
 
   const ConstantInt *NewVal = &Val;
   if (Ty.getSizeInBits() != Val.getBitWidth())
-    NewVal = ConstantInt::get(MF->getFunction().getContext(),
+    NewVal = ConstantInt::get(getMF().getFunction().getContext(),
                               Val.getValue().sextOrTrunc(Ty.getSizeInBits()));
 
   return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addCImm(NewVal);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res,
-                                                    int64_t Val) {
-  auto IntN = IntegerType::get(MF->getFunction().getContext(),
-                               MRI->getType(Res).getSizeInBits());
+MachineInstrBuilder MachineIRBuilderBase::buildConstant(unsigned Res,
+                                                        int64_t Val) {
+  auto IntN = IntegerType::get(getMF().getFunction().getContext(),
+                               getMRI()->getType(Res).getSizeInBits());
   ConstantInt *CI = ConstantInt::get(IntN, Val, true);
   return buildConstant(Res, *CI);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res,
-                                                     const ConstantFP &Val) {
-  assert(MRI->getType(Res).isScalar() && "invalid operand type");
+MachineInstrBuilder
+MachineIRBuilderBase::buildFConstant(unsigned Res, const ConstantFP &Val) {
+  assert(getMRI()->getType(Res).isScalar() && "invalid operand type");
 
   return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res, double Val) {
-  LLT DstTy = MRI->getType(Res);
-  auto &Ctx = MF->getFunction().getContext();
+MachineInstrBuilder MachineIRBuilderBase::buildFConstant(unsigned Res,
+                                                         double Val) {
+  LLT DstTy = getMRI()->getType(Res);
+  auto &Ctx = getMF().getFunction().getContext();
   auto *CFP =
       ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getSizeInBits()));
   return buildFConstant(Res, *CFP);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildBrCond(unsigned Tst,
-                                                  MachineBasicBlock &Dest) {
-  assert(MRI->getType(Tst).isScalar() && "invalid operand type");
+MachineInstrBuilder MachineIRBuilderBase::buildBrCond(unsigned Tst,
+                                                      MachineBasicBlock &Dest) {
+  assert(getMRI()->getType(Tst).isScalar() && "invalid operand type");
 
   return buildInstr(TargetOpcode::G_BRCOND).addUse(Tst).addMBB(&Dest);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildLoad(unsigned Res, unsigned Addr,
-                                                MachineMemOperand &MMO) {
-  assert(MRI->getType(Res).isValid() && "invalid operand type");
-  assert(MRI->getType(Addr).isPointer() && "invalid operand type");
+MachineInstrBuilder MachineIRBuilderBase::buildLoad(unsigned Res, unsigned Addr,
+                                                    MachineMemOperand &MMO) {
+  assert(getMRI()->getType(Res).isValid() && "invalid operand type");
+  assert(getMRI()->getType(Addr).isPointer() && "invalid operand type");
 
   return buildInstr(TargetOpcode::G_LOAD)
       .addDef(Res)
@@ -310,10 +287,11 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addMemOperand(&MMO);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildStore(unsigned Val, unsigned Addr,
-                                                 MachineMemOperand &MMO) {
-  assert(MRI->getType(Val).isValid() && "invalid operand type");
-  assert(MRI->getType(Addr).isPointer() && "invalid operand type");
+MachineInstrBuilder MachineIRBuilderBase::buildStore(unsigned Val,
+                                                     unsigned Addr,
+                                                     MachineMemOperand &MMO) {
+  assert(getMRI()->getType(Val).isValid() && "invalid operand type");
+  assert(getMRI()->getType(Addr).isPointer() && "invalid operand type");
 
   return buildInstr(TargetOpcode::G_STORE)
       .addUse(Val)
@@ -321,15 +299,16 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addMemOperand(&MMO);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildUAdde(unsigned Res,
-                                                 unsigned CarryOut,
-                                                 unsigned Op0, unsigned Op1,
-                                                 unsigned CarryIn) {
-  assert(MRI->getType(Res).isScalar() && "invalid operand type");
-  assert(MRI->getType(Res) == MRI->getType(Op0) &&
-         MRI->getType(Res) == MRI->getType(Op1) && "type mismatch");
-  assert(MRI->getType(CarryOut).isScalar() && "invalid operand type");
-  assert(MRI->getType(CarryOut) == MRI->getType(CarryIn) && "type mismatch");
+MachineInstrBuilder MachineIRBuilderBase::buildUAdde(unsigned Res,
+                                                     unsigned CarryOut,
+                                                     unsigned Op0, unsigned Op1,
+                                                     unsigned CarryIn) {
+  assert(getMRI()->getType(Res).isScalar() && "invalid operand type");
+  assert(getMRI()->getType(Res) == getMRI()->getType(Op0) &&
+         getMRI()->getType(Res) == getMRI()->getType(Op1) && "type mismatch");
+  assert(getMRI()->getType(CarryOut).isScalar() && "invalid operand type");
+  assert(getMRI()->getType(CarryOut) == getMRI()->getType(CarryIn) &&
+         "type mismatch");
 
   return buildInstr(TargetOpcode::G_UADDE)
       .addDef(Res)
@@ -339,58 +318,64 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addUse(CarryIn);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildAnyExt(unsigned Res, unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildAnyExt(unsigned Res,
+                                                      unsigned Op) {
   validateTruncExt(Res, Op, true);
   return buildInstr(TargetOpcode::G_ANYEXT).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildSExt(unsigned Res, unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildSExt(unsigned Res, unsigned Op) {
   validateTruncExt(Res, Op, true);
   return buildInstr(TargetOpcode::G_SEXT).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildZExt(unsigned Res, unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildZExt(unsigned Res, unsigned Op) {
   validateTruncExt(Res, Op, true);
   return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder
-MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc, unsigned Res, unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildExtOrTrunc(unsigned ExtOpc,
+                                                          unsigned Res,
+                                                          unsigned Op) {
   assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
           TargetOpcode::G_SEXT == ExtOpc) &&
          "Expecting Extending Opc");
-  assert(MRI->getType(Res).isScalar() || MRI->getType(Res).isVector());
-  assert(MRI->getType(Res).isScalar() == MRI->getType(Op).isScalar());
+  assert(getMRI()->getType(Res).isScalar() ||
+         getMRI()->getType(Res).isVector());
+  assert(getMRI()->getType(Res).isScalar() == getMRI()->getType(Op).isScalar());
 
   unsigned Opcode = TargetOpcode::COPY;
-  if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits())
+  if (getMRI()->getType(Res).getSizeInBits() >
+      getMRI()->getType(Op).getSizeInBits())
     Opcode = ExtOpc;
-  else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits())
+  else if (getMRI()->getType(Res).getSizeInBits() <
+           getMRI()->getType(Op).getSizeInBits())
     Opcode = TargetOpcode::G_TRUNC;
   else
-    assert(MRI->getType(Res) == MRI->getType(Op));
+    assert(getMRI()->getType(Res) == getMRI()->getType(Op));
 
   return buildInstr(Opcode).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res,
-                                                       unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildSExtOrTrunc(unsigned Res,
+                                                           unsigned Op) {
   return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(unsigned Res,
-                                                       unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildZExtOrTrunc(unsigned Res,
+                                                           unsigned Op) {
   return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildAnyExtOrTrunc(unsigned Res,
-                                                         unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildAnyExtOrTrunc(unsigned Res,
+                                                             unsigned Op) {
   return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildCast(unsigned Dst, unsigned Src) {
-  LLT SrcTy = MRI->getType(Src);
-  LLT DstTy = MRI->getType(Dst);
+MachineInstrBuilder MachineIRBuilderBase::buildCast(unsigned Dst,
+                                                    unsigned Src) {
+  LLT SrcTy = getMRI()->getType(Src);
+  LLT DstTy = getMRI()->getType(Dst);
   if (SrcTy == DstTy)
     return buildCopy(Dst, Src);
 
@@ -407,17 +392,18 @@ MachineInstrBuilder MachineIRBuilder::bu
   return buildInstr(Opcode).addDef(Dst).addUse(Src);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildExtract(unsigned Res, unsigned Src,
-                                                   uint64_t Index) {
+MachineInstrBuilder
+MachineIRBuilderBase::buildExtract(unsigned Res, unsigned Src, uint64_t Index) {
 #ifndef NDEBUG
-  assert(MRI->getType(Src).isValid() && "invalid operand type");
-  assert(MRI->getType(Res).isValid() && "invalid operand type");
-  assert(Index + MRI->getType(Res).getSizeInBits() <=
-             MRI->getType(Src).getSizeInBits() &&
+  assert(getMRI()->getType(Src).isValid() && "invalid operand type");
+  assert(getMRI()->getType(Res).isValid() && "invalid operand type");
+  assert(Index + getMRI()->getType(Res).getSizeInBits() <=
+             getMRI()->getType(Src).getSizeInBits() &&
          "extracting off end of register");
 #endif
 
-  if (MRI->getType(Res).getSizeInBits() == MRI->getType(Src).getSizeInBits()) {
+  if (getMRI()->getType(Res).getSizeInBits() ==
+      getMRI()->getType(Src).getSizeInBits()) {
     assert(Index == 0 && "insertion past the end of a register");
     return buildCast(Res, Src);
   }
@@ -428,25 +414,25 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addImm(Index);
 }
 
-void MachineIRBuilder::buildSequence(unsigned Res, ArrayRef<unsigned> Ops,
-                                     ArrayRef<uint64_t> Indices) {
+void MachineIRBuilderBase::buildSequence(unsigned Res, ArrayRef<unsigned> Ops,
+                                         ArrayRef<uint64_t> Indices) {
 #ifndef NDEBUG
   assert(Ops.size() == Indices.size() && "incompatible args");
   assert(!Ops.empty() && "invalid trivial sequence");
   assert(std::is_sorted(Indices.begin(), Indices.end()) &&
          "sequence offsets must be in ascending order");
 
-  assert(MRI->getType(Res).isValid() && "invalid operand type");
+  assert(getMRI()->getType(Res).isValid() && "invalid operand type");
   for (auto Op : Ops)
-    assert(MRI->getType(Op).isValid() && "invalid operand type");
+    assert(getMRI()->getType(Op).isValid() && "invalid operand type");
 #endif
 
-  LLT ResTy = MRI->getType(Res);
-  LLT OpTy = MRI->getType(Ops[0]);
+  LLT ResTy = getMRI()->getType(Res);
+  LLT OpTy = getMRI()->getType(Ops[0]);
   unsigned OpSize = OpTy.getSizeInBits();
   bool MaybeMerge = true;
   for (unsigned i = 0; i < Ops.size(); ++i) {
-    if (MRI->getType(Ops[i]) != OpTy || Indices[i] != i * OpSize) {
+    if (getMRI()->getType(Ops[i]) != OpTy || Indices[i] != i * OpSize) {
       MaybeMerge = false;
       break;
     }
@@ -457,31 +443,32 @@ void MachineIRBuilder::buildSequence(uns
     return;
   }
 
-  unsigned ResIn = MRI->createGenericVirtualRegister(ResTy);
+  unsigned ResIn = getMRI()->createGenericVirtualRegister(ResTy);
   buildUndef(ResIn);
 
   for (unsigned i = 0; i < Ops.size(); ++i) {
-    unsigned ResOut =
-        i + 1 == Ops.size() ? Res : MRI->createGenericVirtualRegister(ResTy);
+    unsigned ResOut = i + 1 == Ops.size()
+                          ? Res
+                          : getMRI()->createGenericVirtualRegister(ResTy);
     buildInsert(ResOut, ResIn, Ops[i], Indices[i]);
     ResIn = ResOut;
   }
 }
 
-MachineInstrBuilder MachineIRBuilder::buildUndef(unsigned Res) {
+MachineInstrBuilder MachineIRBuilderBase::buildUndef(unsigned Res) {
   return buildInstr(TargetOpcode::G_IMPLICIT_DEF).addDef(Res);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildMerge(unsigned Res,
-                                                 ArrayRef<unsigned> Ops) {
+MachineInstrBuilder MachineIRBuilderBase::buildMerge(unsigned Res,
+                                                     ArrayRef<unsigned> Ops) {
 
 #ifndef NDEBUG
   assert(!Ops.empty() && "invalid trivial sequence");
-  LLT Ty = MRI->getType(Ops[0]);
+  LLT Ty = getMRI()->getType(Ops[0]);
   for (auto Reg : Ops)
-    assert(MRI->getType(Reg) == Ty && "type mismatch in input list");
-  assert(Ops.size() * MRI->getType(Ops[0]).getSizeInBits() ==
-             MRI->getType(Res).getSizeInBits() &&
+    assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list");
+  assert(Ops.size() * getMRI()->getType(Ops[0]).getSizeInBits() ==
+             getMRI()->getType(Res).getSizeInBits() &&
          "input operands do not cover output register");
 #endif
 
@@ -495,16 +482,16 @@ MachineInstrBuilder MachineIRBuilder::bu
   return MIB;
 }
 
-MachineInstrBuilder MachineIRBuilder::buildUnmerge(ArrayRef<unsigned> Res,
-                                                   unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildUnmerge(ArrayRef<unsigned> Res,
+                                                       unsigned Op) {
 
 #ifndef NDEBUG
   assert(!Res.empty() && "invalid trivial sequence");
-  LLT Ty = MRI->getType(Res[0]);
+  LLT Ty = getMRI()->getType(Res[0]);
   for (auto Reg : Res)
-    assert(MRI->getType(Reg) == Ty && "type mismatch in input list");
-  assert(Res.size() * MRI->getType(Res[0]).getSizeInBits() ==
-             MRI->getType(Op).getSizeInBits() &&
+    assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list");
+  assert(Res.size() * getMRI()->getType(Res[0]).getSizeInBits() ==
+             getMRI()->getType(Op).getSizeInBits() &&
          "input operands do not cover output register");
 #endif
 
@@ -515,13 +502,15 @@ MachineInstrBuilder MachineIRBuilder::bu
   return MIB;
 }
 
-MachineInstrBuilder MachineIRBuilder::buildInsert(unsigned Res, unsigned Src,
-                                                  unsigned Op, unsigned Index) {
-  assert(Index + MRI->getType(Op).getSizeInBits() <=
-             MRI->getType(Res).getSizeInBits() &&
+MachineInstrBuilder MachineIRBuilderBase::buildInsert(unsigned Res,
+                                                      unsigned Src, unsigned Op,
+                                                      unsigned Index) {
+  assert(Index + getMRI()->getType(Op).getSizeInBits() <=
+             getMRI()->getType(Res).getSizeInBits() &&
          "insertion past the end of a register");
 
-  if (MRI->getType(Res).getSizeInBits() == MRI->getType(Op).getSizeInBits()) {
+  if (getMRI()->getType(Res).getSizeInBits() ==
+      getMRI()->getType(Op).getSizeInBits()) {
     return buildCast(Res, Op);
   }
 
@@ -532,9 +521,9 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addImm(Index);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
-                                                     unsigned Res,
-                                                     bool HasSideEffects) {
+MachineInstrBuilder MachineIRBuilderBase::buildIntrinsic(Intrinsic::ID ID,
+                                                         unsigned Res,
+                                                         bool HasSideEffects) {
   auto MIB =
       buildInstr(HasSideEffects ? TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
                                 : TargetOpcode::G_INTRINSIC);
@@ -544,28 +533,30 @@ MachineInstrBuilder MachineIRBuilder::bu
   return MIB;
 }
 
-MachineInstrBuilder MachineIRBuilder::buildTrunc(unsigned Res, unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildTrunc(unsigned Res,
+                                                     unsigned Op) {
   validateTruncExt(Res, Op, false);
   return buildInstr(TargetOpcode::G_TRUNC).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildFPTrunc(unsigned Res, unsigned Op) {
+MachineInstrBuilder MachineIRBuilderBase::buildFPTrunc(unsigned Res,
+                                                       unsigned Op) {
   validateTruncExt(Res, Op, false);
   return buildInstr(TargetOpcode::G_FPTRUNC).addDef(Res).addUse(Op);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred,
-                                                unsigned Res, unsigned Op0,
-                                                unsigned Op1) {
+MachineInstrBuilder MachineIRBuilderBase::buildICmp(CmpInst::Predicate Pred,
+                                                    unsigned Res, unsigned Op0,
+                                                    unsigned Op1) {
 #ifndef NDEBUG
-  assert(MRI->getType(Op0) == MRI->getType(Op0) && "type mismatch");
+  assert(getMRI()->getType(Op0) == getMRI()->getType(Op0) && "type mismatch");
   assert(CmpInst::isIntPredicate(Pred) && "invalid predicate");
-  if (MRI->getType(Op0).isScalar() || MRI->getType(Op0).isPointer())
-    assert(MRI->getType(Res).isScalar() && "type mismatch");
+  if (getMRI()->getType(Op0).isScalar() || getMRI()->getType(Op0).isPointer())
+    assert(getMRI()->getType(Res).isScalar() && "type mismatch");
   else
-    assert(MRI->getType(Res).isVector() &&
-           MRI->getType(Res).getNumElements() ==
-               MRI->getType(Op0).getNumElements() &&
+    assert(getMRI()->getType(Res).isVector() &&
+           getMRI()->getType(Res).getNumElements() ==
+               getMRI()->getType(Op0).getNumElements() &&
            "type mismatch");
 #endif
 
@@ -576,20 +567,21 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addUse(Op1);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred,
-                                                unsigned Res, unsigned Op0,
-                                                unsigned Op1) {
+MachineInstrBuilder MachineIRBuilderBase::buildFCmp(CmpInst::Predicate Pred,
+                                                    unsigned Res, unsigned Op0,
+                                                    unsigned Op1) {
 #ifndef NDEBUG
-  assert((MRI->getType(Op0).isScalar() || MRI->getType(Op0).isVector()) &&
+  assert((getMRI()->getType(Op0).isScalar() ||
+          getMRI()->getType(Op0).isVector()) &&
          "invalid operand type");
-  assert(MRI->getType(Op0) == MRI->getType(Op1) && "type mismatch");
+  assert(getMRI()->getType(Op0) == getMRI()->getType(Op1) && "type mismatch");
   assert(CmpInst::isFPPredicate(Pred) && "invalid predicate");
-  if (MRI->getType(Op0).isScalar())
-    assert(MRI->getType(Res).isScalar() && "type mismatch");
+  if (getMRI()->getType(Op0).isScalar())
+    assert(getMRI()->getType(Res).isScalar() && "type mismatch");
   else
-    assert(MRI->getType(Res).isVector() &&
-           MRI->getType(Res).getNumElements() ==
-               MRI->getType(Op0).getNumElements() &&
+    assert(getMRI()->getType(Res).isVector() &&
+           getMRI()->getType(Res).getNumElements() ==
+               getMRI()->getType(Op0).getNumElements() &&
            "type mismatch");
 #endif
 
@@ -600,21 +592,23 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addUse(Op1);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildSelect(unsigned Res, unsigned Tst,
-                                                  unsigned Op0, unsigned Op1) {
+MachineInstrBuilder MachineIRBuilderBase::buildSelect(unsigned Res,
+                                                      unsigned Tst,
+                                                      unsigned Op0,
+                                                      unsigned Op1) {
 #ifndef NDEBUG
-  LLT ResTy = MRI->getType(Res);
+  LLT ResTy = getMRI()->getType(Res);
   assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
          "invalid operand type");
-  assert(ResTy == MRI->getType(Op0) && ResTy == MRI->getType(Op1) &&
+  assert(ResTy == getMRI()->getType(Op0) && ResTy == getMRI()->getType(Op1) &&
          "type mismatch");
   if (ResTy.isScalar() || ResTy.isPointer())
-    assert(MRI->getType(Tst).isScalar() && "type mismatch");
+    assert(getMRI()->getType(Tst).isScalar() && "type mismatch");
   else
-    assert((MRI->getType(Tst).isScalar() ||
-            (MRI->getType(Tst).isVector() &&
-             MRI->getType(Tst).getNumElements() ==
-                 MRI->getType(Op0).getNumElements())) &&
+    assert((getMRI()->getType(Tst).isScalar() ||
+            (getMRI()->getType(Tst).isVector() &&
+             getMRI()->getType(Tst).getNumElements() ==
+                 getMRI()->getType(Op0).getNumElements())) &&
            "type mismatch");
 #endif
 
@@ -625,15 +619,14 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addUse(Op1);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildInsertVectorElement(unsigned Res,
-                                                               unsigned Val,
-                                                               unsigned Elt,
-                                                               unsigned Idx) {
-#ifndef NDEBUG
-  LLT ResTy = MRI->getType(Res);
-  LLT ValTy = MRI->getType(Val);
-  LLT EltTy = MRI->getType(Elt);
-  LLT IdxTy = MRI->getType(Idx);
+MachineInstrBuilder
+MachineIRBuilderBase::buildInsertVectorElement(unsigned Res, unsigned Val,
+                                               unsigned Elt, unsigned Idx) {
+#ifndef NDEBUG
+  LLT ResTy = getMRI()->getType(Res);
+  LLT ValTy = getMRI()->getType(Val);
+  LLT EltTy = getMRI()->getType(Elt);
+  LLT IdxTy = getMRI()->getType(Idx);
   assert(ResTy.isVector() && ValTy.isVector() && "invalid operand type");
   assert(IdxTy.isScalar() && "invalid operand type");
   assert(ResTy.getNumElements() == ValTy.getNumElements() && "type mismatch");
@@ -647,13 +640,13 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addUse(Idx);
 }
 
-MachineInstrBuilder MachineIRBuilder::buildExtractVectorElement(unsigned Res,
-                                                                unsigned Val,
-                                                                unsigned Idx) {
-#ifndef NDEBUG
-  LLT ResTy = MRI->getType(Res);
-  LLT ValTy = MRI->getType(Val);
-  LLT IdxTy = MRI->getType(Idx);
+MachineInstrBuilder
+MachineIRBuilderBase::buildExtractVectorElement(unsigned Res, unsigned Val,
+                                                unsigned Idx) {
+#ifndef NDEBUG
+  LLT ResTy = getMRI()->getType(Res);
+  LLT ValTy = getMRI()->getType(Val);
+  LLT IdxTy = getMRI()->getType(Idx);
   assert(ValTy.isVector() && "invalid operand type");
   assert((ResTy.isScalar() || ResTy.isPointer()) && "invalid operand type");
   assert(IdxTy.isScalar() && "invalid operand type");
@@ -667,14 +660,14 @@ MachineInstrBuilder MachineIRBuilder::bu
 }
 
 MachineInstrBuilder
-MachineIRBuilder::buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr,
-                                     unsigned CmpVal, unsigned NewVal,
-                                     MachineMemOperand &MMO) {
-#ifndef NDEBUG
-  LLT OldValResTy = MRI->getType(OldValRes);
-  LLT AddrTy = MRI->getType(Addr);
-  LLT CmpValTy = MRI->getType(CmpVal);
-  LLT NewValTy = MRI->getType(NewVal);
+MachineIRBuilderBase::buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr,
+                                         unsigned CmpVal, unsigned NewVal,
+                                         MachineMemOperand &MMO) {
+#ifndef NDEBUG
+  LLT OldValResTy = getMRI()->getType(OldValRes);
+  LLT AddrTy = getMRI()->getType(Addr);
+  LLT CmpValTy = getMRI()->getType(CmpVal);
+  LLT NewValTy = getMRI()->getType(NewVal);
   assert(OldValResTy.isScalar() && "invalid operand type");
   assert(AddrTy.isPointer() && "invalid operand type");
   assert(CmpValTy.isValid() && "invalid operand type");
@@ -691,11 +684,11 @@ MachineIRBuilder::buildAtomicCmpXchg(uns
       .addMemOperand(&MMO);
 }
 
-void MachineIRBuilder::validateTruncExt(unsigned Dst, unsigned Src,
-                                        bool IsExtend) {
+void MachineIRBuilderBase::validateTruncExt(unsigned Dst, unsigned Src,
+                                            bool IsExtend) {
 #ifndef NDEBUG
-  LLT SrcTy = MRI->getType(Src);
-  LLT DstTy = MRI->getType(Dst);
+  LLT SrcTy = getMRI()->getType(Src);
+  LLT DstTy = getMRI()->getType(Dst);
 
   if (DstTy.isVector()) {
     assert(SrcTy.isVector() && "mismatched cast between vecot and non-vector");

Modified: llvm/trunk/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp?rev=329596&r1=329595&r2=329596&view=diff
==============================================================================
--- llvm/trunk/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp (original)
+++ llvm/trunk/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp Mon Apr  9 10:30:56 2018
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
@@ -228,6 +229,35 @@ TEST(PatternMatchInstr, MatchBinaryOp) {
   ASSERT_TRUE(match);
   ASSERT_EQ(Src0, Copies[0]);
   ASSERT_EQ(Src1, Copies[1]);
+
+  // Try to use the FoldableInstructionsBuilder to build binary ops.
+  ConstantFoldingMIRBuilder CFB(B.getState());
+  LLT s32 = LLT::scalar(32);
+  auto MIBCAdd =
+      CFB.buildAdd(s32, CFB.buildConstant(s32, 0), CFB.buildConstant(s32, 1));
+  // This should be a constant now.
+  match = mi_match(MIBCAdd->getOperand(0).getReg(), MRI, m_ICst(Cst));
+  ASSERT_TRUE(match);
+  ASSERT_EQ(Cst, 1);
+  auto MIBCAdd1 =
+      CFB.buildInstr(TargetOpcode::G_ADD, s32, CFB.buildConstant(s32, 0),
+                     CFB.buildConstant(s32, 1));
+  // This should be a constant now.
+  match = mi_match(MIBCAdd1->getOperand(0).getReg(), MRI, m_ICst(Cst));
+  ASSERT_TRUE(match);
+  ASSERT_EQ(Cst, 1);
+
+  // Try one of the other constructors of MachineIRBuilder to make sure it's
+  // compatible.
+  ConstantFoldingMIRBuilder CFB1(*MF);
+  CFB1.setInsertPt(*EntryMBB, EntryMBB->end());
+  auto MIBCSub =
+      CFB1.buildInstr(TargetOpcode::G_SUB, s32, CFB1.buildConstant(s32, 1),
+                      CFB1.buildConstant(s32, 1));
+  // This should be a constant now.
+  match = mi_match(MIBCSub->getOperand(0).getReg(), MRI, m_ICst(Cst));
+  ASSERT_TRUE(match);
+  ASSERT_EQ(Cst, 0);
 }
 
 TEST(PatternMatchInstr, MatchFPUnaryOp) {




More information about the llvm-commits mailing list