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