[llvm] r277028 - [Hexagon] Implement MI-level constant propagation

Mike Aizatsky via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 29 19:43:13 PDT 2016


Krzysztof,

I think it breaks build bots:

http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/12555

/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp:2052:26:
runtime error: left shift of negative value -2
    #0 0x1010d5d in (anonymous
namespace)::HexagonConstEvaluator::evaluate(llvm::MachineInstr const&,
(anonymous namespace)::MachineConstPropagator::CellMap const&, (anonymous
namespace)::MachineConstPropagator::CellMap&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp:2052:26
    #1 0x101ec38 in (anonymous
namespace)::MachineConstPropagator::visitNonBranch(llvm::MachineInstr
const&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp:652:19
    #2 0x101d238 in (anonymous
namespace)::MachineConstPropagator::propagate(llvm::MachineFunction&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp:906:9
    #3 0x100f8be in (anonymous
namespace)::MachineConstPropagator::run(llvm::MachineFunction&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp:1051:3
    #4 0x100f4ca in (anonymous
namespace)::HexagonConstPropagation::runOnMachineFunction(llvm::MachineFunction&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp:1924:42
    #5 0x1de4382 in
llvm::MachineFunctionPass::runOnFunction(llvm::Function&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/CodeGen/MachineFunctionPass.cpp:60:13
    #6 0x22b341e in llvm::FPPassManager::runOnFunction(llvm::Function&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/IR/LegacyPassManager.cpp:1526:27
    #7 0x22b380b in llvm::FPPassManager::runOnModule(llvm::Module&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/IR/LegacyPassManager.cpp:1547:16
    #8 0x22b4323 in (anonymous
namespace)::MPPassManager::runOnModule(llvm::Module&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/IR/LegacyPassManager.cpp:1603:27
    #9 0x22b3c53 in llvm::legacy::PassManagerImpl::run(llvm::Module&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/lib/IR/LegacyPassManager.cpp:1706:44
    #10 0x8b2418 in compileModule(char**, llvm::LLVMContext&)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/llc/llc.cpp:497:8
    #11 0x8b128a in main
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/llc/llc.cpp:265:22
    #12 0x7efd4f842f44 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #13 0x88af8d in _start
(/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm_build_ubsan/bin/llc+0x88af8d)


On Thu, Jul 28, 2016 at 1:09 PM Krzysztof Parzyszek via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: kparzysz
> Date: Thu Jul 28 15:01:59 2016
> New Revision: 277028
>
> URL: http://llvm.org/viewvc/llvm-project?rev=277028&view=rev
> Log:
> [Hexagon] Implement MI-level constant propagation
>
> Added:
>     llvm/trunk/lib/Target/Hexagon/HexagonConstPropagation.cpp
>     llvm/trunk/test/CodeGen/Hexagon/constp-clb.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-combine-neg.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-ctb.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-extract.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-physreg.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-rewrite-branches.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-rseq.ll
>     llvm/trunk/test/CodeGen/Hexagon/constp-vsplat.ll
> Modified:
>     llvm/trunk/lib/Target/Hexagon/CMakeLists.txt
>     llvm/trunk/lib/Target/Hexagon/HexagonTargetMachine.cpp
>     llvm/trunk/test/CodeGen/Hexagon/vect/vect-vsplatb.ll
>     llvm/trunk/test/CodeGen/Hexagon/vect/vect-vsplath.ll
>
> Modified: llvm/trunk/lib/Target/Hexagon/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/CMakeLists.txt?rev=277028&r1=277027&r2=277028&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/Hexagon/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Target/Hexagon/CMakeLists.txt Thu Jul 28 15:01:59 2016
> @@ -21,6 +21,7 @@ add_llvm_target(HexagonCodeGen
>    HexagonBranchRelaxation.cpp
>    HexagonCFGOptimizer.cpp
>    HexagonCommonGEP.cpp
> +  HexagonConstPropagation.cpp
>    HexagonCopyToCombine.cpp
>    HexagonEarlyIfConv.cpp
>    HexagonExpandCondsets.cpp
>
> Added: llvm/trunk/lib/Target/Hexagon/HexagonConstPropagation.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonConstPropagation.cpp?rev=277028&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/Target/Hexagon/HexagonConstPropagation.cpp (added)
> +++ llvm/trunk/lib/Target/Hexagon/HexagonConstPropagation.cpp Thu Jul 28
> 15:01:59 2016
> @@ -0,0 +1,3208 @@
> +//===--- HexagonConstPropagation.cpp
> --------------------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "hcp"
> +
> +#include "HexagonInstrInfo.h"
> +#include "HexagonRegisterInfo.h"
> +#include "HexagonSubtarget.h"
> +
> +#include "llvm/ADT/PostOrderIterator.h"
> +#include "llvm/ADT/SetVector.h"
> +#include "llvm/CodeGen/MachineFunction.h"
> +#include "llvm/CodeGen/MachineFunctionPass.h"
> +#include "llvm/CodeGen/MachineInstrBuilder.h"
> +#include "llvm/CodeGen/MachineRegisterInfo.h"
> +#include "llvm/IR/Constants.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Target/TargetInstrInfo.h"
> +
> +#include <map>
> +#include <queue>
> +#include <set>
> +
> +using namespace llvm;
> +
> +namespace {
> +  class LatticeCell;
> +
> +  // Properties of a value that are tracked by the propagation.
> +  // A property that is marked as present (i.e. bit is set) dentes that
> the
> +  // value is known (proven) to have this property. Not all combinations
> +  // of bits make sense, for example Zero and NonZero are mutually
> exclusive,
> +  // but on the other hand, Zero implies Finite. In this case, whenever
> +  // the Zero property is present, Finite should also be present.
> +  class ConstantProperties {
> +  public:
> +    enum {
> +      Unknown   = 0x0000,
> +      Zero      = 0x0001,
> +      NonZero   = 0x0002,
> +      Finite    = 0x0004,
> +      Infinity  = 0x0008,
> +      NaN       = 0x0010,
> +      SignedZero = 0x0020,
> +      NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),
> +      PosOrZero       = 0x0100,
> +      NegOrZero       = 0x0200,
> +      SignProperties  = (PosOrZero|NegOrZero),
> +      Everything      = (NumericProperties|SignProperties)
> +    };
> +
> +    // For a given constant, deduce the set of trackable properties that
> this
> +    // constant has.
> +    static uint32_t deduce(const Constant *C);
> +  };
> +
> +
> +  // A representation of a register as it can appear in a MachineOperand,
> +  // i.e. a pair register:subregister.
> +  struct Register {
> +    unsigned Reg, SubReg;
> +    explicit Register(unsigned R, unsigned SR = 0) : Reg(R), SubReg(SR) {}
> +    explicit Register(const MachineOperand &MO)
> +      : Reg(MO.getReg()), SubReg(MO.getSubReg()) {}
> +    void print(const TargetRegisterInfo *TRI = 0) const {
> +      dbgs() << PrintReg(Reg, TRI, SubReg);
> +    }
> +    bool operator== (const Register &R) const {
> +      return (Reg == R.Reg) && (SubReg == R.SubReg);
> +    }
> +  };
> +
> +
> +  // Lattice cell, based on that was described in the W-Z paper on
> constant
> +  // propagation.
> +  // Latice cell will be allowed to hold multiple constant values. While
> +  // multiple values would normally indicate "bottom", we can still derive
> +  // some useful information from them. For example, comparison X > 0
> +  // could be folded if all the values in the cell associated with X are
> +  // positive.
> +  class LatticeCell {
> +  private:
> +    enum { Normal, Top, Bottom };
> +    static const unsigned MaxCellSize = 4;
> +    unsigned Kind:2;
> +    unsigned Size:3;
> +    unsigned IsSpecial:1;
> +    unsigned :0;
> +
> +  public:
> +    union {
> +      uint32_t Properties;
> +      const Constant *Value;
> +      const Constant *Values[MaxCellSize];
> +    };
> +
> +    LatticeCell() : Kind(Top), Size(0), IsSpecial(false) {
> +      for (unsigned i = 0; i < MaxCellSize; ++i)
> +        Values[i] = 0;
> +    }
> +
> +    bool meet(const LatticeCell &L);
> +    bool add(const Constant *C);
> +    bool add(uint32_t Property);
> +    uint32_t properties() const;
> +    unsigned size() const { return Size; }
> +
> +    LatticeCell &operator= (const LatticeCell &L) {
> +      if (this != &L) {
> +        // This memcpy also copies Properties (when L.Size == 0).
> +        uint32_t N = L.IsSpecial ? sizeof L.Properties
> +                                 : L.Size*sizeof(const Constant*);
> +        memcpy(Values, L.Values, N);
> +        Kind = L.Kind;
> +        Size = L.Size;
> +        IsSpecial = L.IsSpecial;
> +      }
> +      return *this;
> +    }
> +
> +    bool isSingle() const { return size() == 1; }
> +    bool isProperty() const { return IsSpecial; }
> +    bool isTop() const { return Kind == Top; }
> +    bool isBottom() const { return Kind == Bottom; }
> +    bool setBottom() {
> +      bool Changed = (Kind != Bottom);
> +      Kind = Bottom;
> +      Size = 0;
> +      IsSpecial = false;
> +      return Changed;
> +    }
> +    void print(raw_ostream &os) const;
> +
> +  private:
> +    void setProperty() {
> +      IsSpecial = true;
> +      Size = 0;
> +      Kind = Normal;
> +    }
> +    bool convertToProperty();
> +  };
> +
> +  raw_ostream &operator<< (raw_ostream &os, const LatticeCell &L) {
> +    L.print(os);
> +    return os;
> +  }
> +
> +  class MachineConstEvaluator;
> +
> +  class MachineConstPropagator {
> +  public:
> +    MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) {
> +      Bottom.setBottom();
> +    }
> +
> +    // Mapping: vreg -> cell
> +    // The keys are registers _without_ subregisters. This won't allow
> +    // definitions in the form of "vreg:subreg<def> = ...". Such
> definitions
> +    // would be questionable from the point of view of SSA, since the
> "vreg"
> +    // could not be initialized in its entirety (specifically, an
> instruction
> +    // defining the "other part" of "vreg" would also count as a
> definition
> +    // of "vreg", which would violate the SSA).
> +    // If a value of a pair vreg:subreg needs to be obtained, the cell for
> +    // "vreg" needs to be looked up, and then the value of subregister
> "subreg"
> +    // needs to be evaluated.
> +    class CellMap {
> +    public:
> +      CellMap() {
> +        assert(Top.isTop());
> +        Bottom.setBottom();
> +      }
> +      void clear() { Map.clear(); }
> +      bool has(unsigned R) const {
> +        // All non-virtual registers are considered "bottom".
> +        if (!TargetRegisterInfo::isVirtualRegister(R))
> +          return true;
> +        MapType::const_iterator F = Map.find(R);
> +        return F != Map.end();
> +      }
> +      const LatticeCell &get(unsigned R) const {
> +        if (!TargetRegisterInfo::isVirtualRegister(R))
> +          return Bottom;
> +        MapType::const_iterator F = Map.find(R);
> +        if (F != Map.end())
> +          return F->second;
> +        return Top;
> +      }
> +      // Invalidates any const references.
> +      void update(unsigned R, const LatticeCell &L) {
> +        Map[R] = L;
> +      }
> +      void print(raw_ostream &os, const TargetRegisterInfo &TRI) const;
> +    private:
> +      typedef std::map<unsigned,LatticeCell> MapType;
> +      MapType Map;
> +      // To avoid creating "top" entries, return a const reference to
> +      // this cell in "get". Also, have a "Bottom" cell to return from
> +      // get when a value of a physical register is requested.
> +      LatticeCell Top, Bottom;
> +    public:
> +      typedef MapType::const_iterator const_iterator;
> +      const_iterator begin() const { return Map.begin(); }
> +      const_iterator end() const { return Map.end(); }
> +    };
> +
> +    bool run(MachineFunction &MF);
> +
> +  private:
> +    void visitPHI(const MachineInstr &PN);
> +    void visitNonBranch(const MachineInstr &MI);
> +    void visitBranchesFrom(const MachineInstr &BrI);
> +    void visitUsesOf(unsigned R);
> +    bool isExecutable(const MachineBasicBlock *MB) const;
> +    void pushLayoutSuccessor(const MachineBasicBlock *MB);
> +    bool computeBlockSuccessors(const MachineBasicBlock *MB,
> +          SetVector<const MachineBasicBlock*> &Targets);
> +    void removeCFGEdge(MachineBasicBlock *From, MachineBasicBlock *To);
> +
> +    void propagate(MachineFunction &MF);
> +    bool rewrite(MachineFunction &MF);
> +
> +    MachineRegisterInfo      *MRI;
> +    MachineConstEvaluator    &MCE;
> +
> +    typedef std::pair<unsigned,unsigned> CFGEdge;
> +    typedef std::set<CFGEdge> SetOfCFGEdge;
> +    typedef std::set<const MachineInstr*> SetOfInstr;
> +    typedef std::queue<CFGEdge> QueueOfCFGEdge;
> +
> +    LatticeCell     Bottom;
> +    CellMap         Cells;
> +    SetOfCFGEdge    EdgeExec;
> +    SetOfInstr      InstrExec;
> +    QueueOfCFGEdge  FlowQ;
> +  };
> +
> +
> +  // The "evaluator/rewriter" of machine instructions. This is an abstract
> +  // base class that provides the interface that the propagator will use,
> +  // as well as some helper functions that are target-independent.
> +  class MachineConstEvaluator {
> +  public:
> +    MachineConstEvaluator(MachineFunction &Fn)
> +      : TRI(*Fn.getSubtarget().getRegisterInfo()),
> +        MF(Fn), CX(Fn.getFunction()->getContext()) {}
> +    virtual ~MachineConstEvaluator() {}
> +
> +    // The required interface:
> +    // - A set of three "evaluate" functions. Each returns "true" if the
> +    //       computation succeeded, "false" otherwise.
> +    //   (1) Given an instruction MI, and the map with input values
> "Inputs",
> +    //       compute the set of output values "Outputs". An example of
> when
> +    //       the computation can "fail" is if MI is not an instruction
> that
> +    //       is recognized by the evaluator.
> +    //   (2) Given a register R (as reg:subreg), compute the cell that
> +    //       corresponds to the "subreg" part of the given register.
> +    //   (3) Given a branch instruction BrI, compute the set of target
> blocks.
> +    //       If the branch can fall-through, add null (0) to the list of
> +    //       possible targets.
> +    // - A function "rewrite", that given the cell map after propagation,
> +    //   could rewrite instruction MI in a more beneficial form. Return
> +    //   "true" if a change has been made, "false" otherwise.
> +    typedef MachineConstPropagator::CellMap CellMap;
> +    virtual bool evaluate(const MachineInstr &MI, const CellMap &Inputs,
> +                          CellMap &Outputs) = 0;
> +    virtual bool evaluate(const Register &R, const LatticeCell &SrcC,
> +                          LatticeCell &Result) = 0;
> +    virtual bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,
> +                          SetVector<const MachineBasicBlock*> &Targets,
> +                          bool &CanFallThru) = 0;
> +    virtual bool rewrite(MachineInstr &MI, const CellMap &Inputs) = 0;
> +
> +    const TargetRegisterInfo &TRI;
> +
> +  protected:
> +    MachineFunction &MF;
> +    LLVMContext     &CX;
> +
> +    struct Comparison {
> +      enum {
> +        Unk = 0x00,
> +        EQ  = 0x01,
> +        NE  = 0x02,
> +        L   = 0x04, // Less-than property.
> +        G   = 0x08, // Greater-than property.
> +        U   = 0x40, // Unsigned property.
> +        LTs = L,
> +        LEs = L | EQ,
> +        GTs = G,
> +        GEs = G | EQ,
> +        LTu = L      | U,
> +        LEu = L | EQ | U,
> +        GTu = G      | U,
> +        GEu = G | EQ | U
> +      };
> +      static uint32_t negate(uint32_t Cmp) {
> +        if (Cmp == EQ)
> +          return NE;
> +        if (Cmp == NE)
> +          return EQ;
> +        assert((Cmp & (L|G)) != (L|G));
> +        return Cmp ^ (L|G);
> +      }
> +    };
> +
> +    // Helper functions.
> +
> +    bool getCell(const Register &R, const CellMap &Inputs, LatticeCell
> &RC);
> +    bool constToInt(const Constant *C, APInt &Val) const;
> +    bool constToFloat(const Constant *C, APFloat &Val) const;
> +    const ConstantInt *intToConst(const APInt &Val) const;
> +
> +    // Compares.
> +    bool evaluateCMPrr(uint32_t Cmp, const Register &R1, const Register
> &R2,
> +          const CellMap &Inputs, bool &Result);
> +    bool evaluateCMPri(uint32_t Cmp, const Register &R1, const APInt &A2,
> +          const CellMap &Inputs, bool &Result);
> +    bool evaluateCMPrp(uint32_t Cmp, const Register &R1, uint64_t Props2,
> +          const CellMap &Inputs, bool &Result);
> +    bool evaluateCMPii(uint32_t Cmp, const APInt &A1, const APInt &A2,
> +          bool &Result);
> +    bool evaluateCMPpi(uint32_t Cmp, uint32_t Props, const APInt &A2,
> +          bool &Result);
> +    bool evaluateCMPpp(uint32_t Cmp, uint32_t Props1, uint32_t Props2,
> +          bool &Result);
> +
> +    bool evaluateCOPY(const Register &R1, const CellMap &Inputs,
> +          LatticeCell &Result);
> +
> +    // Logical operations.
> +    bool evaluateANDrr(const Register &R1, const Register &R2,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateANDri(const Register &R1, const APInt &A2,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateANDii(const APInt &A1, const APInt &A2, APInt &Result);
> +    bool evaluateORrr(const Register &R1, const Register &R2,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateORri(const Register &R1, const APInt &A2,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateORii(const APInt &A1, const APInt &A2, APInt &Result);
> +    bool evaluateXORrr(const Register &R1, const Register &R2,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateXORri(const Register &R1, const APInt &A2,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateXORii(const APInt &A1, const APInt &A2, APInt &Result);
> +
> +    // Extensions.
> +    bool evaluateZEXTr(const Register &R1, unsigned Width, unsigned Bits,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateZEXTi(const APInt &A1, unsigned Width, unsigned Bits,
> +          APInt &Result);
> +    bool evaluateSEXTr(const Register &R1, unsigned Width, unsigned Bits,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateSEXTi(const APInt &A1, unsigned Width, unsigned Bits,
> +          APInt &Result);
> +
> +    // Leading/trailing bits.
> +    bool evaluateCLBr(const Register &R1, bool Zeros, bool Ones,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateCLBi(const APInt &A1, bool Zeros, bool Ones, APInt
> &Result);
> +    bool evaluateCTBr(const Register &R1, bool Zeros, bool Ones,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateCTBi(const APInt &A1, bool Zeros, bool Ones, APInt
> &Result);
> +
> +    // Bitfield extract.
> +    bool evaluateEXTRACTr(const Register &R1, unsigned Width, unsigned
> Bits,
> +          unsigned Offset, bool Signed, const CellMap &Inputs,
> +          LatticeCell &Result);
> +    bool evaluateEXTRACTi(const APInt &A1, unsigned Bits, unsigned Offset,
> +          bool Signed, APInt &Result);
> +    // Vector operations.
> +    bool evaluateSplatr(const Register &R1, unsigned Bits, unsigned Count,
> +          const CellMap &Inputs, LatticeCell &Result);
> +    bool evaluateSplati(const APInt &A1, unsigned Bits, unsigned Count,
> +          APInt &Result);
> +  };
> +
> +}
> +
> +uint32_t ConstantProperties::deduce(const Constant *C) {
> +  if (isa<ConstantInt>(C)) {
> +    const ConstantInt *CI = cast<ConstantInt>(C);
> +    if (CI->isZero())
> +      return Zero | PosOrZero | NegOrZero | Finite;
> +    uint32_t Props = (NonZero | Finite);
> +    if (CI->isNegative())
> +      return Props | NegOrZero;
> +    return Props | PosOrZero;
> +  }
> +
> +  if (isa<ConstantFP>(C)) {
> +    const ConstantFP *CF = cast<ConstantFP>(C);
> +    uint32_t Props = CF->isNegative() ? (NegOrZero|NonZero)
> +                                      : PosOrZero;
> +    if (CF->isZero())
> +      return (Props & ~NumericProperties) | (Zero|Finite);
> +    Props = (Props & ~NumericProperties) | NonZero;
> +    if (CF->isNaN())
> +      return (Props & ~NumericProperties) | NaN;
> +    const APFloat &Val = CF->getValueAPF();
> +    if (Val.isInfinity())
> +      return (Props & ~NumericProperties) | Infinity;
> +    Props |= Finite;
> +    return Props;
> +  }
> +
> +  return Unknown;
> +}
> +
> +
> +// Convert a cell from a set of specific values to a cell that tracks
> +// properties.
> +bool LatticeCell::convertToProperty() {
> +  if (isProperty())
> +    return false;
> +  // Corner case: converting a fresh (top) cell to "special".
> +  // This can happen, when adding a property to a top cell.
> +  uint32_t Everything = ConstantProperties::Everything;
> +  uint32_t Ps = !isTop() ? properties()
> +                         : Everything;
> +  if (Ps != ConstantProperties::Unknown) {
> +    Properties = Ps;
> +    setProperty();
> +  } else {
> +    setBottom();
> +  }
> +  return true;
> +}
> +
> +
> +void LatticeCell::print(raw_ostream &os) const {
> +  if (isProperty()) {
> +    os << "{ ";
> +    uint32_t Ps = properties();
> +    if (Ps & ConstantProperties::Zero)
> +      os << "zero ";
> +    if (Ps & ConstantProperties::NonZero)
> +      os << "nonzero ";
> +    if (Ps & ConstantProperties::Finite)
> +      os << "finite ";
> +    if (Ps & ConstantProperties::Infinity)
> +      os << "infinity ";
> +    if (Ps & ConstantProperties::NaN)
> +      os << "nan ";
> +    if (Ps & ConstantProperties::PosOrZero)
> +      os << "poz ";
> +    if (Ps & ConstantProperties::NegOrZero)
> +      os << "nez ";
> +    os << '}';
> +    return;
> +  }
> +
> +  os << "{ ";
> +  if (isBottom()) {
> +    os << "bottom";
> +  } else if (isTop()) {
> +    os << "top";
> +  } else {
> +    for (unsigned i = 0; i < size(); ++i) {
> +      const Constant *C = Values[i];
> +      if (i != 0)
> +        os << ", ";
> +      C->print(os);
> +    }
> +  }
> +  os << " }";
> +}
> +
> +
> +// "Meet" operation on two cells. This is the key of the propagation
> +// algorithm.
> +bool LatticeCell::meet(const LatticeCell &L) {
> +  bool Changed = false;
> +  if (L.isBottom())
> +    Changed = setBottom();
> +  if (isBottom() || L.isTop())
> +    return Changed;
> +  if (isTop()) {
> +    *this = L;
> +    // L can be neither Top nor Bottom, so *this must have changed.
> +    return true;
> +  }
> +
> +  // Top/bottom cases covered. Need to integrate L's set into ours.
> +  if (L.isProperty())
> +    return add(L.properties());
> +  for (unsigned i = 0; i < L.size(); ++i) {
> +    const Constant *LC = L.Values[i];
> +    Changed |= add(LC);
> +  }
> +  return Changed;
> +}
> +
> +
> +// Add a new constant to the cell. This is actually where the cell update
> +// happens. If a cell has room for more constants, the new constant is
> added.
> +// Otherwise, the cell is converted to a "property" cell (i.e. a cell that
> +// will track properties of the associated values, and not the values
> +// themselves. Care is taken to handle special cases, like "bottom", etc.
> +bool LatticeCell::add(const Constant *LC) {
> +  assert(LC);
> +  if (isBottom())
> +    return false;
> +
> +  if (!isProperty()) {
> +    // Cell is not special. Try to add the constant here first,
> +    // if there is room.
> +    unsigned Index = 0;
> +    while (Index < Size) {
> +      const Constant *C = Values[Index];
> +      // If the constant is already here, no change is needed.
> +      if (C == LC)
> +        return false;
> +      Index++;
> +    }
> +    if (Index < MaxCellSize) {
> +      Values[Index] = LC;
> +      Kind = Normal;
> +      Size++;
> +      return true;
> +    }
> +  }
> +
> +  bool Changed = false;
> +
> +  // This cell is special, or is not special, but is full. After this
> +  // it will be special.
> +  Changed = convertToProperty();
> +  uint32_t Ps = properties();
> +  uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
> +  if (NewPs == ConstantProperties::Unknown) {
> +    setBottom();
> +    return true;
> +  }
> +  if (Ps != NewPs) {
> +    Properties = NewPs;
> +    Changed = true;
> +  }
> +  return Changed;
> +}
> +
> +
> +// Add a property to the cell. This will force the cell to become a
> property-
> +// tracking cell.
> +bool LatticeCell::add(uint32_t Property) {
> +  bool Changed = convertToProperty();
> +  uint32_t Ps = properties();
> +  if (Ps == (Ps & Property))
> +    return Changed;
> +  Properties = Property & Ps;
> +  return true;
> +}
> +
> +
> +// Return the properties of the values in the cell. This is valid for any
> +// cell, and does not alter the cell itself.
> +uint32_t LatticeCell::properties() const {
> +  if (isProperty())
> +    return Properties;
> +  assert(!isTop() && "Should not call this for a top cell");
> +  if (isBottom())
> +    return ConstantProperties::Unknown;
> +
> +  assert(size() > 0 && "Empty cell");
> +  uint32_t Ps = ConstantProperties::deduce(Values[0]);
> +  for (unsigned i = 1; i < size(); ++i) {
> +    if (Ps == ConstantProperties::Unknown)
> +      break;
> +    Ps &= ConstantProperties::deduce(Values[i]);
> +  }
> +  return Ps;
> +}
> +
> +
> +void MachineConstPropagator::CellMap::print(raw_ostream &os,
> +      const TargetRegisterInfo &TRI) const {
> +  for (auto &I : Map)
> +    dbgs() << "  " << PrintReg(I.first, &TRI) << " -> " << I.second <<
> '\n';
> +}
> +
> +
> +void MachineConstPropagator::visitPHI(const MachineInstr &PN) {
> +  const MachineBasicBlock *MB = PN.getParent();
> +  unsigned MBN = MB->getNumber();
> +  DEBUG(dbgs() << "Visiting FI(BB#" << MBN << "): " << PN);
> +
> +  const MachineOperand &MD = PN.getOperand(0);
> +  Register DefR(MD);
> +  assert(TargetRegisterInfo::isVirtualRegister(DefR.Reg));
> +
> +  bool Changed = false;
> +
> +  // If the def has a sub-register, set the corresponding cell to
> "bottom".
> +  if (DefR.SubReg) {
> +Bottomize:
> +    const LatticeCell &T = Cells.get(DefR.Reg);
> +    Changed = !T.isBottom();
> +    Cells.update(DefR.Reg, Bottom);
> +    if (Changed)
> +      visitUsesOf(DefR.Reg);
> +    return;
> +  }
> +
> +  LatticeCell DefC = Cells.get(DefR.Reg);
> +
> +  for (unsigned i = 1, n = PN.getNumOperands(); i < n; i += 2) {
> +    const MachineBasicBlock *PB = PN.getOperand(i+1).getMBB();
> +    unsigned PBN = PB->getNumber();
> +    if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
> +      DEBUG(dbgs() << "  edge BB#" << PBN << "->BB#" << MBN
> +                   << " not executable\n");
> +      continue;
> +    }
> +    const MachineOperand &SO = PN.getOperand(i);
> +    Register UseR(SO);
> +    // If the input is not a virtual register, we don't really know what
> +    // value it holds.
> +    if (!TargetRegisterInfo::isVirtualRegister(UseR.Reg))
> +      goto Bottomize;
> +    // If there is no cell for an input register, it means top.
> +    if (!Cells.has(UseR.Reg))
> +      continue;
> +
> +    LatticeCell SrcC;
> +    bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
> +    DEBUG(dbgs() << "  edge from BB#" << PBN << ": "
> +                 << PrintReg(UseR.Reg, &MCE.TRI, UseR.SubReg)
> +                 << SrcC << '\n');
> +    Changed |= Eval ? DefC.meet(SrcC)
> +                    : DefC.setBottom();
> +    Cells.update(DefR.Reg, DefC);
> +    if (DefC.isBottom())
> +      break;
> +  }
> +  if (Changed)
> +    visitUsesOf(DefR.Reg);
> +}
> +
> +
> +void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) {
> +  DEBUG(dbgs() << "Visiting MI(BB#" << MI.getParent()->getNumber()
> +               << "): " << MI);
> +  CellMap Outputs;
> +  bool Eval = MCE.evaluate(MI, Cells, Outputs);
> +  DEBUG({
> +    if (Eval) {
> +      dbgs() << "  outputs:";
> +      for (auto &I : Outputs)
> +        dbgs() << ' ' << I.second;
> +      dbgs() << '\n';
> +    }
> +  });
> +
> +  // Update outputs. If the value was not computed, set all the
> +  // def cells to bottom.
> +  for (const MachineOperand &MO : MI.operands()) {
> +    if (!MO.isReg() || !MO.isDef())
> +      continue;
> +    Register DefR(MO);
> +    // Only track virtual registers.
> +    if (!TargetRegisterInfo::isVirtualRegister(DefR.Reg))
> +      continue;
> +    bool Changed = false;
> +    // If the evaluation failed, set cells for all output registers to
> bottom.
> +    if (!Eval) {
> +      const LatticeCell &T = Cells.get(DefR.Reg);
> +      Changed = !T.isBottom();
> +      Cells.update(DefR.Reg, Bottom);
> +    } else {
> +      // Find the corresponding cell in the computed outputs.
> +      // If it's not there, go on to the next def.
> +      if (!Outputs.has(DefR.Reg))
> +        continue;
> +      LatticeCell RC = Cells.get(DefR.Reg);
> +      Changed = RC.meet(Outputs.get(DefR.Reg));
> +      Cells.update(DefR.Reg, RC);
> +    }
> +    if (Changed)
> +      visitUsesOf(DefR.Reg);
> +  }
> +}
> +
> +
> +// \brief Starting at a given branch, visit remaining branches in the
> block.
> +// Traverse over the subsequent branches for as long as the preceding one
> +// can fall through. Add all the possible targets to the flow work queue,
> +// including the potential fall-through to the layout-successor block.
> +void MachineConstPropagator::visitBranchesFrom(const MachineInstr &BrI) {
> +  const MachineBasicBlock &B = *BrI.getParent();
> +  unsigned MBN = B.getNumber();
> +  MachineBasicBlock::const_iterator It = BrI.getIterator();
> +  MachineBasicBlock::const_iterator End = B.end();
> +
> +  SetVector<const MachineBasicBlock*> Targets;
> +  bool EvalOk = true, FallsThru = true;
> +  while (It != End) {
> +    const MachineInstr &MI = *It;
> +    InstrExec.insert(&MI);
> +    DEBUG(dbgs() << "Visiting " << (EvalOk ? "BR" : "br") << "(BB#"
> +                 << MBN << "): " << MI);
> +    // Do not evaluate subsequent branches if the evaluation of any of the
> +    // previous branches failed. Keep iterating over the branches only
> +    // to mark them as executable.
> +    EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);
> +    if (!EvalOk)
> +      FallsThru = true;
> +    if (!FallsThru)
> +      break;
> +    ++It;
> +  }
> +
> +  if (EvalOk) {
> +    // Need to add all CFG successors that lead to EH landing pads.
> +    // There won't be explicit branches to these blocks, but they must
> +    // be processed.
> +    for (const MachineBasicBlock *SB : B.successors()) {
> +      if (SB->isEHPad())
> +        Targets.insert(SB);
> +    }
> +    if (FallsThru) {
> +      const MachineFunction &MF = *B.getParent();
> +      MachineFunction::const_iterator BI = B.getIterator();
> +      MachineFunction::const_iterator Next = std::next(BI);
> +      if (Next != MF.end())
> +        Targets.insert(&*Next);
> +    }
> +  } else {
> +    // If the evaluation of the branches failed, make "Targets" to be the
> +    // set of all successors of the block from the CFG.
> +    // If the evaluation succeeded for all visited branches, then if the
> +    // last one set "FallsThru", then add an edge to the layout successor
> +    // to the targets.
> +    Targets.clear();
> +    DEBUG(dbgs() << "  failed to evaluate a branch...adding all CFG "
> +                    "successors\n");
> +    for (const MachineBasicBlock *SB : B.successors())
> +      Targets.insert(SB);
> +  }
> +
> +  for (const MachineBasicBlock *TB : Targets) {
> +    unsigned TBN = TB->getNumber();
> +    DEBUG(dbgs() << "  pushing edge BB#" << MBN << " -> BB#" << TBN <<
> "\n");
> +    FlowQ.push(CFGEdge(MBN, TBN));
> +  }
> +}
> +
> +
> +void MachineConstPropagator::visitUsesOf(unsigned Reg) {
> +  DEBUG(dbgs() << "Visiting uses of " << PrintReg(Reg, &MCE.TRI)
> +               << Cells.get(Reg) << '\n');
> +  for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
> +    // Do not process non-executable instructions. They can become
> exceutable
> +    // later (via a flow-edge in the work queue). In such case, the
> instruc-
> +    // tion will be visited at that time.
> +    if (!InstrExec.count(&MI))
> +      continue;
> +    if (MI.isPHI())
> +      visitPHI(MI);
> +    else if (!MI.isBranch())
> +      visitNonBranch(MI);
> +    else
> +      visitBranchesFrom(MI);
> +  }
> +}
> +
> +
> +bool MachineConstPropagator::isExecutable(const MachineBasicBlock *MB)
> const {
> +  unsigned MBN = MB->getNumber();
> +  for (const MachineBasicBlock *PB : MB->predecessors()) {
> +    unsigned PBN = PB->getNumber();
> +    if (EdgeExec.count(CFGEdge(PBN, MBN)))
> +      return true;
> +  }
> +  return false;
> +}
> +
> +
> +void MachineConstPropagator::pushLayoutSuccessor(const MachineBasicBlock
> *MB) {
> +  MachineFunction::const_iterator BI = MB->getIterator();
> +  unsigned MBN = MB->getNumber();
> +  unsigned SBN = std::next(BI)->getNumber();
> +  FlowQ.push(CFGEdge(MBN, SBN));
> +}
> +
> +
> +bool MachineConstPropagator::computeBlockSuccessors(const
> MachineBasicBlock *MB,
> +      SetVector<const MachineBasicBlock*> &Targets) {
> +  MachineBasicBlock::const_iterator FirstBr = MB->end();
> +  for (const MachineInstr &MI : *MB) {
> +    if (MI.isDebugValue())
> +      continue;
> +    if (MI.isBranch()) {
> +      FirstBr = MI.getIterator();
> +      break;
> +    }
> +  }
> +
> +  Targets.clear();
> +  MachineBasicBlock::const_iterator End = MB->end();
> +
> +  bool DoNext = true;
> +  for (MachineBasicBlock::const_iterator I = FirstBr; I != End; ++I) {
> +    const MachineInstr &MI = *I;
> +    // Can there be debug instructions between branches?
> +    if (MI.isDebugValue())
> +      continue;
> +    if (!InstrExec.count(&MI))
> +      continue;
> +    bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);
> +    if (!Eval)
> +      return false;
> +    if (!DoNext)
> +      break;
> +  }
> +  // If the last branch could fall-through, add block's layout successor.
> +  if (DoNext) {
> +    MachineFunction::const_iterator BI = MB->getIterator();
> +    MachineFunction::const_iterator NextI = std::next(BI);
> +    if (NextI != MB->getParent()->end())
> +      Targets.insert(&*NextI);
> +  }
> +
> +  // Add all the EH landing pads.
> +  for (const MachineBasicBlock *SB : MB->successors())
> +    if (SB->isEHPad())
> +      Targets.insert(SB);
> +
> +  return true;
> +}
> +
> +
> +void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From,
> +      MachineBasicBlock *To) {
> +  // First, remove the CFG successor/predecessor information.
> +  From->removeSuccessor(To);
> +  // Remove all corresponding PHI operands in the To block.
> +  for (auto I = To->begin(), E = To->getFirstNonPHI(); I != E; ++I) {
> +    MachineInstr *PN = &*I;
> +    // reg0 = PHI reg1, bb2, reg3, bb4, ...
> +    int N = PN->getNumOperands()-2;
> +    while (N > 0) {
> +      if (PN->getOperand(N+1).getMBB() == From) {
> +        PN->RemoveOperand(N+1);
> +        PN->RemoveOperand(N);
> +      }
> +      N -= 2;
> +    }
> +  }
> +}
> +
> +
> +void MachineConstPropagator::propagate(MachineFunction &MF) {
> +  MachineBasicBlock *Entry =
> GraphTraits<MachineFunction*>::getEntryNode(&MF);
> +  unsigned EntryNum = Entry->getNumber();
> +
> +  // Start with a fake edge, just to process the entry node.
> +  FlowQ.push(CFGEdge(EntryNum, EntryNum));
> +
> +  while (!FlowQ.empty()) {
> +    CFGEdge Edge = FlowQ.front();
> +    FlowQ.pop();
> +
> +    DEBUG(dbgs() << "Picked edge BB#" << Edge.first << "->BB#"
> +                 << Edge.second << '\n');
> +    if (Edge.first != EntryNum)
> +      if (EdgeExec.count(Edge))
> +        continue;
> +    EdgeExec.insert(Edge);
> +    MachineBasicBlock *SB = MF.getBlockNumbered(Edge.second);
> +
> +    // Process the block in three stages:
> +    // - visit all PHI nodes,
> +    // - visit all non-branch instructions,
> +    // - visit block branches.
> +    MachineBasicBlock::const_iterator It = SB->begin(), End = SB->end();
> +
> +    // Visit PHI nodes in the successor block.
> +    while (It != End && It->isPHI()) {
> +      InstrExec.insert(&*It);
> +      visitPHI(*It);
> +      ++It;
> +    }
> +
> +    // If the successor block just became executable, visit all
> instructions.
> +    // To see if this is the first time we're visiting it, check the first
> +    // non-debug instruction to see if it is executable.
> +    while (It != End && It->isDebugValue())
> +      ++It;
> +    assert(It == End || !It->isPHI());
> +    // If this block has been visited, go on to the next one.
> +    if (It != End && InstrExec.count(&*It))
> +      continue;
> +    // For now, scan all non-branch instructions. Branches require
> different
> +    // processing.
> +    while (It != End && !It->isBranch()) {
> +      if (!It->isDebugValue()) {
> +        InstrExec.insert(&*It);
> +        visitNonBranch(*It);
> +      }
> +      ++It;
> +    }
> +
> +    // Time to process the end of the block. This is different from
> +    // processing regular (non-branch) instructions, because there can
> +    // be multiple branches in a block, and they can cause the block to
> +    // terminate early.
> +    if (It != End) {
> +      visitBranchesFrom(*It);
> +    } else {
> +      // If the block didn't have a branch, add all successor edges to the
> +      // work queue. (There should really be only one successor in such
> case.)
> +      unsigned SBN = SB->getNumber();
> +      for (const MachineBasicBlock *SSB : SB->successors())
> +        FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
> +    }
> +  } // while (FlowQ)
> +
> +  DEBUG({
> +    dbgs() << "Cells after propagation:\n";
> +    Cells.print(dbgs(), MCE.TRI);
> +    dbgs() << "Dead CFG edges:\n";
> +    for (const MachineBasicBlock &B : MF) {
> +      unsigned BN = B.getNumber();
> +      for (const MachineBasicBlock *SB : B.successors()) {
> +        unsigned SN = SB->getNumber();
> +        if (!EdgeExec.count(CFGEdge(BN, SN)))
> +          dbgs() << "  BB#" << BN << " -> BB#" << SN << '\n';
> +      }
> +    }
> +  });
> +}
> +
> +
> +bool MachineConstPropagator::rewrite(MachineFunction &MF) {
> +  bool Changed = false;
> +  // Rewrite all instructions based on the collected cell information.
> +  //
> +  // Traverse the instructions in a post-order, so that rewriting an
> +  // instruction can make changes "downstream" in terms of control-flow
> +  // without affecting the rewriting process. (We should not change
> +  // instructions that have not yet been visited by the rewriter.)
> +  // The reason for this is that the rewriter can introduce new vregs,
> +  // and replace uses of old vregs (which had corresponding cells
> +  // computed during propagation) with these new vregs (which at this
> +  // point would not have any cells, and would appear to be "top").
> +  // If an attempt was made to evaluate an instruction with a fresh
> +  // "top" vreg, it would cause an error (abend) in the evaluator.
> +
> +  // Collect the post-order-traversal block ordering. The subsequent
> +  // traversal/rewrite will update block successors, so it's safer
> +  // if the visiting order it computed ahead of time.
> +  std::vector<MachineBasicBlock*> POT;
> +  for (MachineBasicBlock *B : post_order(&MF))
> +    if (!B->empty())
> +      POT.push_back(B);
> +
> +  for (MachineBasicBlock *B : POT) {
> +    // Walk the block backwards (which usually begin with the branches).
> +    // If any branch is rewritten, we may need to update the successor
> +    // information for this block. Unless the block's successors can be
> +    // precisely determined (which may not be the case for indirect
> +    // branches), we cannot modify any branch.
> +
> +    // Compute the successor information.
> +    SetVector<const MachineBasicBlock*> Targets;
> +    bool HaveTargets = computeBlockSuccessors(B, Targets);
> +    // Rewrite the executable instructions. Skip branches if we don't
> +    // have block successor information.
> +    for (auto I = B->rbegin(), E = B->rend(); I != E; ++I) {
> +      MachineInstr &MI = *I;
> +      if (InstrExec.count(&MI)) {
> +        if (MI.isBranch() && !HaveTargets)
> +          continue;
> +        Changed |= MCE.rewrite(MI, Cells);
> +      }
> +    }
> +    // The rewriting could rewrite PHI nodes to non-PHI nodes, causing
> +    // regular instructions to appear in between PHI nodes. Bring all
> +    // the PHI nodes to the beginning of the block.
> +    for (auto I = B->begin(), E = B->end(); I != E; ++I) {
> +      if (I->isPHI())
> +        continue;
> +      // I is not PHI. Find the next PHI node P.
> +      auto P = I;
> +      while (++P != E)
> +        if (P->isPHI())
> +          break;
> +      // Not found.
> +      if (P == E)
> +        break;
> +      // Splice P right before I.
> +      B->splice(I, B, P);
> +      // Reset I to point at the just spliced PHI node.
> +      --I;
> +    }
> +    // Update the block successor information: remove unnecessary
> successors.
> +    if (HaveTargets) {
> +      SmallVector<MachineBasicBlock*,2> ToRemove;
> +      for (MachineBasicBlock *SB : B->successors()) {
> +        if (!Targets.count(SB))
> +          ToRemove.push_back(const_cast<MachineBasicBlock*>(SB));
> +        Targets.remove(SB);
> +      }
> +      for (unsigned i = 0, n = ToRemove.size(); i < n; ++i)
> +        removeCFGEdge(B, ToRemove[i]);
> +      // If there are any blocks left in the computed targets, it means
> that
> +      // we think that the block could go somewhere, but the CFG does not.
> +      // This could legitimately happen in blocks that have non-returning
> +      // calls---we would think that the execution can continue, but the
> +      // CFG will not have a successor edge.
> +    }
> +  }
> +  // Need to do some final post-processing.
> +  // If a branch was not executable, it will not get rewritten, but should
> +  // be removed (or replaced with something equivalent to a A2_nop). We
> can't
> +  // erase instructions during rewriting, so this needs to be delayed
> until
> +  // now.
> +  for (MachineBasicBlock &B : MF) {
> +    MachineBasicBlock::iterator I = B.begin(), E = B.end();
> +    while (I != E) {
> +      auto Next = std::next(I);
> +      if (I->isBranch() && !InstrExec.count(&*I))
> +        B.erase(I);
> +      I = Next;
> +    }
> +  }
> +  return Changed;
> +}
> +
> +
> +// This is the constant propagation algorithm as described by
> Wegman-Zadeck.
> +// Most of the terminology comes from there.
> +bool MachineConstPropagator::run(MachineFunction &MF) {
> +  DEBUG(MF.print(dbgs() << "Starting MachineConstPropagator\n", 0));
> +
> +  MRI = &MF.getRegInfo();
> +
> +  Cells.clear();
> +  EdgeExec.clear();
> +  InstrExec.clear();
> +  assert(FlowQ.empty());
> +
> +  propagate(MF);
> +  bool Changed = rewrite(MF);
> +
> +  DEBUG({
> +    dbgs() << "End of MachineConstPropagator (Changed=" << Changed <<
> ")\n";
> +    if (Changed)
> +      MF.print(dbgs(), 0);
> +  });
> +  return Changed;
> +}
> +
> +
> +// --------------------------------------------------------------------
> +// Machine const evaluator.
> +
> +bool MachineConstEvaluator::getCell(const Register &R, const CellMap
> &Inputs,
> +      LatticeCell &RC) {
> +  if (!TargetRegisterInfo::isVirtualRegister(R.Reg))
> +    return false;
> +  const LatticeCell &L = Inputs.get(R.Reg);
> +  if (!R.SubReg) {
> +    RC = L;
> +    return !RC.isBottom();
> +  }
> +  bool Eval = evaluate(R, L, RC);
> +  return Eval && !RC.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::constToInt(const Constant *C,
> +      APInt &Val) const {
> +  const ConstantInt *CI = dyn_cast<ConstantInt>(C);
> +  if (!CI)
> +    return false;
> +  Val = CI->getValue();
> +  return true;
> +}
> +
> +
> +const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val)
> const {
> +  return ConstantInt::get(CX, Val);
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const Register
> &R1,
> +      const Register &R2, const CellMap &Inputs, bool &Result) {
> +  assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
> +  LatticeCell LS1, LS2;
> +  if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
> +    return false;
> +
> +  bool IsProp1 = LS1.isProperty();
> +  bool IsProp2 = LS2.isProperty();
> +  if (IsProp1) {
> +    uint32_t Prop1 = LS1.properties();
> +    if (IsProp2)
> +      return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);
> +    uint32_t NegCmp = Comparison::negate(Cmp);
> +    return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);
> +  }
> +  if (IsProp2) {
> +    uint32_t Prop2 = LS2.properties();
> +    return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
> +  }
> +
> +  APInt A;
> +  bool IsTrue = true, IsFalse = true;
> +  for (unsigned i = 0; i < LS2.size(); ++i) {
> +    bool Res;
> +    bool Computed = constToInt(LS2.Values[i], A) &&
> +                    evaluateCMPri(Cmp, R1, A, Inputs, Res);
> +    if (!Computed)
> +      return false;
> +    IsTrue &= Res;
> +    IsFalse &= !Res;
> +  }
> +  assert(!IsTrue || !IsFalse);
> +  // The actual logical value of the comparison is same as IsTrue.
> +  Result = IsTrue;
> +  // Return true if the result was proven to be true or proven to be
> false.
> +  return IsTrue || IsFalse;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const Register
> &R1,
> +      const APInt &A2, const CellMap &Inputs, bool &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS;
> +  if (!getCell(R1, Inputs, LS))
> +    return false;
> +  if (LS.isProperty())
> +    return evaluateCMPpi(Cmp, LS.properties(), A2, Result);
> +
> +  APInt A;
> +  bool IsTrue = true, IsFalse = true;
> +  for (unsigned i = 0; i < LS.size(); ++i) {
> +    bool Res;
> +    bool Computed = constToInt(LS.Values[i], A) &&
> +                    evaluateCMPii(Cmp, A, A2, Res);
> +    if (!Computed)
> +      return false;
> +    IsTrue &= Res;
> +    IsFalse &= !Res;
> +  }
> +  assert(!IsTrue || !IsFalse);
> +  // The actual logical value of the comparison is same as IsTrue.
> +  Result = IsTrue;
> +  // Return true if the result was proven to be true or proven to be
> false.
> +  return IsTrue || IsFalse;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const Register
> &R1,
> +      uint64_t Props2, const CellMap &Inputs, bool &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS;
> +  if (!getCell(R1, Inputs, LS))
> +    return false;
> +  if (LS.isProperty())
> +    return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);
> +
> +  APInt A;
> +  uint32_t NegCmp = Comparison::negate(Cmp);
> +  bool IsTrue = true, IsFalse = true;
> +  for (unsigned i = 0; i < LS.size(); ++i) {
> +    bool Res;
> +    bool Computed = constToInt(LS.Values[i], A) &&
> +                    evaluateCMPpi(NegCmp, Props2, A, Res);
> +    if (!Computed)
> +      return false;
> +    IsTrue &= Res;
> +    IsFalse &= !Res;
> +  }
> +  assert(!IsTrue || !IsFalse);
> +  Result = IsTrue;
> +  return IsTrue || IsFalse;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1,
> +      const APInt &A2, bool &Result) {
> +  // NE is a special kind of comparison (not composed of smaller
> properties).
> +  if (Cmp == Comparison::NE) {
> +    Result = !APInt::isSameValue(A1, A2);
> +    return true;
> +  }
> +  if (Cmp == Comparison::EQ) {
> +    Result = APInt::isSameValue(A1, A2);
> +    return true;
> +  }
> +  if (Cmp & Comparison::EQ) {
> +    if (APInt::isSameValue(A1, A2))
> +      return (Result = true);
> +  }
> +  assert((Cmp & (Comparison::L | Comparison::G)) && "Malformed
> comparison");
> +  Result = false;
> +
> +  unsigned W1 = A1.getBitWidth();
> +  unsigned W2 = A2.getBitWidth();
> +  unsigned MaxW = (W1 >= W2) ? W1 : W2;
> +  if (Cmp & Comparison::U) {
> +    const APInt Zx1 = A1.zextOrSelf(MaxW);
> +    const APInt Zx2 = A2.zextOrSelf(MaxW);
> +    if (Cmp & Comparison::L)
> +      Result = Zx1.ult(Zx2);
> +    else if (Cmp & Comparison::G)
> +      Result = Zx2.ult(Zx1);
> +    return true;
> +  }
> +
> +  // Signed comparison.
> +  const APInt Sx1 = A1.sextOrSelf(MaxW);
> +  const APInt Sx2 = A2.sextOrSelf(MaxW);
> +  if (Cmp & Comparison::L)
> +    Result = Sx1.slt(Sx2);
> +  else if (Cmp & Comparison::G)
> +    Result = Sx2.slt(Sx1);
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props,
> +      const APInt &A2, bool &Result) {
> +  if (Props == ConstantProperties::Unknown)
> +    return false;
> +
> +  // Should never see NaN here, but check for it for completeness.
> +  if (Props & ConstantProperties::NaN)
> +    return false;
> +  // Infinity could theoretically be compared to a number, but the
> +  // presence of infinity here would be very suspicious. If we don't
> +  // know for sure that the number is finite, bail out.
> +  if (!(Props & ConstantProperties::Finite))
> +    return false;
> +
> +  // Let X be a number that has properties Props.
> +
> +  if (Cmp & Comparison::U) {
> +    // In case of unsigned comparisons, we can only compare against 0.
> +    if (A2 == 0) {
> +      // Any x!=0 will be considered >0 in an unsigned comparison.
> +      if (Props & ConstantProperties::Zero)
> +        Result = (Cmp & Comparison::EQ);
> +      else if (Props & ConstantProperties::NonZero)
> +        Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);
> +      else
> +        return false;
> +      return true;
> +    }
> +    // A2 is not zero. The only handled case is if X = 0.
> +    if (Props & ConstantProperties::Zero) {
> +      Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);
> +      return true;
> +    }
> +    return false;
> +  }
> +
> +  // Signed comparisons are different.
> +  if (Props & ConstantProperties::Zero) {
> +    if (A2 == 0)
> +      Result = (Cmp & Comparison::EQ);
> +    else
> +      Result = (Cmp == Comparison::NE) ||
> +               ((Cmp & Comparison::L) && !A2.isNegative()) ||
> +               ((Cmp & Comparison::G) &&  A2.isNegative());
> +    return true;
> +  }
> +  if (Props & ConstantProperties::PosOrZero) {
> +    // X >= 0 and !(A2 < 0) => cannot compare
> +    if (!A2.isNegative())
> +      return false;
> +    // X >= 0 and A2 < 0
> +    Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);
> +    return true;
> +  }
> +  if (Props & ConstantProperties::NegOrZero) {
> +    // X <= 0 and Src1 < 0 => cannot compare
> +    if (A2 == 0 || A2.isNegative())
> +      return false;
> +    // X <= 0 and A2 > 0
> +    Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);
> +    return true;
> +  }
> +
> +  return false;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1,
> +      uint32_t Props2, bool &Result) {
> +  typedef ConstantProperties P;
> +  if ((Props1 & P::NaN) && (Props2 & P::NaN))
> +    return false;
> +  if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
> +    return false;
> +
> +  bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);
> +  bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
> +  if (Zero1 && Zero2) {
> +    Result = (Cmp & Comparison::EQ);
> +    return true;
> +  }
> +  if (Cmp == Comparison::NE) {
> +    if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
> +      return (Result = true);
> +    return false;
> +  }
> +
> +  if (Cmp & Comparison::U) {
> +    // In unsigned comparisons, we can only compare against a known zero,
> +    // or a known non-zero.
> +    if (Zero1 && NonZero2) {
> +      Result = (Cmp & Comparison::L);
> +      return true;
> +    }
> +    if (NonZero1 && Zero2) {
> +      Result = (Cmp & Comparison::G);
> +      return true;
> +    }
> +    return false;
> +  }
> +
> +  // Signed comparison. The comparison is not NE.
> +  bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
> +  bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
> +  if (Nez1 && Poz2) {
> +    if (NonZero1 || NonZero2) {
> +      Result = (Cmp & Comparison::L);
> +      return true;
> +    }
> +    // Either (or both) could be zero. Can only say that X <= Y.
> +    if ((Cmp & Comparison::EQ) && (Cmp & Comparison::L))
> +      return (Result = true);
> +  }
> +  if (Poz1 && Nez2) {
> +    if (NonZero1 || NonZero2) {
> +      Result = (Cmp & Comparison::G);
> +      return true;
> +    }
> +    // Either (or both) could be zero. Can only say that X >= Y.
> +    if ((Cmp & Comparison::EQ) && (Cmp & Comparison::G))
> +      return (Result = true);
> +  }
> +
> +  return false;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCOPY(const Register &R1,
> +      const CellMap &Inputs, LatticeCell &Result) {
> +  return getCell(R1, Inputs, Result);
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateANDrr(const Register &R1,
> +      const Register &R2, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
> +  const LatticeCell &L1 = Inputs.get(R2.Reg);
> +  const LatticeCell &L2 = Inputs.get(R2.Reg);
> +  // If both sources are bottom, exit. Otherwise try to evaluate ANDri
> +  // with the non-bottom argument passed as the immediate. This is to
> +  // catch cases of ANDing with 0.
> +  if (L2.isBottom()) {
> +    if (L1.isBottom())
> +      return false;
> +    return evaluateANDrr(R2, R1, Inputs, Result);
> +  }
> +  LatticeCell LS2;
> +  if (!evaluate(R2, L2, LS2))
> +    return false;
> +  if (LS2.isBottom() || LS2.isProperty())
> +    return false;
> +
> +  APInt A;
> +  for (unsigned i = 0; i < LS2.size(); ++i) {
> +    LatticeCell RC;
> +    bool Eval = constToInt(LS2.Values[i], A) &&
> +                evaluateANDri(R1, A, Inputs, RC);
> +    if (!Eval)
> +      return false;
> +    Result.meet(RC);
> +  }
> +  return !Result.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateANDri(const Register &R1,
> +      const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  if (A2 == -1)
> +    return getCell(R1, Inputs, Result);
> +  if (A2 == 0) {
> +    LatticeCell RC;
> +    RC.add(intToConst(A2));
> +    // Overwrite Result.
> +    Result = RC;
> +    return true;
> +  }
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom() || LS1.isProperty())
> +    return false;
> +
> +  APInt A, ResA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateANDii(A, A2, ResA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(ResA);
> +    Result.add(C);
> +  }
> +  return !Result.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateANDii(const APInt &A1,
> +      const APInt &A2, APInt &Result) {
> +  Result = A1 & A2;
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateORrr(const Register &R1,
> +      const Register &R2, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
> +  const LatticeCell &L1 = Inputs.get(R2.Reg);
> +  const LatticeCell &L2 = Inputs.get(R2.Reg);
> +  // If both sources are bottom, exit. Otherwise try to evaluate ORri
> +  // with the non-bottom argument passed as the immediate. This is to
> +  // catch cases of ORing with -1.
> +  if (L2.isBottom()) {
> +    if (L1.isBottom())
> +      return false;
> +    return evaluateORrr(R2, R1, Inputs, Result);
> +  }
> +  LatticeCell LS2;
> +  if (!evaluate(R2, L2, LS2))
> +    return false;
> +  if (LS2.isBottom() || LS2.isProperty())
> +    return false;
> +
> +  APInt A;
> +  for (unsigned i = 0; i < LS2.size(); ++i) {
> +    LatticeCell RC;
> +    bool Eval = constToInt(LS2.Values[i], A) &&
> +                evaluateORri(R1, A, Inputs, RC);
> +    if (!Eval)
> +      return false;
> +    Result.meet(RC);
> +  }
> +  return !Result.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateORri(const Register &R1,
> +      const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  if (A2 == 0)
> +    return getCell(R1, Inputs, Result);
> +  if (A2 == -1) {
> +    LatticeCell RC;
> +    RC.add(intToConst(A2));
> +    // Overwrite Result.
> +    Result = RC;
> +    return true;
> +  }
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom() || LS1.isProperty())
> +    return false;
> +
> +  APInt A, ResA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateORii(A, A2, ResA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(ResA);
> +    Result.add(C);
> +  }
> +  return !Result.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateORii(const APInt &A1,
> +      const APInt &A2, APInt &Result) {
> +  Result = A1 | A2;
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateXORrr(const Register &R1,
> +      const Register &R2, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
> +  LatticeCell LS1, LS2;
> +  if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
> +    return false;
> +  if (LS1.isProperty()) {
> +    if (LS1.properties() & ConstantProperties::Zero)
> +      return !(Result = LS2).isBottom();
> +    return false;
> +  }
> +  if (LS2.isProperty()) {
> +    if (LS2.properties() & ConstantProperties::Zero)
> +      return !(Result = LS1).isBottom();
> +    return false;
> +  }
> +
> +  APInt A;
> +  for (unsigned i = 0; i < LS2.size(); ++i) {
> +    LatticeCell RC;
> +    bool Eval = constToInt(LS2.Values[i], A) &&
> +                evaluateXORri(R1, A, Inputs, RC);
> +    if (!Eval)
> +      return false;
> +    Result.meet(RC);
> +  }
> +  return !Result.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateXORri(const Register &R1,
> +      const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isProperty()) {
> +    if (LS1.properties() & ConstantProperties::Zero) {
> +      const Constant *C = intToConst(A2);
> +      Result.add(C);
> +      return !Result.isBottom();
> +    }
> +    return false;
> +  }
> +
> +  APInt A, XA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateXORii(A, A2, XA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(XA);
> +    Result.add(C);
> +  }
> +  return !Result.isBottom();
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateXORii(const APInt &A1,
> +      const APInt &A2, APInt &Result) {
> +  Result = A1 ^ A2;
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateZEXTr(const Register &R1, unsigned
> Width,
> +      unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isProperty())
> +    return false;
> +
> +  APInt A, XA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateZEXTi(A, Width, Bits, XA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(XA);
> +    Result.add(C);
> +  }
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width,
> +      unsigned Bits, APInt &Result) {
> +  unsigned BW = A1.getBitWidth();
> +  assert(Width >= Bits && BW >= Bits);
> +  APInt Mask = APInt::getLowBitsSet(Width, Bits);
> +  Result = A1.zextOrTrunc(Width) & Mask;
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateSEXTr(const Register &R1, unsigned
> Width,
> +      unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom() || LS1.isProperty())
> +    return false;
> +
> +  APInt A, XA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateSEXTi(A, Width, Bits, XA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(XA);
> +    Result.add(C);
> +  }
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width,
> +      unsigned Bits, APInt &Result) {
> +  unsigned BW = A1.getBitWidth();
> +  assert(Width >= Bits && BW >= Bits);
> +  // Special case to make things faster for smaller source widths.
> +  // Sign extension of 0 bits generates 0 as a result. This is consistent
> +  // with what the HW does.
> +  if (Bits == 0) {
> +    Result = APInt(Width, 0);
> +    return true;
> +  }
> +  // In C, shifts by 64 invoke undefined behavior: handle that case in
> APInt.
> +  if (BW <= 64 && Bits != 0) {
> +    int64_t V = A1.getSExtValue();
> +    switch (Bits) {
> +      case 8:
> +        V = static_cast<int8_t>(V);
> +        break;
> +      case 16:
> +        V = static_cast<int16_t>(V);
> +        break;
> +      case 32:
> +        V = static_cast<int32_t>(V);
> +        break;
> +      default:
> +        // Shift left to lose all bits except lower "Bits" bits, then
> shift
> +        // the value back, replicating what was a sign bit after the first
> +        // shift.
> +        V = (V << (64-Bits)) >> (64-Bits);
> +        break;
> +    }
> +    // V is a 64-bit sign-extended value. Convert it to APInt of desired
> +    // width.
> +    Result = APInt(Width, V, true);
> +    return true;
> +  }
> +  // Slow case: the value doesn't fit in int64_t.
> +  if (Bits < BW)
> +    Result = A1.trunc(Bits).sext(Width);
> +  else // Bits == BW
> +    Result = A1.sext(Width);
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCLBr(const Register &R1, bool Zeros,
> +      bool Ones, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom() || LS1.isProperty())
> +    return false;
> +
> +  APInt A, CA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateCLBi(A, Zeros, Ones, CA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(CA);
> +    Result.add(C);
> +  }
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros,
> +      bool Ones, APInt &Result) {
> +  unsigned BW = A1.getBitWidth();
> +  if (!Zeros && !Ones)
> +    return false;
> +  unsigned Count = 0;
> +  if (Zeros && (Count == 0))
> +    Count = A1.countLeadingZeros();
> +  if (Ones && (Count == 0))
> +    Count = A1.countLeadingOnes();
> +  Result = APInt(BW, static_cast<uint64_t>(Count), false);
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCTBr(const Register &R1, bool Zeros,
> +      bool Ones, const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom() || LS1.isProperty())
> +    return false;
> +
> +  APInt A, CA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateCTBi(A, Zeros, Ones, CA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(CA);
> +    Result.add(C);
> +  }
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros,
> +      bool Ones, APInt &Result) {
> +  unsigned BW = A1.getBitWidth();
> +  if (!Zeros && !Ones)
> +    return false;
> +  unsigned Count = 0;
> +  if (Zeros && (Count == 0))
> +    Count = A1.countTrailingZeros();
> +  if (Ones && (Count == 0))
> +    Count = A1.countTrailingOnes();
> +  Result = APInt(BW, static_cast<uint64_t>(Count), false);
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateEXTRACTr(const Register &R1,
> +      unsigned Width, unsigned Bits, unsigned Offset, bool Signed,
> +      const CellMap &Inputs, LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  assert(Bits+Offset <= Width);
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom())
> +    return false;
> +  if (LS1.isProperty()) {
> +    uint32_t Ps = LS1.properties();
> +    if (Ps & ConstantProperties::Zero) {
> +      const Constant *C = intToConst(APInt(Width, 0, false));
> +      Result.add(C);
> +      return true;
> +    }
> +    return false;
> +  }
> +
> +  APInt A, CA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateEXTRACTi(A, Bits, Offset, Signed, CA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(CA);
> +    Result.add(C);
> +  }
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned
> Bits,
> +      unsigned Offset, bool Signed, APInt &Result) {
> +  unsigned BW = A1.getBitWidth();
> +  assert(Bits+Offset <= BW);
> +  // Extracting 0 bits generates 0 as a result (as indicated by the HW
> people).
> +  if (Bits == 0) {
> +    Result = APInt(BW, 0);
> +    return true;
> +  }
> +  if (BW <= 64) {
> +    int64_t V = A1.getZExtValue();
> +    V <<= (64-Bits-Offset);
> +    if (Signed)
> +      V >>= (64-Bits);
> +    else
> +      V = static_cast<uint64_t>(V) >> (64-Bits);
> +    Result = APInt(BW, V, Signed);
> +    return true;
> +  }
> +  if (Signed)
> +    Result = A1.shl(BW-Bits-Offset).ashr(BW-Bits);
> +  else
> +    Result = A1.shl(BW-Bits-Offset).lshr(BW-Bits);
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateSplatr(const Register &R1,
> +      unsigned Bits, unsigned Count, const CellMap &Inputs,
> +      LatticeCell &Result) {
> +  assert(Inputs.has(R1.Reg));
> +  LatticeCell LS1;
> +  if (!getCell(R1, Inputs, LS1))
> +    return false;
> +  if (LS1.isBottom() || LS1.isProperty())
> +    return false;
> +
> +  APInt A, SA;
> +  for (unsigned i = 0; i < LS1.size(); ++i) {
> +    bool Eval = constToInt(LS1.Values[i], A) &&
> +                evaluateSplati(A, Bits, Count, SA);
> +    if (!Eval)
> +      return false;
> +    const Constant *C = intToConst(SA);
> +    Result.add(C);
> +  }
> +  return true;
> +}
> +
> +
> +bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits,
> +      unsigned Count, APInt &Result) {
> +  assert(Count > 0);
> +  unsigned BW = A1.getBitWidth(), SW = Count*Bits;
> +  APInt LoBits = (Bits < BW) ? A1.trunc(Bits) : A1.zextOrSelf(Bits);
> +  if (Count > 1)
> +    LoBits = LoBits.zext(SW);
> +
> +  APInt Res(SW, 0, false);
> +  for (unsigned i = 0; i < Count; ++i) {
> +    Res <<= Bits;
> +    Res |= LoBits;
> +  }
> +  Result = Res;
> +  return true;
> +}
> +
> +
> +// ----------------------------------------------------------------------
> +// Hexagon-specific code.
> +
> +namespace llvm {
> +  FunctionPass *createHexagonConstPropagationPass();
> +  void initializeHexagonConstPropagationPass(PassRegistry &Registry);
> +}
> +
> +namespace {
> +  class HexagonConstEvaluator : public MachineConstEvaluator {
> +  public:
> +    HexagonConstEvaluator(MachineFunction &Fn);
> +
> +    bool evaluate(const MachineInstr &MI, const CellMap &Inputs,
> +          CellMap &Outputs) override;
> +    bool evaluate(const Register &R, const LatticeCell &SrcC,
> +          LatticeCell &Result) override;
> +    bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,
> +          SetVector<const MachineBasicBlock*> &Targets, bool &FallsThru)
> +          override;
> +    bool rewrite(MachineInstr &MI, const CellMap &Inputs) override;
> +
> +
> +  private:
> +    unsigned getRegBitWidth(unsigned Reg) const;
> +
> +    static uint32_t getCmp(unsigned Opc);
> +    static APInt getCmpImm(unsigned Opc, unsigned OpX,
> +          const MachineOperand &MO);
> +    void replaceWithNop(MachineInstr &MI);
> +
> +    bool evaluateHexRSEQ32(Register RL, Register RH, const CellMap
> &Inputs,
> +          LatticeCell &Result);
> +    bool evaluateHexCompare(const MachineInstr &MI, const CellMap &Inputs,
> +          CellMap &Outputs);
> +    // This is suitable to be called for compare-and-jump instructions.
> +    bool evaluateHexCompare2(uint32_t Cmp, const MachineOperand &Src1,
> +          const MachineOperand &Src2, const CellMap &Inputs, bool
> &Result);
> +    bool evaluateHexLogical(const MachineInstr &MI, const CellMap &Inputs,
> +          CellMap &Outputs);
> +    bool evaluateHexCondMove(const MachineInstr &MI, const CellMap
> &Inputs,
> +          CellMap &Outputs);
> +    bool evaluateHexExt(const MachineInstr &MI, const CellMap &Inputs,
> +          CellMap &Outputs);
> +    bool evaluateHexVector1(const MachineInstr &MI, const CellMap &Inputs,
> +          CellMap &Outputs);
> +    bool evaluateHexVector2(const MachineInstr &MI, const CellMap &Inputs,
> +          CellMap &Outputs);
> +
> +    void replaceAllRegUsesWith(unsigned FromReg, unsigned ToReg);
> +    bool rewriteHexBranch(MachineInstr &BrI, const CellMap &Inputs);
> +    bool rewriteHexConstDefs(MachineInstr &MI, const CellMap &Inputs,
> +          bool &AllDefs);
> +    bool rewriteHexConstUses(MachineInstr &MI, const CellMap &Inputs);
> +
> +    MachineRegisterInfo *MRI;
> +    const HexagonInstrInfo &HII;
> +    const HexagonRegisterInfo &HRI;
> +  };
> +
> +
> +  class HexagonConstPropagation : public MachineFunctionPass {
> +  public:
> +    static char ID;
> +    HexagonConstPropagation() : MachineFunctionPass(ID) {
> +      PassRegistry &Registry = *PassRegistry::getPassRegistry();
> +      initializeHexagonConstPropagationPass(Registry);
> +    }
> +    const char *getPassName() const override {
> +      return "Hexagon Constant Propagation";
> +    }
> +    bool runOnMachineFunction(MachineFunction &MF) override {
> +      const Function *F = MF.getFunction();
> +      if (!F)
> +        return false;
> +      if (skipFunction(*F))
> +        return false;
> +
> +      HexagonConstEvaluator HCE(MF);
> +      return MachineConstPropagator(HCE).run(MF);
> +    }
> +  };
> +
> +  char HexagonConstPropagation::ID = 0;
> +}
> +
> +INITIALIZE_PASS(HexagonConstPropagation, "hcp", "Hexagon Constant
> Propagation",
> +                false, false)
> +
> +
> +HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn)
> +  : MachineConstEvaluator(Fn),
> +    HII(*Fn.getSubtarget<HexagonSubtarget>().getInstrInfo()),
> +    HRI(*Fn.getSubtarget<HexagonSubtarget>().getRegisterInfo()) {
> +  MRI = &Fn.getRegInfo();
> +}
> +
> +
> +bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,
> +      const CellMap &Inputs, CellMap &Outputs) {
> +  if (MI.isCall())
> +    return false;
> +  if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg())
> +    return false;
> +  const MachineOperand &MD = MI.getOperand(0);
> +  if (!MD.isDef())
> +    return false;
> +
> +  unsigned Opc = MI.getOpcode();
> +  Register DefR(MD);
> +  assert(!DefR.SubReg);
> +  if (!TargetRegisterInfo::isVirtualRegister(DefR.Reg))
> +    return false;
> +
> +  if (MI.isCopy()) {
> +    LatticeCell RC;
> +    Register SrcR(MI.getOperand(1));
> +    bool Eval = evaluateCOPY(SrcR, Inputs, RC);
> +    if (!Eval)
> +      return false;
> +    Outputs.update(DefR.Reg, RC);
> +    return true;
> +  }
> +  if (MI.isRegSequence()) {
> +    unsigned Sub1 = MI.getOperand(2).getImm();
> +    unsigned Sub2 = MI.getOperand(4).getImm();
> +    if (Sub1 != Hexagon::subreg_loreg && Sub1 != Hexagon::subreg_hireg)
> +      return false;
> +    if (Sub2 != Hexagon::subreg_loreg && Sub2 != Hexagon::subreg_hireg)
> +      return false;
> +    assert(Sub1 != Sub2);
> +    bool LoIs1 = (Sub1 == Hexagon::subreg_loreg);
> +    const MachineOperand &OpLo = LoIs1 ? MI.getOperand(1) :
> MI.getOperand(3);
> +    const MachineOperand &OpHi = LoIs1 ? MI.getOperand(3) :
> MI.getOperand(1);
> +    LatticeCell RC;
> +    Register SrcRL(OpLo), SrcRH(OpHi);
> +    bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
> +    if (!Eval)
> +      return false;
> +    Outputs.update(DefR.Reg, RC);
> +    return true;
> +  }
> +  if (MI.isCompare()) {
> +    bool Eval = evaluateHexCompare(MI, Inputs, Outputs);
> +    return Eval;
> +  }
> +
> +  switch (Opc) {
> +    defa

-- 
Mike
Sent from phone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160730/cc52c8c3/attachment-0001.html>


More information about the llvm-commits mailing list