Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonConstPropagation.cpp
35266 views
//===- HexagonConstPropagation.cpp ----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "HexagonInstrInfo.h"9#include "HexagonRegisterInfo.h"10#include "HexagonSubtarget.h"11#include "llvm/ADT/APFloat.h"12#include "llvm/ADT/APInt.h"13#include "llvm/ADT/PostOrderIterator.h"14#include "llvm/ADT/SetVector.h"15#include "llvm/ADT/SmallVector.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/CodeGen/MachineBasicBlock.h"18#include "llvm/CodeGen/MachineFunction.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20#include "llvm/CodeGen/MachineInstr.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/MachineOperand.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/TargetRegisterInfo.h"25#include "llvm/CodeGen/TargetSubtargetInfo.h"26#include "llvm/IR/Constants.h"27#include "llvm/IR/Type.h"28#include "llvm/Pass.h"29#include "llvm/Support/Casting.h"30#include "llvm/Support/Compiler.h"31#include "llvm/Support/Debug.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/MathExtras.h"34#include "llvm/Support/raw_ostream.h"35#include <cassert>36#include <cstdint>37#include <cstring>38#include <iterator>39#include <map>40#include <queue>41#include <set>42#include <utility>43#include <vector>4445#define DEBUG_TYPE "hcp"4647using namespace llvm;4849namespace {5051// Properties of a value that are tracked by the propagation.52// A property that is marked as present (i.e. bit is set) dentes that the53// value is known (proven) to have this property. Not all combinations54// of bits make sense, for example Zero and NonZero are mutually exclusive,55// but on the other hand, Zero implies Finite. In this case, whenever56// the Zero property is present, Finite should also be present.57class ConstantProperties {58public:59enum {60Unknown = 0x0000,61Zero = 0x0001,62NonZero = 0x0002,63Finite = 0x0004,64Infinity = 0x0008,65NaN = 0x0010,66SignedZero = 0x0020,67NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),68PosOrZero = 0x0100,69NegOrZero = 0x0200,70SignProperties = (PosOrZero|NegOrZero),71Everything = (NumericProperties|SignProperties)72};7374// For a given constant, deduce the set of trackable properties that this75// constant has.76static uint32_t deduce(const Constant *C);77};7879// A representation of a register as it can appear in a MachineOperand,80// i.e. a pair register:subregister.8182// FIXME: Use TargetInstrInfo::RegSubRegPair. Also duplicated in83// HexagonGenPredicate84struct RegisterSubReg {85Register Reg;86unsigned SubReg;8788explicit RegisterSubReg(unsigned R, unsigned SR = 0) : Reg(R), SubReg(SR) {}89explicit RegisterSubReg(const MachineOperand &MO)90: Reg(MO.getReg()), SubReg(MO.getSubReg()) {}9192void print(const TargetRegisterInfo *TRI = nullptr) const {93dbgs() << printReg(Reg, TRI, SubReg);94}9596bool operator== (const RegisterSubReg &R) const {97return (Reg == R.Reg) && (SubReg == R.SubReg);98}99};100101// Lattice cell, based on that was described in the W-Z paper on constant102// propagation.103// Latice cell will be allowed to hold multiple constant values. While104// multiple values would normally indicate "bottom", we can still derive105// some useful information from them. For example, comparison X > 0106// could be folded if all the values in the cell associated with X are107// positive.108class LatticeCell {109private:110enum { Normal, Top, Bottom };111112static const unsigned MaxCellSize = 4;113114unsigned Kind:2;115unsigned Size:3;116unsigned IsSpecial:1;117unsigned :0;118119public:120union {121uint32_t Properties;122const Constant *Value;123const Constant *Values[MaxCellSize];124};125126LatticeCell() : Kind(Top), Size(0), IsSpecial(false) {127for (const Constant *&Value : Values)128Value = nullptr;129}130131bool meet(const LatticeCell &L);132bool add(const Constant *C);133bool add(uint32_t Property);134uint32_t properties() const;135unsigned size() const { return Size; }136137LatticeCell(const LatticeCell &L) {138// This memcpy also copies Properties (when L.Size == 0).139uint32_t N =140L.IsSpecial ? sizeof L.Properties : L.Size * sizeof(const Constant *);141memcpy(Values, L.Values, N);142Kind = L.Kind;143Size = L.Size;144IsSpecial = L.IsSpecial;145}146147LatticeCell &operator=(const LatticeCell &L) {148if (this != &L) {149// This memcpy also copies Properties (when L.Size == 0).150uint32_t N = L.IsSpecial ? sizeof L.Properties151: L.Size * sizeof(const Constant *);152memcpy(Values, L.Values, N);153Kind = L.Kind;154Size = L.Size;155IsSpecial = L.IsSpecial;156}157return *this;158}159160bool isSingle() const { return size() == 1; }161bool isProperty() const { return IsSpecial; }162bool isTop() const { return Kind == Top; }163bool isBottom() const { return Kind == Bottom; }164165bool setBottom() {166bool Changed = (Kind != Bottom);167Kind = Bottom;168Size = 0;169IsSpecial = false;170return Changed;171}172173void print(raw_ostream &os) const;174175private:176void setProperty() {177IsSpecial = true;178Size = 0;179Kind = Normal;180}181182bool convertToProperty();183};184185#ifndef NDEBUG186raw_ostream &operator<< (raw_ostream &os, const LatticeCell &L) {187L.print(os);188return os;189}190#endif191192class MachineConstEvaluator;193194class MachineConstPropagator {195public:196MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) {197Bottom.setBottom();198}199200// Mapping: vreg -> cell201// The keys are registers _without_ subregisters. This won't allow202// definitions in the form of "vreg:subreg = ...". Such definitions203// would be questionable from the point of view of SSA, since the "vreg"204// could not be initialized in its entirety (specifically, an instruction205// defining the "other part" of "vreg" would also count as a definition206// of "vreg", which would violate the SSA).207// If a value of a pair vreg:subreg needs to be obtained, the cell for208// "vreg" needs to be looked up, and then the value of subregister "subreg"209// needs to be evaluated.210class CellMap {211public:212CellMap() {213assert(Top.isTop());214Bottom.setBottom();215}216217void clear() { Map.clear(); }218219bool has(Register R) const {220// All non-virtual registers are considered "bottom".221if (!R.isVirtual())222return true;223MapType::const_iterator F = Map.find(R);224return F != Map.end();225}226227const LatticeCell &get(Register R) const {228if (!R.isVirtual())229return Bottom;230MapType::const_iterator F = Map.find(R);231if (F != Map.end())232return F->second;233return Top;234}235236// Invalidates any const references.237void update(Register R, const LatticeCell &L) { Map[R] = L; }238239void print(raw_ostream &os, const TargetRegisterInfo &TRI) const;240241private:242using MapType = std::map<Register, LatticeCell>;243244MapType Map;245// To avoid creating "top" entries, return a const reference to246// this cell in "get". Also, have a "Bottom" cell to return from247// get when a value of a physical register is requested.248LatticeCell Top, Bottom;249250public:251using const_iterator = MapType::const_iterator;252253const_iterator begin() const { return Map.begin(); }254const_iterator end() const { return Map.end(); }255};256257bool run(MachineFunction &MF);258259private:260void visitPHI(const MachineInstr &PN);261void visitNonBranch(const MachineInstr &MI);262void visitBranchesFrom(const MachineInstr &BrI);263void visitUsesOf(unsigned R);264bool computeBlockSuccessors(const MachineBasicBlock *MB,265SetVector<const MachineBasicBlock*> &Targets);266void removeCFGEdge(MachineBasicBlock *From, MachineBasicBlock *To);267268void propagate(MachineFunction &MF);269bool rewrite(MachineFunction &MF);270271MachineRegisterInfo *MRI = nullptr;272MachineConstEvaluator &MCE;273274using CFGEdge = std::pair<unsigned, unsigned>;275using SetOfCFGEdge = std::set<CFGEdge>;276using SetOfInstr = std::set<const MachineInstr *>;277using QueueOfCFGEdge = std::queue<CFGEdge>;278279LatticeCell Bottom;280CellMap Cells;281SetOfCFGEdge EdgeExec;282SetOfInstr InstrExec;283QueueOfCFGEdge FlowQ;284};285286// The "evaluator/rewriter" of machine instructions. This is an abstract287// base class that provides the interface that the propagator will use,288// as well as some helper functions that are target-independent.289class MachineConstEvaluator {290public:291MachineConstEvaluator(MachineFunction &Fn)292: TRI(*Fn.getSubtarget().getRegisterInfo()),293MF(Fn), CX(Fn.getFunction().getContext()) {}294virtual ~MachineConstEvaluator() = default;295296// The required interface:297// - A set of three "evaluate" functions. Each returns "true" if the298// computation succeeded, "false" otherwise.299// (1) Given an instruction MI, and the map with input values "Inputs",300// compute the set of output values "Outputs". An example of when301// the computation can "fail" is if MI is not an instruction that302// is recognized by the evaluator.303// (2) Given a register R (as reg:subreg), compute the cell that304// corresponds to the "subreg" part of the given register.305// (3) Given a branch instruction BrI, compute the set of target blocks.306// If the branch can fall-through, add null (0) to the list of307// possible targets.308// - A function "rewrite", that given the cell map after propagation,309// could rewrite instruction MI in a more beneficial form. Return310// "true" if a change has been made, "false" otherwise.311using CellMap = MachineConstPropagator::CellMap;312virtual bool evaluate(const MachineInstr &MI, const CellMap &Inputs,313CellMap &Outputs) = 0;314virtual bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC,315LatticeCell &Result) = 0;316virtual bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,317SetVector<const MachineBasicBlock*> &Targets,318bool &CanFallThru) = 0;319virtual bool rewrite(MachineInstr &MI, const CellMap &Inputs) = 0;320321const TargetRegisterInfo &TRI;322323protected:324MachineFunction &MF;325LLVMContext &CX;326327struct Comparison {328enum {329Unk = 0x00,330EQ = 0x01,331NE = 0x02,332L = 0x04, // Less-than property.333G = 0x08, // Greater-than property.334U = 0x40, // Unsigned property.335LTs = L,336LEs = L | EQ,337GTs = G,338GEs = G | EQ,339LTu = L | U,340LEu = L | EQ | U,341GTu = G | U,342GEu = G | EQ | U343};344345static uint32_t negate(uint32_t Cmp) {346if (Cmp == EQ)347return NE;348if (Cmp == NE)349return EQ;350assert((Cmp & (L|G)) != (L|G));351return Cmp ^ (L|G);352}353};354355// Helper functions.356357bool getCell(const RegisterSubReg &R, const CellMap &Inputs, LatticeCell &RC);358bool constToInt(const Constant *C, APInt &Val) const;359const ConstantInt *intToConst(const APInt &Val) const;360361// Compares.362bool evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1, const RegisterSubReg &R2,363const CellMap &Inputs, bool &Result);364bool evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1, const APInt &A2,365const CellMap &Inputs, bool &Result);366bool evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1, uint64_t Props2,367const CellMap &Inputs, bool &Result);368bool evaluateCMPii(uint32_t Cmp, const APInt &A1, const APInt &A2,369bool &Result);370bool evaluateCMPpi(uint32_t Cmp, uint32_t Props, const APInt &A2,371bool &Result);372bool evaluateCMPpp(uint32_t Cmp, uint32_t Props1, uint32_t Props2,373bool &Result);374375bool evaluateCOPY(const RegisterSubReg &R1, const CellMap &Inputs,376LatticeCell &Result);377378// Logical operations.379bool evaluateANDrr(const RegisterSubReg &R1, const RegisterSubReg &R2,380const CellMap &Inputs, LatticeCell &Result);381bool evaluateANDri(const RegisterSubReg &R1, const APInt &A2,382const CellMap &Inputs, LatticeCell &Result);383bool evaluateANDii(const APInt &A1, const APInt &A2, APInt &Result);384bool evaluateORrr(const RegisterSubReg &R1, const RegisterSubReg &R2,385const CellMap &Inputs, LatticeCell &Result);386bool evaluateORri(const RegisterSubReg &R1, const APInt &A2,387const CellMap &Inputs, LatticeCell &Result);388bool evaluateORii(const APInt &A1, const APInt &A2, APInt &Result);389bool evaluateXORrr(const RegisterSubReg &R1, const RegisterSubReg &R2,390const CellMap &Inputs, LatticeCell &Result);391bool evaluateXORri(const RegisterSubReg &R1, const APInt &A2,392const CellMap &Inputs, LatticeCell &Result);393bool evaluateXORii(const APInt &A1, const APInt &A2, APInt &Result);394395// Extensions.396bool evaluateZEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,397const CellMap &Inputs, LatticeCell &Result);398bool evaluateZEXTi(const APInt &A1, unsigned Width, unsigned Bits,399APInt &Result);400bool evaluateSEXTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,401const CellMap &Inputs, LatticeCell &Result);402bool evaluateSEXTi(const APInt &A1, unsigned Width, unsigned Bits,403APInt &Result);404405// Leading/trailing bits.406bool evaluateCLBr(const RegisterSubReg &R1, bool Zeros, bool Ones,407const CellMap &Inputs, LatticeCell &Result);408bool evaluateCLBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);409bool evaluateCTBr(const RegisterSubReg &R1, bool Zeros, bool Ones,410const CellMap &Inputs, LatticeCell &Result);411bool evaluateCTBi(const APInt &A1, bool Zeros, bool Ones, APInt &Result);412413// Bitfield extract.414bool evaluateEXTRACTr(const RegisterSubReg &R1, unsigned Width, unsigned Bits,415unsigned Offset, bool Signed, const CellMap &Inputs,416LatticeCell &Result);417bool evaluateEXTRACTi(const APInt &A1, unsigned Bits, unsigned Offset,418bool Signed, APInt &Result);419// Vector operations.420bool evaluateSplatr(const RegisterSubReg &R1, unsigned Bits, unsigned Count,421const CellMap &Inputs, LatticeCell &Result);422bool evaluateSplati(const APInt &A1, unsigned Bits, unsigned Count,423APInt &Result);424};425426} // end anonymous namespace427428uint32_t ConstantProperties::deduce(const Constant *C) {429if (isa<ConstantInt>(C)) {430const ConstantInt *CI = cast<ConstantInt>(C);431if (CI->isZero())432return Zero | PosOrZero | NegOrZero | Finite;433uint32_t Props = (NonZero | Finite);434if (CI->isNegative())435return Props | NegOrZero;436return Props | PosOrZero;437}438439if (isa<ConstantFP>(C)) {440const ConstantFP *CF = cast<ConstantFP>(C);441uint32_t Props = CF->isNegative() ? (NegOrZero|NonZero)442: PosOrZero;443if (CF->isZero())444return (Props & ~NumericProperties) | (Zero|Finite);445Props = (Props & ~NumericProperties) | NonZero;446if (CF->isNaN())447return (Props & ~NumericProperties) | NaN;448const APFloat &Val = CF->getValueAPF();449if (Val.isInfinity())450return (Props & ~NumericProperties) | Infinity;451Props |= Finite;452return Props;453}454455return Unknown;456}457458// Convert a cell from a set of specific values to a cell that tracks459// properties.460bool LatticeCell::convertToProperty() {461if (isProperty())462return false;463// Corner case: converting a fresh (top) cell to "special".464// This can happen, when adding a property to a top cell.465uint32_t Everything = ConstantProperties::Everything;466uint32_t Ps = !isTop() ? properties()467: Everything;468if (Ps != ConstantProperties::Unknown) {469Properties = Ps;470setProperty();471} else {472setBottom();473}474return true;475}476477#ifndef NDEBUG478void LatticeCell::print(raw_ostream &os) const {479if (isProperty()) {480os << "{ ";481uint32_t Ps = properties();482if (Ps & ConstantProperties::Zero)483os << "zero ";484if (Ps & ConstantProperties::NonZero)485os << "nonzero ";486if (Ps & ConstantProperties::Finite)487os << "finite ";488if (Ps & ConstantProperties::Infinity)489os << "infinity ";490if (Ps & ConstantProperties::NaN)491os << "nan ";492if (Ps & ConstantProperties::PosOrZero)493os << "poz ";494if (Ps & ConstantProperties::NegOrZero)495os << "nez ";496os << '}';497return;498}499500os << "{ ";501if (isBottom()) {502os << "bottom";503} else if (isTop()) {504os << "top";505} else {506for (unsigned i = 0; i < size(); ++i) {507const Constant *C = Values[i];508if (i != 0)509os << ", ";510C->print(os);511}512}513os << " }";514}515#endif516517// "Meet" operation on two cells. This is the key of the propagation518// algorithm.519bool LatticeCell::meet(const LatticeCell &L) {520bool Changed = false;521if (L.isBottom())522Changed = setBottom();523if (isBottom() || L.isTop())524return Changed;525if (isTop()) {526*this = L;527// L can be neither Top nor Bottom, so *this must have changed.528return true;529}530531// Top/bottom cases covered. Need to integrate L's set into ours.532if (L.isProperty())533return add(L.properties());534for (unsigned i = 0; i < L.size(); ++i) {535const Constant *LC = L.Values[i];536Changed |= add(LC);537}538return Changed;539}540541// Add a new constant to the cell. This is actually where the cell update542// happens. If a cell has room for more constants, the new constant is added.543// Otherwise, the cell is converted to a "property" cell (i.e. a cell that544// will track properties of the associated values, and not the values545// themselves. Care is taken to handle special cases, like "bottom", etc.546bool LatticeCell::add(const Constant *LC) {547assert(LC);548if (isBottom())549return false;550551if (!isProperty()) {552// Cell is not special. Try to add the constant here first,553// if there is room.554unsigned Index = 0;555while (Index < Size) {556const Constant *C = Values[Index];557// If the constant is already here, no change is needed.558if (C == LC)559return false;560Index++;561}562if (Index < MaxCellSize) {563Values[Index] = LC;564Kind = Normal;565Size++;566return true;567}568}569570bool Changed = false;571572// This cell is special, or is not special, but is full. After this573// it will be special.574Changed = convertToProperty();575uint32_t Ps = properties();576uint32_t NewPs = Ps & ConstantProperties::deduce(LC);577if (NewPs == ConstantProperties::Unknown) {578setBottom();579return true;580}581if (Ps != NewPs) {582Properties = NewPs;583Changed = true;584}585return Changed;586}587588// Add a property to the cell. This will force the cell to become a property-589// tracking cell.590bool LatticeCell::add(uint32_t Property) {591bool Changed = convertToProperty();592uint32_t Ps = properties();593if (Ps == (Ps & Property))594return Changed;595Properties = Property & Ps;596return true;597}598599// Return the properties of the values in the cell. This is valid for any600// cell, and does not alter the cell itself.601uint32_t LatticeCell::properties() const {602if (isProperty())603return Properties;604assert(!isTop() && "Should not call this for a top cell");605if (isBottom())606return ConstantProperties::Unknown;607608assert(size() > 0 && "Empty cell");609uint32_t Ps = ConstantProperties::deduce(Values[0]);610for (unsigned i = 1; i < size(); ++i) {611if (Ps == ConstantProperties::Unknown)612break;613Ps &= ConstantProperties::deduce(Values[i]);614}615return Ps;616}617618#ifndef NDEBUG619void MachineConstPropagator::CellMap::print(raw_ostream &os,620const TargetRegisterInfo &TRI) const {621for (auto &I : Map)622dbgs() << " " << printReg(I.first, &TRI) << " -> " << I.second << '\n';623}624#endif625626void MachineConstPropagator::visitPHI(const MachineInstr &PN) {627const MachineBasicBlock *MB = PN.getParent();628unsigned MBN = MB->getNumber();629LLVM_DEBUG(dbgs() << "Visiting FI(" << printMBBReference(*MB) << "): " << PN);630631const MachineOperand &MD = PN.getOperand(0);632RegisterSubReg DefR(MD);633assert(DefR.Reg.isVirtual());634635bool Changed = false;636637// If the def has a sub-register, set the corresponding cell to "bottom".638if (DefR.SubReg) {639Bottomize:640const LatticeCell &T = Cells.get(DefR.Reg);641Changed = !T.isBottom();642Cells.update(DefR.Reg, Bottom);643if (Changed)644visitUsesOf(DefR.Reg);645return;646}647648LatticeCell DefC = Cells.get(DefR.Reg);649650for (unsigned i = 1, n = PN.getNumOperands(); i < n; i += 2) {651const MachineBasicBlock *PB = PN.getOperand(i+1).getMBB();652unsigned PBN = PB->getNumber();653if (!EdgeExec.count(CFGEdge(PBN, MBN))) {654LLVM_DEBUG(dbgs() << " edge " << printMBBReference(*PB) << "->"655<< printMBBReference(*MB) << " not executable\n");656continue;657}658const MachineOperand &SO = PN.getOperand(i);659RegisterSubReg UseR(SO);660// If the input is not a virtual register, we don't really know what661// value it holds.662if (!UseR.Reg.isVirtual())663goto Bottomize;664// If there is no cell for an input register, it means top.665if (!Cells.has(UseR.Reg))666continue;667668LatticeCell SrcC;669bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);670LLVM_DEBUG(dbgs() << " edge from " << printMBBReference(*PB) << ": "671<< printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC672<< '\n');673Changed |= Eval ? DefC.meet(SrcC)674: DefC.setBottom();675Cells.update(DefR.Reg, DefC);676if (DefC.isBottom())677break;678}679if (Changed)680visitUsesOf(DefR.Reg);681}682683void MachineConstPropagator::visitNonBranch(const MachineInstr &MI) {684LLVM_DEBUG(dbgs() << "Visiting MI(" << printMBBReference(*MI.getParent())685<< "): " << MI);686CellMap Outputs;687bool Eval = MCE.evaluate(MI, Cells, Outputs);688LLVM_DEBUG({689if (Eval) {690dbgs() << " outputs:";691for (auto &I : Outputs)692dbgs() << ' ' << I.second;693dbgs() << '\n';694}695});696697// Update outputs. If the value was not computed, set all the698// def cells to bottom.699for (const MachineOperand &MO : MI.operands()) {700if (!MO.isReg() || !MO.isDef())701continue;702RegisterSubReg DefR(MO);703// Only track virtual registers.704if (!DefR.Reg.isVirtual())705continue;706bool Changed = false;707// If the evaluation failed, set cells for all output registers to bottom.708if (!Eval) {709const LatticeCell &T = Cells.get(DefR.Reg);710Changed = !T.isBottom();711Cells.update(DefR.Reg, Bottom);712} else {713// Find the corresponding cell in the computed outputs.714// If it's not there, go on to the next def.715if (!Outputs.has(DefR.Reg))716continue;717LatticeCell RC = Cells.get(DefR.Reg);718Changed = RC.meet(Outputs.get(DefR.Reg));719Cells.update(DefR.Reg, RC);720}721if (Changed)722visitUsesOf(DefR.Reg);723}724}725726// Starting at a given branch, visit remaining branches in the block.727// Traverse over the subsequent branches for as long as the preceding one728// can fall through. Add all the possible targets to the flow work queue,729// including the potential fall-through to the layout-successor block.730void MachineConstPropagator::visitBranchesFrom(const MachineInstr &BrI) {731const MachineBasicBlock &B = *BrI.getParent();732unsigned MBN = B.getNumber();733MachineBasicBlock::const_iterator It = BrI.getIterator();734MachineBasicBlock::const_iterator End = B.end();735736SetVector<const MachineBasicBlock*> Targets;737bool EvalOk = true, FallsThru = true;738while (It != End) {739const MachineInstr &MI = *It;740InstrExec.insert(&MI);741LLVM_DEBUG(dbgs() << "Visiting " << (EvalOk ? "BR" : "br") << "("742<< printMBBReference(B) << "): " << MI);743// Do not evaluate subsequent branches if the evaluation of any of the744// previous branches failed. Keep iterating over the branches only745// to mark them as executable.746EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);747if (!EvalOk)748FallsThru = true;749if (!FallsThru)750break;751++It;752}753754if (B.mayHaveInlineAsmBr())755EvalOk = false;756757if (EvalOk) {758// Need to add all CFG successors that lead to EH landing pads.759// There won't be explicit branches to these blocks, but they must760// be processed.761for (const MachineBasicBlock *SB : B.successors()) {762if (SB->isEHPad())763Targets.insert(SB);764}765if (FallsThru) {766const MachineFunction &MF = *B.getParent();767MachineFunction::const_iterator BI = B.getIterator();768MachineFunction::const_iterator Next = std::next(BI);769if (Next != MF.end())770Targets.insert(&*Next);771}772} else {773// If the evaluation of the branches failed, make "Targets" to be the774// set of all successors of the block from the CFG.775// If the evaluation succeeded for all visited branches, then if the776// last one set "FallsThru", then add an edge to the layout successor777// to the targets.778Targets.clear();779LLVM_DEBUG(dbgs() << " failed to evaluate a branch...adding all CFG "780"successors\n");781for (const MachineBasicBlock *SB : B.successors())782Targets.insert(SB);783}784785for (const MachineBasicBlock *TB : Targets) {786unsigned TBN = TB->getNumber();787LLVM_DEBUG(dbgs() << " pushing edge " << printMBBReference(B) << " -> "788<< printMBBReference(*TB) << "\n");789FlowQ.push(CFGEdge(MBN, TBN));790}791}792793void MachineConstPropagator::visitUsesOf(unsigned Reg) {794LLVM_DEBUG(dbgs() << "Visiting uses of " << printReg(Reg, &MCE.TRI)795<< Cells.get(Reg) << '\n');796for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {797// Do not process non-executable instructions. They can become exceutable798// later (via a flow-edge in the work queue). In such case, the instruc-799// tion will be visited at that time.800if (!InstrExec.count(&MI))801continue;802if (MI.isPHI())803visitPHI(MI);804else if (!MI.isBranch())805visitNonBranch(MI);806else807visitBranchesFrom(MI);808}809}810811bool MachineConstPropagator::computeBlockSuccessors(const MachineBasicBlock *MB,812SetVector<const MachineBasicBlock*> &Targets) {813Targets.clear();814815MachineBasicBlock::const_iterator FirstBr = MB->end();816for (const MachineInstr &MI : *MB) {817if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)818return false;819if (MI.isDebugInstr())820continue;821if (MI.isBranch()) {822FirstBr = MI.getIterator();823break;824}825}826827MachineBasicBlock::const_iterator End = MB->end();828829bool DoNext = true;830for (MachineBasicBlock::const_iterator I = FirstBr; I != End; ++I) {831const MachineInstr &MI = *I;832// Can there be debug instructions between branches?833if (MI.isDebugInstr())834continue;835if (!InstrExec.count(&MI))836continue;837bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);838if (!Eval)839return false;840if (!DoNext)841break;842}843// If the last branch could fall-through, add block's layout successor.844if (DoNext) {845MachineFunction::const_iterator BI = MB->getIterator();846MachineFunction::const_iterator NextI = std::next(BI);847if (NextI != MB->getParent()->end())848Targets.insert(&*NextI);849}850851// Add all the EH landing pads.852for (const MachineBasicBlock *SB : MB->successors())853if (SB->isEHPad())854Targets.insert(SB);855856return true;857}858859void MachineConstPropagator::removeCFGEdge(MachineBasicBlock *From,860MachineBasicBlock *To) {861// First, remove the CFG successor/predecessor information.862From->removeSuccessor(To);863// Remove all corresponding PHI operands in the To block.864for (MachineInstr &PN : To->phis()) {865// reg0 = PHI reg1, bb2, reg3, bb4, ...866int N = PN.getNumOperands() - 2;867while (N > 0) {868if (PN.getOperand(N + 1).getMBB() == From) {869PN.removeOperand(N + 1);870PN.removeOperand(N);871}872N -= 2;873}874}875}876877void MachineConstPropagator::propagate(MachineFunction &MF) {878MachineBasicBlock *Entry = GraphTraits<MachineFunction*>::getEntryNode(&MF);879unsigned EntryNum = Entry->getNumber();880881// Start with a fake edge, just to process the entry node.882FlowQ.push(CFGEdge(EntryNum, EntryNum));883884while (!FlowQ.empty()) {885CFGEdge Edge = FlowQ.front();886FlowQ.pop();887888LLVM_DEBUG(889dbgs() << "Picked edge "890<< printMBBReference(*MF.getBlockNumbered(Edge.first)) << "->"891<< printMBBReference(*MF.getBlockNumbered(Edge.second)) << '\n');892if (Edge.first != EntryNum)893if (EdgeExec.count(Edge))894continue;895EdgeExec.insert(Edge);896MachineBasicBlock *SB = MF.getBlockNumbered(Edge.second);897898// Process the block in three stages:899// - visit all PHI nodes,900// - visit all non-branch instructions,901// - visit block branches.902MachineBasicBlock::const_iterator It = SB->begin(), End = SB->end();903904// Visit PHI nodes in the successor block.905while (It != End && It->isPHI()) {906InstrExec.insert(&*It);907visitPHI(*It);908++It;909}910911// If the successor block just became executable, visit all instructions.912// To see if this is the first time we're visiting it, check the first913// non-debug instruction to see if it is executable.914while (It != End && It->isDebugInstr())915++It;916assert(It == End || !It->isPHI());917// If this block has been visited, go on to the next one.918if (It != End && InstrExec.count(&*It))919continue;920// For now, scan all non-branch instructions. Branches require different921// processing.922while (It != End && !It->isBranch()) {923if (!It->isDebugInstr()) {924InstrExec.insert(&*It);925visitNonBranch(*It);926}927++It;928}929930// Time to process the end of the block. This is different from931// processing regular (non-branch) instructions, because there can932// be multiple branches in a block, and they can cause the block to933// terminate early.934if (It != End) {935visitBranchesFrom(*It);936} else {937// If the block didn't have a branch, add all successor edges to the938// work queue. (There should really be only one successor in such case.)939unsigned SBN = SB->getNumber();940for (const MachineBasicBlock *SSB : SB->successors())941FlowQ.push(CFGEdge(SBN, SSB->getNumber()));942}943} // while (FlowQ)944945LLVM_DEBUG({946dbgs() << "Cells after propagation:\n";947Cells.print(dbgs(), MCE.TRI);948dbgs() << "Dead CFG edges:\n";949for (const MachineBasicBlock &B : MF) {950unsigned BN = B.getNumber();951for (const MachineBasicBlock *SB : B.successors()) {952unsigned SN = SB->getNumber();953if (!EdgeExec.count(CFGEdge(BN, SN)))954dbgs() << " " << printMBBReference(B) << " -> "955<< printMBBReference(*SB) << '\n';956}957}958});959}960961bool MachineConstPropagator::rewrite(MachineFunction &MF) {962bool Changed = false;963// Rewrite all instructions based on the collected cell information.964//965// Traverse the instructions in a post-order, so that rewriting an966// instruction can make changes "downstream" in terms of control-flow967// without affecting the rewriting process. (We should not change968// instructions that have not yet been visited by the rewriter.)969// The reason for this is that the rewriter can introduce new vregs,970// and replace uses of old vregs (which had corresponding cells971// computed during propagation) with these new vregs (which at this972// point would not have any cells, and would appear to be "top").973// If an attempt was made to evaluate an instruction with a fresh974// "top" vreg, it would cause an error (abend) in the evaluator.975976// Collect the post-order-traversal block ordering. The subsequent977// traversal/rewrite will update block successors, so it's safer978// if the visiting order it computed ahead of time.979std::vector<MachineBasicBlock*> POT;980for (MachineBasicBlock *B : post_order(&MF))981if (!B->empty())982POT.push_back(B);983984for (MachineBasicBlock *B : POT) {985// Walk the block backwards (which usually begin with the branches).986// If any branch is rewritten, we may need to update the successor987// information for this block. Unless the block's successors can be988// precisely determined (which may not be the case for indirect989// branches), we cannot modify any branch.990991// Compute the successor information.992SetVector<const MachineBasicBlock*> Targets;993bool HaveTargets = computeBlockSuccessors(B, Targets);994// Rewrite the executable instructions. Skip branches if we don't995// have block successor information.996for (MachineInstr &MI : llvm::reverse(*B)) {997if (InstrExec.count(&MI)) {998if (MI.isBranch() && !HaveTargets)999continue;1000Changed |= MCE.rewrite(MI, Cells);1001}1002}1003// The rewriting could rewrite PHI nodes to non-PHI nodes, causing1004// regular instructions to appear in between PHI nodes. Bring all1005// the PHI nodes to the beginning of the block.1006for (auto I = B->begin(), E = B->end(); I != E; ++I) {1007if (I->isPHI())1008continue;1009// I is not PHI. Find the next PHI node P.1010auto P = I;1011while (++P != E)1012if (P->isPHI())1013break;1014// Not found.1015if (P == E)1016break;1017// Splice P right before I.1018B->splice(I, B, P);1019// Reset I to point at the just spliced PHI node.1020--I;1021}1022// Update the block successor information: remove unnecessary successors.1023if (HaveTargets) {1024SmallVector<MachineBasicBlock*,2> ToRemove;1025for (MachineBasicBlock *SB : B->successors()) {1026if (!Targets.count(SB))1027ToRemove.push_back(const_cast<MachineBasicBlock*>(SB));1028Targets.remove(SB);1029}1030for (MachineBasicBlock *MBB : ToRemove)1031removeCFGEdge(B, MBB);1032// If there are any blocks left in the computed targets, it means that1033// we think that the block could go somewhere, but the CFG does not.1034// This could legitimately happen in blocks that have non-returning1035// calls---we would think that the execution can continue, but the1036// CFG will not have a successor edge.1037}1038}1039// Need to do some final post-processing.1040// If a branch was not executable, it will not get rewritten, but should1041// be removed (or replaced with something equivalent to a A2_nop). We can't1042// erase instructions during rewriting, so this needs to be delayed until1043// now.1044for (MachineBasicBlock &B : MF) {1045for (MachineInstr &MI : llvm::make_early_inc_range(B))1046if (MI.isBranch() && !InstrExec.count(&MI))1047B.erase(&MI);1048}1049return Changed;1050}10511052// This is the constant propagation algorithm as described by Wegman-Zadeck.1053// Most of the terminology comes from there.1054bool MachineConstPropagator::run(MachineFunction &MF) {1055LLVM_DEBUG(MF.print(dbgs() << "Starting MachineConstPropagator\n", nullptr));10561057MRI = &MF.getRegInfo();10581059Cells.clear();1060EdgeExec.clear();1061InstrExec.clear();1062assert(FlowQ.empty());10631064propagate(MF);1065bool Changed = rewrite(MF);10661067LLVM_DEBUG({1068dbgs() << "End of MachineConstPropagator (Changed=" << Changed << ")\n";1069if (Changed)1070MF.print(dbgs(), nullptr);1071});1072return Changed;1073}10741075// --------------------------------------------------------------------1076// Machine const evaluator.10771078bool MachineConstEvaluator::getCell(const RegisterSubReg &R, const CellMap &Inputs,1079LatticeCell &RC) {1080if (!R.Reg.isVirtual())1081return false;1082const LatticeCell &L = Inputs.get(R.Reg);1083if (!R.SubReg) {1084RC = L;1085return !RC.isBottom();1086}1087bool Eval = evaluate(R, L, RC);1088return Eval && !RC.isBottom();1089}10901091bool MachineConstEvaluator::constToInt(const Constant *C,1092APInt &Val) const {1093const ConstantInt *CI = dyn_cast<ConstantInt>(C);1094if (!CI)1095return false;1096Val = CI->getValue();1097return true;1098}10991100const ConstantInt *MachineConstEvaluator::intToConst(const APInt &Val) const {1101return ConstantInt::get(CX, Val);1102}11031104bool MachineConstEvaluator::evaluateCMPrr(uint32_t Cmp, const RegisterSubReg &R1,1105const RegisterSubReg &R2, const CellMap &Inputs, bool &Result) {1106assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));1107LatticeCell LS1, LS2;1108if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))1109return false;11101111bool IsProp1 = LS1.isProperty();1112bool IsProp2 = LS2.isProperty();1113if (IsProp1) {1114uint32_t Prop1 = LS1.properties();1115if (IsProp2)1116return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);1117uint32_t NegCmp = Comparison::negate(Cmp);1118return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);1119}1120if (IsProp2) {1121uint32_t Prop2 = LS2.properties();1122return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);1123}11241125APInt A;1126bool IsTrue = true, IsFalse = true;1127for (unsigned i = 0; i < LS2.size(); ++i) {1128bool Res;1129bool Computed = constToInt(LS2.Values[i], A) &&1130evaluateCMPri(Cmp, R1, A, Inputs, Res);1131if (!Computed)1132return false;1133IsTrue &= Res;1134IsFalse &= !Res;1135}1136assert(!IsTrue || !IsFalse);1137// The actual logical value of the comparison is same as IsTrue.1138Result = IsTrue;1139// Return true if the result was proven to be true or proven to be false.1140return IsTrue || IsFalse;1141}11421143bool MachineConstEvaluator::evaluateCMPri(uint32_t Cmp, const RegisterSubReg &R1,1144const APInt &A2, const CellMap &Inputs, bool &Result) {1145assert(Inputs.has(R1.Reg));1146LatticeCell LS;1147if (!getCell(R1, Inputs, LS))1148return false;1149if (LS.isProperty())1150return evaluateCMPpi(Cmp, LS.properties(), A2, Result);11511152APInt A;1153bool IsTrue = true, IsFalse = true;1154for (unsigned i = 0; i < LS.size(); ++i) {1155bool Res;1156bool Computed = constToInt(LS.Values[i], A) &&1157evaluateCMPii(Cmp, A, A2, Res);1158if (!Computed)1159return false;1160IsTrue &= Res;1161IsFalse &= !Res;1162}1163assert(!IsTrue || !IsFalse);1164// The actual logical value of the comparison is same as IsTrue.1165Result = IsTrue;1166// Return true if the result was proven to be true or proven to be false.1167return IsTrue || IsFalse;1168}11691170bool MachineConstEvaluator::evaluateCMPrp(uint32_t Cmp, const RegisterSubReg &R1,1171uint64_t Props2, const CellMap &Inputs, bool &Result) {1172assert(Inputs.has(R1.Reg));1173LatticeCell LS;1174if (!getCell(R1, Inputs, LS))1175return false;1176if (LS.isProperty())1177return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);11781179APInt A;1180uint32_t NegCmp = Comparison::negate(Cmp);1181bool IsTrue = true, IsFalse = true;1182for (unsigned i = 0; i < LS.size(); ++i) {1183bool Res;1184bool Computed = constToInt(LS.Values[i], A) &&1185evaluateCMPpi(NegCmp, Props2, A, Res);1186if (!Computed)1187return false;1188IsTrue &= Res;1189IsFalse &= !Res;1190}1191assert(!IsTrue || !IsFalse);1192Result = IsTrue;1193return IsTrue || IsFalse;1194}11951196bool MachineConstEvaluator::evaluateCMPii(uint32_t Cmp, const APInt &A1,1197const APInt &A2, bool &Result) {1198// NE is a special kind of comparison (not composed of smaller properties).1199if (Cmp == Comparison::NE) {1200Result = !APInt::isSameValue(A1, A2);1201return true;1202}1203if (Cmp == Comparison::EQ) {1204Result = APInt::isSameValue(A1, A2);1205return true;1206}1207if (Cmp & Comparison::EQ) {1208if (APInt::isSameValue(A1, A2))1209return (Result = true);1210}1211assert((Cmp & (Comparison::L | Comparison::G)) && "Malformed comparison");1212Result = false;12131214unsigned W1 = A1.getBitWidth();1215unsigned W2 = A2.getBitWidth();1216unsigned MaxW = (W1 >= W2) ? W1 : W2;1217if (Cmp & Comparison::U) {1218APInt Zx1 = A1.zext(MaxW);1219APInt Zx2 = A2.zext(MaxW);1220if (Cmp & Comparison::L)1221Result = Zx1.ult(Zx2);1222else if (Cmp & Comparison::G)1223Result = Zx2.ult(Zx1);1224return true;1225}12261227// Signed comparison.1228APInt Sx1 = A1.sext(MaxW);1229APInt Sx2 = A2.sext(MaxW);1230if (Cmp & Comparison::L)1231Result = Sx1.slt(Sx2);1232else if (Cmp & Comparison::G)1233Result = Sx2.slt(Sx1);1234return true;1235}12361237bool MachineConstEvaluator::evaluateCMPpi(uint32_t Cmp, uint32_t Props,1238const APInt &A2, bool &Result) {1239if (Props == ConstantProperties::Unknown)1240return false;12411242// Should never see NaN here, but check for it for completeness.1243if (Props & ConstantProperties::NaN)1244return false;1245// Infinity could theoretically be compared to a number, but the1246// presence of infinity here would be very suspicious. If we don't1247// know for sure that the number is finite, bail out.1248if (!(Props & ConstantProperties::Finite))1249return false;12501251// Let X be a number that has properties Props.12521253if (Cmp & Comparison::U) {1254// In case of unsigned comparisons, we can only compare against 0.1255if (A2 == 0) {1256// Any x!=0 will be considered >0 in an unsigned comparison.1257if (Props & ConstantProperties::Zero)1258Result = (Cmp & Comparison::EQ);1259else if (Props & ConstantProperties::NonZero)1260Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);1261else1262return false;1263return true;1264}1265// A2 is not zero. The only handled case is if X = 0.1266if (Props & ConstantProperties::Zero) {1267Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);1268return true;1269}1270return false;1271}12721273// Signed comparisons are different.1274if (Props & ConstantProperties::Zero) {1275if (A2 == 0)1276Result = (Cmp & Comparison::EQ);1277else1278Result = (Cmp == Comparison::NE) ||1279((Cmp & Comparison::L) && !A2.isNegative()) ||1280((Cmp & Comparison::G) && A2.isNegative());1281return true;1282}1283if (Props & ConstantProperties::PosOrZero) {1284// X >= 0 and !(A2 < 0) => cannot compare1285if (!A2.isNegative())1286return false;1287// X >= 0 and A2 < 01288Result = (Cmp & Comparison::G) || (Cmp == Comparison::NE);1289return true;1290}1291if (Props & ConstantProperties::NegOrZero) {1292// X <= 0 and Src1 < 0 => cannot compare1293if (A2 == 0 || A2.isNegative())1294return false;1295// X <= 0 and A2 > 01296Result = (Cmp & Comparison::L) || (Cmp == Comparison::NE);1297return true;1298}12991300return false;1301}13021303bool MachineConstEvaluator::evaluateCMPpp(uint32_t Cmp, uint32_t Props1,1304uint32_t Props2, bool &Result) {1305using P = ConstantProperties;13061307if ((Props1 & P::NaN) && (Props2 & P::NaN))1308return false;1309if (!(Props1 & P::Finite) || !(Props2 & P::Finite))1310return false;13111312bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);1313bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);1314if (Zero1 && Zero2) {1315Result = (Cmp & Comparison::EQ);1316return true;1317}1318if (Cmp == Comparison::NE) {1319if ((Zero1 && NonZero2) || (NonZero1 && Zero2))1320return (Result = true);1321return false;1322}13231324if (Cmp & Comparison::U) {1325// In unsigned comparisons, we can only compare against a known zero,1326// or a known non-zero.1327if (Zero1 && NonZero2) {1328Result = (Cmp & Comparison::L);1329return true;1330}1331if (NonZero1 && Zero2) {1332Result = (Cmp & Comparison::G);1333return true;1334}1335return false;1336}13371338// Signed comparison. The comparison is not NE.1339bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);1340bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);1341if (Nez1 && Poz2) {1342if (NonZero1 || NonZero2) {1343Result = (Cmp & Comparison::L);1344return true;1345}1346// Either (or both) could be zero. Can only say that X <= Y.1347if ((Cmp & Comparison::EQ) && (Cmp & Comparison::L))1348return (Result = true);1349}1350if (Poz1 && Nez2) {1351if (NonZero1 || NonZero2) {1352Result = (Cmp & Comparison::G);1353return true;1354}1355// Either (or both) could be zero. Can only say that X >= Y.1356if ((Cmp & Comparison::EQ) && (Cmp & Comparison::G))1357return (Result = true);1358}13591360return false;1361}13621363bool MachineConstEvaluator::evaluateCOPY(const RegisterSubReg &R1,1364const CellMap &Inputs, LatticeCell &Result) {1365return getCell(R1, Inputs, Result);1366}13671368bool MachineConstEvaluator::evaluateANDrr(const RegisterSubReg &R1,1369const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {1370assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));1371const LatticeCell &L1 = Inputs.get(R2.Reg);1372const LatticeCell &L2 = Inputs.get(R2.Reg);1373// If both sources are bottom, exit. Otherwise try to evaluate ANDri1374// with the non-bottom argument passed as the immediate. This is to1375// catch cases of ANDing with 0.1376if (L2.isBottom()) {1377if (L1.isBottom())1378return false;1379return evaluateANDrr(R2, R1, Inputs, Result);1380}1381LatticeCell LS2;1382if (!evaluate(R2, L2, LS2))1383return false;1384if (LS2.isBottom() || LS2.isProperty())1385return false;13861387APInt A;1388for (unsigned i = 0; i < LS2.size(); ++i) {1389LatticeCell RC;1390bool Eval = constToInt(LS2.Values[i], A) &&1391evaluateANDri(R1, A, Inputs, RC);1392if (!Eval)1393return false;1394Result.meet(RC);1395}1396return !Result.isBottom();1397}13981399bool MachineConstEvaluator::evaluateANDri(const RegisterSubReg &R1,1400const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {1401assert(Inputs.has(R1.Reg));1402if (A2 == -1)1403return getCell(R1, Inputs, Result);1404if (A2 == 0) {1405LatticeCell RC;1406RC.add(intToConst(A2));1407// Overwrite Result.1408Result = RC;1409return true;1410}1411LatticeCell LS1;1412if (!getCell(R1, Inputs, LS1))1413return false;1414if (LS1.isBottom() || LS1.isProperty())1415return false;14161417APInt A, ResA;1418for (unsigned i = 0; i < LS1.size(); ++i) {1419bool Eval = constToInt(LS1.Values[i], A) &&1420evaluateANDii(A, A2, ResA);1421if (!Eval)1422return false;1423const Constant *C = intToConst(ResA);1424Result.add(C);1425}1426return !Result.isBottom();1427}14281429bool MachineConstEvaluator::evaluateANDii(const APInt &A1,1430const APInt &A2, APInt &Result) {1431Result = A1 & A2;1432return true;1433}14341435bool MachineConstEvaluator::evaluateORrr(const RegisterSubReg &R1,1436const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {1437assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));1438const LatticeCell &L1 = Inputs.get(R2.Reg);1439const LatticeCell &L2 = Inputs.get(R2.Reg);1440// If both sources are bottom, exit. Otherwise try to evaluate ORri1441// with the non-bottom argument passed as the immediate. This is to1442// catch cases of ORing with -1.1443if (L2.isBottom()) {1444if (L1.isBottom())1445return false;1446return evaluateORrr(R2, R1, Inputs, Result);1447}1448LatticeCell LS2;1449if (!evaluate(R2, L2, LS2))1450return false;1451if (LS2.isBottom() || LS2.isProperty())1452return false;14531454APInt A;1455for (unsigned i = 0; i < LS2.size(); ++i) {1456LatticeCell RC;1457bool Eval = constToInt(LS2.Values[i], A) &&1458evaluateORri(R1, A, Inputs, RC);1459if (!Eval)1460return false;1461Result.meet(RC);1462}1463return !Result.isBottom();1464}14651466bool MachineConstEvaluator::evaluateORri(const RegisterSubReg &R1,1467const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {1468assert(Inputs.has(R1.Reg));1469if (A2 == 0)1470return getCell(R1, Inputs, Result);1471if (A2 == -1) {1472LatticeCell RC;1473RC.add(intToConst(A2));1474// Overwrite Result.1475Result = RC;1476return true;1477}1478LatticeCell LS1;1479if (!getCell(R1, Inputs, LS1))1480return false;1481if (LS1.isBottom() || LS1.isProperty())1482return false;14831484APInt A, ResA;1485for (unsigned i = 0; i < LS1.size(); ++i) {1486bool Eval = constToInt(LS1.Values[i], A) &&1487evaluateORii(A, A2, ResA);1488if (!Eval)1489return false;1490const Constant *C = intToConst(ResA);1491Result.add(C);1492}1493return !Result.isBottom();1494}14951496bool MachineConstEvaluator::evaluateORii(const APInt &A1,1497const APInt &A2, APInt &Result) {1498Result = A1 | A2;1499return true;1500}15011502bool MachineConstEvaluator::evaluateXORrr(const RegisterSubReg &R1,1503const RegisterSubReg &R2, const CellMap &Inputs, LatticeCell &Result) {1504assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));1505LatticeCell LS1, LS2;1506if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))1507return false;1508if (LS1.isProperty()) {1509if (LS1.properties() & ConstantProperties::Zero)1510return !(Result = LS2).isBottom();1511return false;1512}1513if (LS2.isProperty()) {1514if (LS2.properties() & ConstantProperties::Zero)1515return !(Result = LS1).isBottom();1516return false;1517}15181519APInt A;1520for (unsigned i = 0; i < LS2.size(); ++i) {1521LatticeCell RC;1522bool Eval = constToInt(LS2.Values[i], A) &&1523evaluateXORri(R1, A, Inputs, RC);1524if (!Eval)1525return false;1526Result.meet(RC);1527}1528return !Result.isBottom();1529}15301531bool MachineConstEvaluator::evaluateXORri(const RegisterSubReg &R1,1532const APInt &A2, const CellMap &Inputs, LatticeCell &Result) {1533assert(Inputs.has(R1.Reg));1534LatticeCell LS1;1535if (!getCell(R1, Inputs, LS1))1536return false;1537if (LS1.isProperty()) {1538if (LS1.properties() & ConstantProperties::Zero) {1539const Constant *C = intToConst(A2);1540Result.add(C);1541return !Result.isBottom();1542}1543return false;1544}15451546APInt A, XA;1547for (unsigned i = 0; i < LS1.size(); ++i) {1548bool Eval = constToInt(LS1.Values[i], A) &&1549evaluateXORii(A, A2, XA);1550if (!Eval)1551return false;1552const Constant *C = intToConst(XA);1553Result.add(C);1554}1555return !Result.isBottom();1556}15571558bool MachineConstEvaluator::evaluateXORii(const APInt &A1,1559const APInt &A2, APInt &Result) {1560Result = A1 ^ A2;1561return true;1562}15631564bool MachineConstEvaluator::evaluateZEXTr(const RegisterSubReg &R1, unsigned Width,1565unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {1566assert(Inputs.has(R1.Reg));1567LatticeCell LS1;1568if (!getCell(R1, Inputs, LS1))1569return false;1570if (LS1.isProperty())1571return false;15721573APInt A, XA;1574for (unsigned i = 0; i < LS1.size(); ++i) {1575bool Eval = constToInt(LS1.Values[i], A) &&1576evaluateZEXTi(A, Width, Bits, XA);1577if (!Eval)1578return false;1579const Constant *C = intToConst(XA);1580Result.add(C);1581}1582return true;1583}15841585bool MachineConstEvaluator::evaluateZEXTi(const APInt &A1, unsigned Width,1586unsigned Bits, APInt &Result) {1587unsigned BW = A1.getBitWidth();1588(void)BW;1589assert(Width >= Bits && BW >= Bits);1590APInt Mask = APInt::getLowBitsSet(Width, Bits);1591Result = A1.zextOrTrunc(Width) & Mask;1592return true;1593}15941595bool MachineConstEvaluator::evaluateSEXTr(const RegisterSubReg &R1, unsigned Width,1596unsigned Bits, const CellMap &Inputs, LatticeCell &Result) {1597assert(Inputs.has(R1.Reg));1598LatticeCell LS1;1599if (!getCell(R1, Inputs, LS1))1600return false;1601if (LS1.isBottom() || LS1.isProperty())1602return false;16031604APInt A, XA;1605for (unsigned i = 0; i < LS1.size(); ++i) {1606bool Eval = constToInt(LS1.Values[i], A) &&1607evaluateSEXTi(A, Width, Bits, XA);1608if (!Eval)1609return false;1610const Constant *C = intToConst(XA);1611Result.add(C);1612}1613return true;1614}16151616bool MachineConstEvaluator::evaluateSEXTi(const APInt &A1, unsigned Width,1617unsigned Bits, APInt &Result) {1618unsigned BW = A1.getBitWidth();1619assert(Width >= Bits && BW >= Bits);1620// Special case to make things faster for smaller source widths.1621// Sign extension of 0 bits generates 0 as a result. This is consistent1622// with what the HW does.1623if (Bits == 0) {1624Result = APInt(Width, 0);1625return true;1626}1627// In C, shifts by 64 invoke undefined behavior: handle that case in APInt.1628if (BW <= 64 && Bits != 0) {1629int64_t V = A1.getSExtValue();1630switch (Bits) {1631case 8:1632V = static_cast<int8_t>(V);1633break;1634case 16:1635V = static_cast<int16_t>(V);1636break;1637case 32:1638V = static_cast<int32_t>(V);1639break;1640default:1641// Shift left to lose all bits except lower "Bits" bits, then shift1642// the value back, replicating what was a sign bit after the first1643// shift.1644V = (V << (64-Bits)) >> (64-Bits);1645break;1646}1647// V is a 64-bit sign-extended value. Convert it to APInt of desired1648// width.1649Result = APInt(Width, V, true);1650return true;1651}1652// Slow case: the value doesn't fit in int64_t.1653if (Bits < BW)1654Result = A1.trunc(Bits).sext(Width);1655else // Bits == BW1656Result = A1.sext(Width);1657return true;1658}16591660bool MachineConstEvaluator::evaluateCLBr(const RegisterSubReg &R1, bool Zeros,1661bool Ones, const CellMap &Inputs, LatticeCell &Result) {1662assert(Inputs.has(R1.Reg));1663LatticeCell LS1;1664if (!getCell(R1, Inputs, LS1))1665return false;1666if (LS1.isBottom() || LS1.isProperty())1667return false;16681669APInt A, CA;1670for (unsigned i = 0; i < LS1.size(); ++i) {1671bool Eval = constToInt(LS1.Values[i], A) &&1672evaluateCLBi(A, Zeros, Ones, CA);1673if (!Eval)1674return false;1675const Constant *C = intToConst(CA);1676Result.add(C);1677}1678return true;1679}16801681bool MachineConstEvaluator::evaluateCLBi(const APInt &A1, bool Zeros,1682bool Ones, APInt &Result) {1683unsigned BW = A1.getBitWidth();1684if (!Zeros && !Ones)1685return false;1686unsigned Count = 0;1687if (Zeros && (Count == 0))1688Count = A1.countl_zero();1689if (Ones && (Count == 0))1690Count = A1.countl_one();1691Result = APInt(BW, static_cast<uint64_t>(Count), false);1692return true;1693}16941695bool MachineConstEvaluator::evaluateCTBr(const RegisterSubReg &R1, bool Zeros,1696bool Ones, const CellMap &Inputs, LatticeCell &Result) {1697assert(Inputs.has(R1.Reg));1698LatticeCell LS1;1699if (!getCell(R1, Inputs, LS1))1700return false;1701if (LS1.isBottom() || LS1.isProperty())1702return false;17031704APInt A, CA;1705for (unsigned i = 0; i < LS1.size(); ++i) {1706bool Eval = constToInt(LS1.Values[i], A) &&1707evaluateCTBi(A, Zeros, Ones, CA);1708if (!Eval)1709return false;1710const Constant *C = intToConst(CA);1711Result.add(C);1712}1713return true;1714}17151716bool MachineConstEvaluator::evaluateCTBi(const APInt &A1, bool Zeros,1717bool Ones, APInt &Result) {1718unsigned BW = A1.getBitWidth();1719if (!Zeros && !Ones)1720return false;1721unsigned Count = 0;1722if (Zeros && (Count == 0))1723Count = A1.countr_zero();1724if (Ones && (Count == 0))1725Count = A1.countr_one();1726Result = APInt(BW, static_cast<uint64_t>(Count), false);1727return true;1728}17291730bool MachineConstEvaluator::evaluateEXTRACTr(const RegisterSubReg &R1,1731unsigned Width, unsigned Bits, unsigned Offset, bool Signed,1732const CellMap &Inputs, LatticeCell &Result) {1733assert(Inputs.has(R1.Reg));1734assert(Bits+Offset <= Width);1735LatticeCell LS1;1736if (!getCell(R1, Inputs, LS1))1737return false;1738if (LS1.isBottom())1739return false;1740if (LS1.isProperty()) {1741uint32_t Ps = LS1.properties();1742if (Ps & ConstantProperties::Zero) {1743const Constant *C = intToConst(APInt(Width, 0, false));1744Result.add(C);1745return true;1746}1747return false;1748}17491750APInt A, CA;1751for (unsigned i = 0; i < LS1.size(); ++i) {1752bool Eval = constToInt(LS1.Values[i], A) &&1753evaluateEXTRACTi(A, Bits, Offset, Signed, CA);1754if (!Eval)1755return false;1756const Constant *C = intToConst(CA);1757Result.add(C);1758}1759return true;1760}17611762bool MachineConstEvaluator::evaluateEXTRACTi(const APInt &A1, unsigned Bits,1763unsigned Offset, bool Signed, APInt &Result) {1764unsigned BW = A1.getBitWidth();1765assert(Bits+Offset <= BW);1766// Extracting 0 bits generates 0 as a result (as indicated by the HW people).1767if (Bits == 0) {1768Result = APInt(BW, 0);1769return true;1770}1771if (BW <= 64) {1772int64_t V = A1.getZExtValue();1773V <<= (64-Bits-Offset);1774if (Signed)1775V >>= (64-Bits);1776else1777V = static_cast<uint64_t>(V) >> (64-Bits);1778Result = APInt(BW, V, Signed);1779return true;1780}1781if (Signed)1782Result = A1.shl(BW-Bits-Offset).ashr(BW-Bits);1783else1784Result = A1.shl(BW-Bits-Offset).lshr(BW-Bits);1785return true;1786}17871788bool MachineConstEvaluator::evaluateSplatr(const RegisterSubReg &R1,1789unsigned Bits, unsigned Count, const CellMap &Inputs,1790LatticeCell &Result) {1791assert(Inputs.has(R1.Reg));1792LatticeCell LS1;1793if (!getCell(R1, Inputs, LS1))1794return false;1795if (LS1.isBottom() || LS1.isProperty())1796return false;17971798APInt A, SA;1799for (unsigned i = 0; i < LS1.size(); ++i) {1800bool Eval = constToInt(LS1.Values[i], A) &&1801evaluateSplati(A, Bits, Count, SA);1802if (!Eval)1803return false;1804const Constant *C = intToConst(SA);1805Result.add(C);1806}1807return true;1808}18091810bool MachineConstEvaluator::evaluateSplati(const APInt &A1, unsigned Bits,1811unsigned Count, APInt &Result) {1812assert(Count > 0);1813unsigned BW = A1.getBitWidth(), SW = Count*Bits;1814APInt LoBits = (Bits < BW) ? A1.trunc(Bits) : A1.zext(Bits);1815if (Count > 1)1816LoBits = LoBits.zext(SW);18171818APInt Res(SW, 0, false);1819for (unsigned i = 0; i < Count; ++i) {1820Res <<= Bits;1821Res |= LoBits;1822}1823Result = Res;1824return true;1825}18261827// ----------------------------------------------------------------------1828// Hexagon-specific code.18291830namespace llvm {18311832FunctionPass *createHexagonConstPropagationPass();1833void initializeHexagonConstPropagationPass(PassRegistry &Registry);18341835} // end namespace llvm18361837namespace {18381839class HexagonConstEvaluator : public MachineConstEvaluator {1840public:1841HexagonConstEvaluator(MachineFunction &Fn);18421843bool evaluate(const MachineInstr &MI, const CellMap &Inputs,1844CellMap &Outputs) override;1845bool evaluate(const RegisterSubReg &R, const LatticeCell &SrcC,1846LatticeCell &Result) override;1847bool evaluate(const MachineInstr &BrI, const CellMap &Inputs,1848SetVector<const MachineBasicBlock*> &Targets, bool &FallsThru)1849override;1850bool rewrite(MachineInstr &MI, const CellMap &Inputs) override;18511852private:1853unsigned getRegBitWidth(unsigned Reg) const;18541855static uint32_t getCmp(unsigned Opc);1856static APInt getCmpImm(unsigned Opc, unsigned OpX,1857const MachineOperand &MO);1858void replaceWithNop(MachineInstr &MI);18591860bool evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH, const CellMap &Inputs,1861LatticeCell &Result);1862bool evaluateHexCompare(const MachineInstr &MI, const CellMap &Inputs,1863CellMap &Outputs);1864// This is suitable to be called for compare-and-jump instructions.1865bool evaluateHexCompare2(uint32_t Cmp, const MachineOperand &Src1,1866const MachineOperand &Src2, const CellMap &Inputs, bool &Result);1867bool evaluateHexLogical(const MachineInstr &MI, const CellMap &Inputs,1868CellMap &Outputs);1869bool evaluateHexCondMove(const MachineInstr &MI, const CellMap &Inputs,1870CellMap &Outputs);1871bool evaluateHexExt(const MachineInstr &MI, const CellMap &Inputs,1872CellMap &Outputs);1873bool evaluateHexVector1(const MachineInstr &MI, const CellMap &Inputs,1874CellMap &Outputs);1875bool evaluateHexVector2(const MachineInstr &MI, const CellMap &Inputs,1876CellMap &Outputs);18771878void replaceAllRegUsesWith(Register FromReg, Register ToReg);1879bool rewriteHexBranch(MachineInstr &BrI, const CellMap &Inputs);1880bool rewriteHexConstDefs(MachineInstr &MI, const CellMap &Inputs,1881bool &AllDefs);1882bool rewriteHexConstUses(MachineInstr &MI, const CellMap &Inputs);18831884MachineRegisterInfo *MRI;1885const HexagonInstrInfo &HII;1886const HexagonRegisterInfo &HRI;1887};18881889class HexagonConstPropagation : public MachineFunctionPass {1890public:1891static char ID;18921893HexagonConstPropagation() : MachineFunctionPass(ID) {}18941895StringRef getPassName() const override {1896return "Hexagon Constant Propagation";1897}18981899bool runOnMachineFunction(MachineFunction &MF) override {1900const Function &F = MF.getFunction();1901if (skipFunction(F))1902return false;19031904HexagonConstEvaluator HCE(MF);1905return MachineConstPropagator(HCE).run(MF);1906}1907};19081909} // end anonymous namespace19101911char HexagonConstPropagation::ID = 0;19121913INITIALIZE_PASS(HexagonConstPropagation, "hexagon-constp",1914"Hexagon Constant Propagation", false, false)19151916HexagonConstEvaluator::HexagonConstEvaluator(MachineFunction &Fn)1917: MachineConstEvaluator(Fn),1918HII(*Fn.getSubtarget<HexagonSubtarget>().getInstrInfo()),1919HRI(*Fn.getSubtarget<HexagonSubtarget>().getRegisterInfo()) {1920MRI = &Fn.getRegInfo();1921}19221923bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,1924const CellMap &Inputs, CellMap &Outputs) {1925if (MI.isCall())1926return false;1927if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg())1928return false;1929const MachineOperand &MD = MI.getOperand(0);1930if (!MD.isDef())1931return false;19321933unsigned Opc = MI.getOpcode();1934RegisterSubReg DefR(MD);1935assert(!DefR.SubReg);1936if (!DefR.Reg.isVirtual())1937return false;19381939if (MI.isCopy()) {1940LatticeCell RC;1941RegisterSubReg SrcR(MI.getOperand(1));1942bool Eval = evaluateCOPY(SrcR, Inputs, RC);1943if (!Eval)1944return false;1945Outputs.update(DefR.Reg, RC);1946return true;1947}1948if (MI.isRegSequence()) {1949unsigned Sub1 = MI.getOperand(2).getImm();1950unsigned Sub2 = MI.getOperand(4).getImm();1951const TargetRegisterClass &DefRC = *MRI->getRegClass(DefR.Reg);1952unsigned SubLo = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_lo);1953unsigned SubHi = HRI.getHexagonSubRegIndex(DefRC, Hexagon::ps_sub_hi);1954if (Sub1 != SubLo && Sub1 != SubHi)1955return false;1956if (Sub2 != SubLo && Sub2 != SubHi)1957return false;1958assert(Sub1 != Sub2);1959bool LoIs1 = (Sub1 == SubLo);1960const MachineOperand &OpLo = LoIs1 ? MI.getOperand(1) : MI.getOperand(3);1961const MachineOperand &OpHi = LoIs1 ? MI.getOperand(3) : MI.getOperand(1);1962LatticeCell RC;1963RegisterSubReg SrcRL(OpLo), SrcRH(OpHi);1964bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);1965if (!Eval)1966return false;1967Outputs.update(DefR.Reg, RC);1968return true;1969}1970if (MI.isCompare()) {1971bool Eval = evaluateHexCompare(MI, Inputs, Outputs);1972return Eval;1973}19741975switch (Opc) {1976default:1977return false;1978case Hexagon::A2_tfrsi:1979case Hexagon::A2_tfrpi:1980case Hexagon::CONST32:1981case Hexagon::CONST64:1982{1983const MachineOperand &VO = MI.getOperand(1);1984// The operand of CONST32 can be a blockaddress, e.g.1985// %0 = CONST32 <blockaddress(@eat, %l)>1986// Do this check for all instructions for safety.1987if (!VO.isImm())1988return false;1989int64_t V = MI.getOperand(1).getImm();1990unsigned W = getRegBitWidth(DefR.Reg);1991if (W != 32 && W != 64)1992return false;1993IntegerType *Ty = (W == 32) ? Type::getInt32Ty(CX)1994: Type::getInt64Ty(CX);1995const ConstantInt *CI = ConstantInt::get(Ty, V, true);1996LatticeCell RC = Outputs.get(DefR.Reg);1997RC.add(CI);1998Outputs.update(DefR.Reg, RC);1999break;2000}20012002case Hexagon::PS_true:2003case Hexagon::PS_false:2004{2005LatticeCell RC = Outputs.get(DefR.Reg);2006bool NonZero = (Opc == Hexagon::PS_true);2007uint32_t P = NonZero ? ConstantProperties::NonZero2008: ConstantProperties::Zero;2009RC.add(P);2010Outputs.update(DefR.Reg, RC);2011break;2012}20132014case Hexagon::A2_and:2015case Hexagon::A2_andir:2016case Hexagon::A2_andp:2017case Hexagon::A2_or:2018case Hexagon::A2_orir:2019case Hexagon::A2_orp:2020case Hexagon::A2_xor:2021case Hexagon::A2_xorp:2022{2023bool Eval = evaluateHexLogical(MI, Inputs, Outputs);2024if (!Eval)2025return false;2026break;2027}20282029case Hexagon::A2_combineii: // combine(#s8Ext, #s8)2030case Hexagon::A4_combineii: // combine(#s8, #u6Ext)2031{2032if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isImm())2033return false;2034uint64_t Hi = MI.getOperand(1).getImm();2035uint64_t Lo = MI.getOperand(2).getImm();2036uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF);2037IntegerType *Ty = Type::getInt64Ty(CX);2038const ConstantInt *CI = ConstantInt::get(Ty, Res, false);2039LatticeCell RC = Outputs.get(DefR.Reg);2040RC.add(CI);2041Outputs.update(DefR.Reg, RC);2042break;2043}20442045case Hexagon::S2_setbit_i:2046{2047int64_t B = MI.getOperand(2).getImm();2048assert(B >=0 && B < 32);2049APInt A(32, (1ull << B), false);2050RegisterSubReg R(MI.getOperand(1));2051LatticeCell RC = Outputs.get(DefR.Reg);2052bool Eval = evaluateORri(R, A, Inputs, RC);2053if (!Eval)2054return false;2055Outputs.update(DefR.Reg, RC);2056break;2057}20582059case Hexagon::C2_mux:2060case Hexagon::C2_muxir:2061case Hexagon::C2_muxri:2062case Hexagon::C2_muxii:2063{2064bool Eval = evaluateHexCondMove(MI, Inputs, Outputs);2065if (!Eval)2066return false;2067break;2068}20692070case Hexagon::A2_sxtb:2071case Hexagon::A2_sxth:2072case Hexagon::A2_sxtw:2073case Hexagon::A2_zxtb:2074case Hexagon::A2_zxth:2075{2076bool Eval = evaluateHexExt(MI, Inputs, Outputs);2077if (!Eval)2078return false;2079break;2080}20812082case Hexagon::S2_ct0:2083case Hexagon::S2_ct0p:2084case Hexagon::S2_ct1:2085case Hexagon::S2_ct1p:2086{2087using namespace Hexagon;20882089bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);2090RegisterSubReg R1(MI.getOperand(1));2091assert(Inputs.has(R1.Reg));2092LatticeCell T;2093bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs, T);2094if (!Eval)2095return false;2096// All of these instructions return a 32-bit value. The evaluate2097// will generate the same type as the operand, so truncate the2098// result if necessary.2099APInt C;2100LatticeCell RC = Outputs.get(DefR.Reg);2101for (unsigned i = 0; i < T.size(); ++i) {2102const Constant *CI = T.Values[i];2103if (constToInt(CI, C) && C.getBitWidth() > 32)2104CI = intToConst(C.trunc(32));2105RC.add(CI);2106}2107Outputs.update(DefR.Reg, RC);2108break;2109}21102111case Hexagon::S2_cl0:2112case Hexagon::S2_cl0p:2113case Hexagon::S2_cl1:2114case Hexagon::S2_cl1p:2115case Hexagon::S2_clb:2116case Hexagon::S2_clbp:2117{2118using namespace Hexagon;21192120bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);2121bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p);2122RegisterSubReg R1(MI.getOperand(1));2123assert(Inputs.has(R1.Reg));2124LatticeCell T;2125bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs, T);2126if (!Eval)2127return false;2128// All of these instructions return a 32-bit value. The evaluate2129// will generate the same type as the operand, so truncate the2130// result if necessary.2131APInt C;2132LatticeCell RC = Outputs.get(DefR.Reg);2133for (unsigned i = 0; i < T.size(); ++i) {2134const Constant *CI = T.Values[i];2135if (constToInt(CI, C) && C.getBitWidth() > 32)2136CI = intToConst(C.trunc(32));2137RC.add(CI);2138}2139Outputs.update(DefR.Reg, RC);2140break;2141}21422143case Hexagon::S4_extract:2144case Hexagon::S4_extractp:2145case Hexagon::S2_extractu:2146case Hexagon::S2_extractup:2147{2148bool Signed = (Opc == Hexagon::S4_extract) ||2149(Opc == Hexagon::S4_extractp);2150RegisterSubReg R1(MI.getOperand(1));2151unsigned BW = getRegBitWidth(R1.Reg);2152unsigned Bits = MI.getOperand(2).getImm();2153unsigned Offset = MI.getOperand(3).getImm();2154LatticeCell RC = Outputs.get(DefR.Reg);2155if (Offset >= BW) {2156APInt Zero(BW, 0, false);2157RC.add(intToConst(Zero));2158break;2159}2160if (Offset+Bits > BW) {2161// If the requested bitfield extends beyond the most significant bit,2162// the extra bits are treated as 0s. To emulate this behavior, reduce2163// the number of requested bits, and make the extract unsigned.2164Bits = BW-Offset;2165Signed = false;2166}2167bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC);2168if (!Eval)2169return false;2170Outputs.update(DefR.Reg, RC);2171break;2172}21732174case Hexagon::S2_vsplatrb:2175case Hexagon::S2_vsplatrh:2176// vabsh, vabsh:sat2177// vabsw, vabsw:sat2178// vconj:sat2179// vrndwh, vrndwh:sat2180// vsathb, vsathub, vsatwuh2181// vsxtbh, vsxthw2182// vtrunehb, vtrunohb2183// vzxtbh, vzxthw2184{2185bool Eval = evaluateHexVector1(MI, Inputs, Outputs);2186if (!Eval)2187return false;2188break;2189}21902191// TODO:2192// A2_vaddh2193// A2_vaddhs2194// A2_vaddw2195// A2_vaddws2196}21972198return true;2199}22002201bool HexagonConstEvaluator::evaluate(const RegisterSubReg &R,2202const LatticeCell &Input, LatticeCell &Result) {2203if (!R.SubReg) {2204Result = Input;2205return true;2206}2207const TargetRegisterClass *RC = MRI->getRegClass(R.Reg);2208if (RC != &Hexagon::DoubleRegsRegClass)2209return false;2210if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi)2211return false;22122213assert(!Input.isTop());2214if (Input.isBottom())2215return false;22162217using P = ConstantProperties;22182219if (Input.isProperty()) {2220uint32_t Ps = Input.properties();2221if (Ps & (P::Zero|P::NaN)) {2222uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));2223Result.add(Ns);2224return true;2225}2226if (R.SubReg == Hexagon::isub_hi) {2227uint32_t Ns = (Ps & P::SignProperties);2228Result.add(Ns);2229return true;2230}2231return false;2232}22332234// The Input cell contains some known values. Pick the word corresponding2235// to the subregister.2236APInt A;2237for (unsigned i = 0; i < Input.size(); ++i) {2238const Constant *C = Input.Values[i];2239if (!constToInt(C, A))2240return false;2241if (!A.isIntN(64))2242return false;2243uint64_t U = A.getZExtValue();2244if (R.SubReg == Hexagon::isub_hi)2245U >>= 32;2246U &= 0xFFFFFFFFULL;2247uint32_t U32 = Lo_32(U);2248int32_t V32;2249memcpy(&V32, &U32, sizeof V32);2250IntegerType *Ty = Type::getInt32Ty(CX);2251const ConstantInt *C32 = ConstantInt::get(Ty, static_cast<int64_t>(V32));2252Result.add(C32);2253}2254return true;2255}22562257bool HexagonConstEvaluator::evaluate(const MachineInstr &BrI,2258const CellMap &Inputs, SetVector<const MachineBasicBlock*> &Targets,2259bool &FallsThru) {2260// We need to evaluate one branch at a time. TII::analyzeBranch checks2261// all the branches in a basic block at once, so we cannot use it.2262unsigned Opc = BrI.getOpcode();2263bool SimpleBranch = false;2264bool Negated = false;2265switch (Opc) {2266case Hexagon::J2_jumpf:2267case Hexagon::J2_jumpfnew:2268case Hexagon::J2_jumpfnewpt:2269Negated = true;2270[[fallthrough]];2271case Hexagon::J2_jumpt:2272case Hexagon::J2_jumptnew:2273case Hexagon::J2_jumptnewpt:2274// Simple branch: if([!]Pn) jump ...2275// i.e. Op0 = predicate, Op1 = branch target.2276SimpleBranch = true;2277break;2278case Hexagon::J2_jump:2279Targets.insert(BrI.getOperand(0).getMBB());2280FallsThru = false;2281return true;2282default:2283Undetermined:2284// If the branch is of unknown type, assume that all successors are2285// executable.2286FallsThru = !BrI.isUnconditionalBranch();2287return false;2288}22892290if (SimpleBranch) {2291const MachineOperand &MD = BrI.getOperand(0);2292RegisterSubReg PR(MD);2293// If the condition operand has a subregister, this is not something2294// we currently recognize.2295if (PR.SubReg)2296goto Undetermined;2297assert(Inputs.has(PR.Reg));2298const LatticeCell &PredC = Inputs.get(PR.Reg);2299if (PredC.isBottom())2300goto Undetermined;23012302uint32_t Props = PredC.properties();2303bool CTrue = false, CFalse = false;2304if (Props & ConstantProperties::Zero)2305CFalse = true;2306else if (Props & ConstantProperties::NonZero)2307CTrue = true;2308// If the condition is not known to be either, bail out.2309if (!CTrue && !CFalse)2310goto Undetermined;23112312const MachineBasicBlock *BranchTarget = BrI.getOperand(1).getMBB();23132314FallsThru = false;2315if ((!Negated && CTrue) || (Negated && CFalse))2316Targets.insert(BranchTarget);2317else if ((!Negated && CFalse) || (Negated && CTrue))2318FallsThru = true;2319else2320goto Undetermined;2321}23222323return true;2324}23252326bool HexagonConstEvaluator::rewrite(MachineInstr &MI, const CellMap &Inputs) {2327if (MI.isBranch())2328return rewriteHexBranch(MI, Inputs);23292330unsigned Opc = MI.getOpcode();2331switch (Opc) {2332default:2333break;2334case Hexagon::A2_tfrsi:2335case Hexagon::A2_tfrpi:2336case Hexagon::CONST32:2337case Hexagon::CONST64:2338case Hexagon::PS_true:2339case Hexagon::PS_false:2340return false;2341}23422343unsigned NumOp = MI.getNumOperands();2344if (NumOp == 0)2345return false;23462347bool AllDefs, Changed;2348Changed = rewriteHexConstDefs(MI, Inputs, AllDefs);2349// If not all defs have been rewritten (i.e. the instruction defines2350// a register that is not compile-time constant), then try to rewrite2351// register operands that are known to be constant with immediates.2352if (!AllDefs)2353Changed |= rewriteHexConstUses(MI, Inputs);23542355return Changed;2356}23572358unsigned HexagonConstEvaluator::getRegBitWidth(unsigned Reg) const {2359const TargetRegisterClass *RC = MRI->getRegClass(Reg);2360if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))2361return 32;2362if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))2363return 64;2364if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))2365return 8;2366llvm_unreachable("Invalid register");2367return 0;2368}23692370uint32_t HexagonConstEvaluator::getCmp(unsigned Opc) {2371switch (Opc) {2372case Hexagon::C2_cmpeq:2373case Hexagon::C2_cmpeqp:2374case Hexagon::A4_cmpbeq:2375case Hexagon::A4_cmpheq:2376case Hexagon::A4_cmpbeqi:2377case Hexagon::A4_cmpheqi:2378case Hexagon::C2_cmpeqi:2379case Hexagon::J4_cmpeqn1_t_jumpnv_nt:2380case Hexagon::J4_cmpeqn1_t_jumpnv_t:2381case Hexagon::J4_cmpeqi_t_jumpnv_nt:2382case Hexagon::J4_cmpeqi_t_jumpnv_t:2383case Hexagon::J4_cmpeq_t_jumpnv_nt:2384case Hexagon::J4_cmpeq_t_jumpnv_t:2385return Comparison::EQ;23862387case Hexagon::C4_cmpneq:2388case Hexagon::C4_cmpneqi:2389case Hexagon::J4_cmpeqn1_f_jumpnv_nt:2390case Hexagon::J4_cmpeqn1_f_jumpnv_t:2391case Hexagon::J4_cmpeqi_f_jumpnv_nt:2392case Hexagon::J4_cmpeqi_f_jumpnv_t:2393case Hexagon::J4_cmpeq_f_jumpnv_nt:2394case Hexagon::J4_cmpeq_f_jumpnv_t:2395return Comparison::NE;23962397case Hexagon::C2_cmpgt:2398case Hexagon::C2_cmpgtp:2399case Hexagon::A4_cmpbgt:2400case Hexagon::A4_cmphgt:2401case Hexagon::A4_cmpbgti:2402case Hexagon::A4_cmphgti:2403case Hexagon::C2_cmpgti:2404case Hexagon::J4_cmpgtn1_t_jumpnv_nt:2405case Hexagon::J4_cmpgtn1_t_jumpnv_t:2406case Hexagon::J4_cmpgti_t_jumpnv_nt:2407case Hexagon::J4_cmpgti_t_jumpnv_t:2408case Hexagon::J4_cmpgt_t_jumpnv_nt:2409case Hexagon::J4_cmpgt_t_jumpnv_t:2410return Comparison::GTs;24112412case Hexagon::C4_cmplte:2413case Hexagon::C4_cmpltei:2414case Hexagon::J4_cmpgtn1_f_jumpnv_nt:2415case Hexagon::J4_cmpgtn1_f_jumpnv_t:2416case Hexagon::J4_cmpgti_f_jumpnv_nt:2417case Hexagon::J4_cmpgti_f_jumpnv_t:2418case Hexagon::J4_cmpgt_f_jumpnv_nt:2419case Hexagon::J4_cmpgt_f_jumpnv_t:2420return Comparison::LEs;24212422case Hexagon::C2_cmpgtu:2423case Hexagon::C2_cmpgtup:2424case Hexagon::A4_cmpbgtu:2425case Hexagon::A4_cmpbgtui:2426case Hexagon::A4_cmphgtu:2427case Hexagon::A4_cmphgtui:2428case Hexagon::C2_cmpgtui:2429case Hexagon::J4_cmpgtui_t_jumpnv_nt:2430case Hexagon::J4_cmpgtui_t_jumpnv_t:2431case Hexagon::J4_cmpgtu_t_jumpnv_nt:2432case Hexagon::J4_cmpgtu_t_jumpnv_t:2433return Comparison::GTu;24342435case Hexagon::J4_cmpltu_f_jumpnv_nt:2436case Hexagon::J4_cmpltu_f_jumpnv_t:2437return Comparison::GEu;24382439case Hexagon::J4_cmpltu_t_jumpnv_nt:2440case Hexagon::J4_cmpltu_t_jumpnv_t:2441return Comparison::LTu;24422443case Hexagon::J4_cmplt_f_jumpnv_nt:2444case Hexagon::J4_cmplt_f_jumpnv_t:2445return Comparison::GEs;24462447case Hexagon::C4_cmplteu:2448case Hexagon::C4_cmplteui:2449case Hexagon::J4_cmpgtui_f_jumpnv_nt:2450case Hexagon::J4_cmpgtui_f_jumpnv_t:2451case Hexagon::J4_cmpgtu_f_jumpnv_nt:2452case Hexagon::J4_cmpgtu_f_jumpnv_t:2453return Comparison::LEu;24542455case Hexagon::J4_cmplt_t_jumpnv_nt:2456case Hexagon::J4_cmplt_t_jumpnv_t:2457return Comparison::LTs;24582459default:2460break;2461}2462return Comparison::Unk;2463}24642465APInt HexagonConstEvaluator::getCmpImm(unsigned Opc, unsigned OpX,2466const MachineOperand &MO) {2467bool Signed = false;2468switch (Opc) {2469case Hexagon::A4_cmpbgtui: // u72470case Hexagon::A4_cmphgtui: // u72471break;2472case Hexagon::A4_cmpheqi: // s82473case Hexagon::C4_cmpneqi: // s82474Signed = true;2475break;2476case Hexagon::A4_cmpbeqi: // u82477break;2478case Hexagon::C2_cmpgtui: // u92479case Hexagon::C4_cmplteui: // u92480break;2481case Hexagon::C2_cmpeqi: // s102482case Hexagon::C2_cmpgti: // s102483case Hexagon::C4_cmpltei: // s102484Signed = true;2485break;2486case Hexagon::J4_cmpeqi_f_jumpnv_nt: // u52487case Hexagon::J4_cmpeqi_f_jumpnv_t: // u52488case Hexagon::J4_cmpeqi_t_jumpnv_nt: // u52489case Hexagon::J4_cmpeqi_t_jumpnv_t: // u52490case Hexagon::J4_cmpgti_f_jumpnv_nt: // u52491case Hexagon::J4_cmpgti_f_jumpnv_t: // u52492case Hexagon::J4_cmpgti_t_jumpnv_nt: // u52493case Hexagon::J4_cmpgti_t_jumpnv_t: // u52494case Hexagon::J4_cmpgtui_f_jumpnv_nt: // u52495case Hexagon::J4_cmpgtui_f_jumpnv_t: // u52496case Hexagon::J4_cmpgtui_t_jumpnv_nt: // u52497case Hexagon::J4_cmpgtui_t_jumpnv_t: // u52498break;2499default:2500llvm_unreachable("Unhandled instruction");2501break;2502}25032504uint64_t Val = MO.getImm();2505return APInt(32, Val, Signed);2506}25072508void HexagonConstEvaluator::replaceWithNop(MachineInstr &MI) {2509MI.setDesc(HII.get(Hexagon::A2_nop));2510while (MI.getNumOperands() > 0)2511MI.removeOperand(0);2512}25132514bool HexagonConstEvaluator::evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH,2515const CellMap &Inputs, LatticeCell &Result) {2516assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));2517LatticeCell LSL, LSH;2518if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))2519return false;2520if (LSL.isProperty() || LSH.isProperty())2521return false;25222523unsigned LN = LSL.size(), HN = LSH.size();2524SmallVector<APInt,4> LoVs(LN), HiVs(HN);2525for (unsigned i = 0; i < LN; ++i) {2526bool Eval = constToInt(LSL.Values[i], LoVs[i]);2527if (!Eval)2528return false;2529assert(LoVs[i].getBitWidth() == 32);2530}2531for (unsigned i = 0; i < HN; ++i) {2532bool Eval = constToInt(LSH.Values[i], HiVs[i]);2533if (!Eval)2534return false;2535assert(HiVs[i].getBitWidth() == 32);2536}25372538for (unsigned i = 0; i < HiVs.size(); ++i) {2539APInt HV = HiVs[i].zext(64) << 32;2540for (unsigned j = 0; j < LoVs.size(); ++j) {2541APInt LV = LoVs[j].zext(64);2542const Constant *C = intToConst(HV | LV);2543Result.add(C);2544if (Result.isBottom())2545return false;2546}2547}2548return !Result.isBottom();2549}25502551bool HexagonConstEvaluator::evaluateHexCompare(const MachineInstr &MI,2552const CellMap &Inputs, CellMap &Outputs) {2553unsigned Opc = MI.getOpcode();2554bool Classic = false;2555switch (Opc) {2556case Hexagon::C2_cmpeq:2557case Hexagon::C2_cmpeqp:2558case Hexagon::C2_cmpgt:2559case Hexagon::C2_cmpgtp:2560case Hexagon::C2_cmpgtu:2561case Hexagon::C2_cmpgtup:2562case Hexagon::C2_cmpeqi:2563case Hexagon::C2_cmpgti:2564case Hexagon::C2_cmpgtui:2565// Classic compare: Dst0 = CMP Src1, Src22566Classic = true;2567break;2568default:2569// Not handling other compare instructions now.2570return false;2571}25722573if (Classic) {2574const MachineOperand &Src1 = MI.getOperand(1);2575const MachineOperand &Src2 = MI.getOperand(2);25762577bool Result;2578unsigned Opc = MI.getOpcode();2579bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);2580if (Computed) {2581// Only create a zero/non-zero cell. At this time there isn't really2582// much need for specific values.2583RegisterSubReg DefR(MI.getOperand(0));2584LatticeCell L = Outputs.get(DefR.Reg);2585uint32_t P = Result ? ConstantProperties::NonZero2586: ConstantProperties::Zero;2587L.add(P);2588Outputs.update(DefR.Reg, L);2589return true;2590}2591}25922593return false;2594}25952596bool HexagonConstEvaluator::evaluateHexCompare2(unsigned Opc,2597const MachineOperand &Src1, const MachineOperand &Src2,2598const CellMap &Inputs, bool &Result) {2599uint32_t Cmp = getCmp(Opc);2600bool Reg1 = Src1.isReg(), Reg2 = Src2.isReg();2601bool Imm1 = Src1.isImm(), Imm2 = Src2.isImm();2602if (Reg1) {2603RegisterSubReg R1(Src1);2604if (Reg2) {2605RegisterSubReg R2(Src2);2606return evaluateCMPrr(Cmp, R1, R2, Inputs, Result);2607} else if (Imm2) {2608APInt A2 = getCmpImm(Opc, 2, Src2);2609return evaluateCMPri(Cmp, R1, A2, Inputs, Result);2610}2611} else if (Imm1) {2612APInt A1 = getCmpImm(Opc, 1, Src1);2613if (Reg2) {2614RegisterSubReg R2(Src2);2615uint32_t NegCmp = Comparison::negate(Cmp);2616return evaluateCMPri(NegCmp, R2, A1, Inputs, Result);2617} else if (Imm2) {2618APInt A2 = getCmpImm(Opc, 2, Src2);2619return evaluateCMPii(Cmp, A1, A2, Result);2620}2621}2622// Unknown kind of comparison.2623return false;2624}26252626bool HexagonConstEvaluator::evaluateHexLogical(const MachineInstr &MI,2627const CellMap &Inputs, CellMap &Outputs) {2628unsigned Opc = MI.getOpcode();2629if (MI.getNumOperands() != 3)2630return false;2631const MachineOperand &Src1 = MI.getOperand(1);2632const MachineOperand &Src2 = MI.getOperand(2);2633RegisterSubReg R1(Src1);2634bool Eval = false;2635LatticeCell RC;2636switch (Opc) {2637default:2638return false;2639case Hexagon::A2_and:2640case Hexagon::A2_andp:2641Eval = evaluateANDrr(R1, RegisterSubReg(Src2), Inputs, RC);2642break;2643case Hexagon::A2_andir: {2644if (!Src2.isImm())2645return false;2646APInt A(32, Src2.getImm(), true);2647Eval = evaluateANDri(R1, A, Inputs, RC);2648break;2649}2650case Hexagon::A2_or:2651case Hexagon::A2_orp:2652Eval = evaluateORrr(R1, RegisterSubReg(Src2), Inputs, RC);2653break;2654case Hexagon::A2_orir: {2655if (!Src2.isImm())2656return false;2657APInt A(32, Src2.getImm(), true);2658Eval = evaluateORri(R1, A, Inputs, RC);2659break;2660}2661case Hexagon::A2_xor:2662case Hexagon::A2_xorp:2663Eval = evaluateXORrr(R1, RegisterSubReg(Src2), Inputs, RC);2664break;2665}2666if (Eval) {2667RegisterSubReg DefR(MI.getOperand(0));2668Outputs.update(DefR.Reg, RC);2669}2670return Eval;2671}26722673bool HexagonConstEvaluator::evaluateHexCondMove(const MachineInstr &MI,2674const CellMap &Inputs, CellMap &Outputs) {2675// Dst0 = Cond1 ? Src2 : Src32676RegisterSubReg CR(MI.getOperand(1));2677assert(Inputs.has(CR.Reg));2678LatticeCell LS;2679if (!getCell(CR, Inputs, LS))2680return false;2681uint32_t Ps = LS.properties();2682unsigned TakeOp;2683if (Ps & ConstantProperties::Zero)2684TakeOp = 3;2685else if (Ps & ConstantProperties::NonZero)2686TakeOp = 2;2687else2688return false;26892690const MachineOperand &ValOp = MI.getOperand(TakeOp);2691RegisterSubReg DefR(MI.getOperand(0));2692LatticeCell RC = Outputs.get(DefR.Reg);26932694if (ValOp.isImm()) {2695int64_t V = ValOp.getImm();2696unsigned W = getRegBitWidth(DefR.Reg);2697APInt A(W, V, true);2698const Constant *C = intToConst(A);2699RC.add(C);2700Outputs.update(DefR.Reg, RC);2701return true;2702}2703if (ValOp.isReg()) {2704RegisterSubReg R(ValOp);2705const LatticeCell &LR = Inputs.get(R.Reg);2706LatticeCell LSR;2707if (!evaluate(R, LR, LSR))2708return false;2709RC.meet(LSR);2710Outputs.update(DefR.Reg, RC);2711return true;2712}2713return false;2714}27152716bool HexagonConstEvaluator::evaluateHexExt(const MachineInstr &MI,2717const CellMap &Inputs, CellMap &Outputs) {2718// Dst0 = ext R12719RegisterSubReg R1(MI.getOperand(1));2720assert(Inputs.has(R1.Reg));27212722unsigned Opc = MI.getOpcode();2723unsigned Bits;2724switch (Opc) {2725case Hexagon::A2_sxtb:2726case Hexagon::A2_zxtb:2727Bits = 8;2728break;2729case Hexagon::A2_sxth:2730case Hexagon::A2_zxth:2731Bits = 16;2732break;2733case Hexagon::A2_sxtw:2734Bits = 32;2735break;2736default:2737llvm_unreachable("Unhandled extension opcode");2738}27392740bool Signed = false;2741switch (Opc) {2742case Hexagon::A2_sxtb:2743case Hexagon::A2_sxth:2744case Hexagon::A2_sxtw:2745Signed = true;2746break;2747}27482749RegisterSubReg DefR(MI.getOperand(0));2750unsigned BW = getRegBitWidth(DefR.Reg);2751LatticeCell RC = Outputs.get(DefR.Reg);2752bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)2753: evaluateZEXTr(R1, BW, Bits, Inputs, RC);2754if (!Eval)2755return false;2756Outputs.update(DefR.Reg, RC);2757return true;2758}27592760bool HexagonConstEvaluator::evaluateHexVector1(const MachineInstr &MI,2761const CellMap &Inputs, CellMap &Outputs) {2762// DefR = op R12763RegisterSubReg DefR(MI.getOperand(0));2764RegisterSubReg R1(MI.getOperand(1));2765assert(Inputs.has(R1.Reg));2766LatticeCell RC = Outputs.get(DefR.Reg);2767bool Eval;27682769unsigned Opc = MI.getOpcode();2770switch (Opc) {2771case Hexagon::S2_vsplatrb:2772// Rd = 4 times Rs:0..72773Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);2774break;2775case Hexagon::S2_vsplatrh:2776// Rdd = 4 times Rs:0..152777Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);2778break;2779default:2780return false;2781}27822783if (!Eval)2784return false;2785Outputs.update(DefR.Reg, RC);2786return true;2787}27882789bool HexagonConstEvaluator::rewriteHexConstDefs(MachineInstr &MI,2790const CellMap &Inputs, bool &AllDefs) {2791AllDefs = false;27922793// Some diagnostics.2794// LLVM_DEBUG({...}) gets confused with all this code as an argument.2795#ifndef NDEBUG2796bool Debugging = DebugFlag && isCurrentDebugType(DEBUG_TYPE);2797if (Debugging) {2798bool Const = true, HasUse = false;2799for (const MachineOperand &MO : MI.operands()) {2800if (!MO.isReg() || !MO.isUse() || MO.isImplicit())2801continue;2802RegisterSubReg R(MO);2803if (!R.Reg.isVirtual())2804continue;2805HasUse = true;2806// PHIs can legitimately have "top" cells after propagation.2807if (!MI.isPHI() && !Inputs.has(R.Reg)) {2808dbgs() << "Top " << printReg(R.Reg, &HRI, R.SubReg)2809<< " in MI: " << MI;2810continue;2811}2812const LatticeCell &L = Inputs.get(R.Reg);2813Const &= L.isSingle();2814if (!Const)2815break;2816}2817if (HasUse && Const) {2818if (!MI.isCopy()) {2819dbgs() << "CONST: " << MI;2820for (const MachineOperand &MO : MI.operands()) {2821if (!MO.isReg() || !MO.isUse() || MO.isImplicit())2822continue;2823Register R = MO.getReg();2824dbgs() << printReg(R, &TRI) << ": " << Inputs.get(R) << "\n";2825}2826}2827}2828}2829#endif28302831// Avoid generating TFRIs for register transfers---this will keep the2832// coalescing opportunities.2833if (MI.isCopy())2834return false;28352836MachineFunction *MF = MI.getParent()->getParent();2837auto &HST = MF->getSubtarget<HexagonSubtarget>();28382839// Collect all virtual register-def operands.2840SmallVector<unsigned,2> DefRegs;2841for (const MachineOperand &MO : MI.operands()) {2842if (!MO.isReg() || !MO.isDef())2843continue;2844Register R = MO.getReg();2845if (!R.isVirtual())2846continue;2847assert(!MO.getSubReg());2848assert(Inputs.has(R));2849DefRegs.push_back(R);2850}28512852MachineBasicBlock &B = *MI.getParent();2853const DebugLoc &DL = MI.getDebugLoc();2854unsigned ChangedNum = 0;2855#ifndef NDEBUG2856SmallVector<const MachineInstr*,4> NewInstrs;2857#endif28582859// For each defined register, if it is a constant, create an instruction2860// NewR = const2861// and replace all uses of the defined register with NewR.2862for (unsigned R : DefRegs) {2863const LatticeCell &L = Inputs.get(R);2864if (L.isBottom())2865continue;2866const TargetRegisterClass *RC = MRI->getRegClass(R);2867MachineBasicBlock::iterator At = MI.getIterator();28682869if (!L.isSingle()) {2870// If this a zero/non-zero cell, we can fold a definition2871// of a predicate register.2872using P = ConstantProperties;28732874uint64_t Ps = L.properties();2875if (!(Ps & (P::Zero|P::NonZero)))2876continue;2877const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;2878if (RC != PredRC)2879continue;2880const MCInstrDesc *NewD = (Ps & P::Zero) ?2881&HII.get(Hexagon::PS_false) :2882&HII.get(Hexagon::PS_true);2883Register NewR = MRI->createVirtualRegister(PredRC);2884const MachineInstrBuilder &MIB = BuildMI(B, At, DL, *NewD, NewR);2885(void)MIB;2886#ifndef NDEBUG2887NewInstrs.push_back(&*MIB);2888#endif2889replaceAllRegUsesWith(R, NewR);2890} else {2891// This cell has a single value.2892APInt A;2893if (!constToInt(L.Value, A) || !A.isSignedIntN(64))2894continue;2895const TargetRegisterClass *NewRC;2896const MCInstrDesc *NewD;28972898unsigned W = getRegBitWidth(R);2899int64_t V = A.getSExtValue();2900assert(W == 32 || W == 64);2901if (W == 32)2902NewRC = &Hexagon::IntRegsRegClass;2903else2904NewRC = &Hexagon::DoubleRegsRegClass;2905Register NewR = MRI->createVirtualRegister(NewRC);2906const MachineInstr *NewMI;29072908if (W == 32) {2909NewD = &HII.get(Hexagon::A2_tfrsi);2910NewMI = BuildMI(B, At, DL, *NewD, NewR)2911.addImm(V);2912} else {2913if (A.isSignedIntN(8)) {2914NewD = &HII.get(Hexagon::A2_tfrpi);2915NewMI = BuildMI(B, At, DL, *NewD, NewR)2916.addImm(V);2917} else {2918int32_t Hi = V >> 32;2919int32_t Lo = V & 0xFFFFFFFFLL;2920if (isInt<8>(Hi) && isInt<8>(Lo)) {2921NewD = &HII.get(Hexagon::A2_combineii);2922NewMI = BuildMI(B, At, DL, *NewD, NewR)2923.addImm(Hi)2924.addImm(Lo);2925} else if (MF->getFunction().hasOptSize() || !HST.isTinyCore()) {2926// Disable CONST64 for tiny core since it takes a LD resource.2927NewD = &HII.get(Hexagon::CONST64);2928NewMI = BuildMI(B, At, DL, *NewD, NewR)2929.addImm(V);2930} else2931return false;2932}2933}2934(void)NewMI;2935#ifndef NDEBUG2936NewInstrs.push_back(NewMI);2937#endif2938replaceAllRegUsesWith(R, NewR);2939}2940ChangedNum++;2941}29422943LLVM_DEBUG({2944if (!NewInstrs.empty()) {2945MachineFunction &MF = *MI.getParent()->getParent();2946dbgs() << "In function: " << MF.getName() << "\n";2947dbgs() << "Rewrite: for " << MI << " created " << *NewInstrs[0];2948for (unsigned i = 1; i < NewInstrs.size(); ++i)2949dbgs() << " " << *NewInstrs[i];2950}2951});29522953AllDefs = (ChangedNum == DefRegs.size());2954return ChangedNum > 0;2955}29562957bool HexagonConstEvaluator::rewriteHexConstUses(MachineInstr &MI,2958const CellMap &Inputs) {2959bool Changed = false;2960unsigned Opc = MI.getOpcode();2961MachineBasicBlock &B = *MI.getParent();2962const DebugLoc &DL = MI.getDebugLoc();2963MachineBasicBlock::iterator At = MI.getIterator();2964MachineInstr *NewMI = nullptr;29652966switch (Opc) {2967case Hexagon::M2_maci:2968// Convert DefR += mpyi(R2, R3)2969// to DefR += mpyi(R, #imm),2970// or DefR -= mpyi(R, #imm).2971{2972RegisterSubReg DefR(MI.getOperand(0));2973assert(!DefR.SubReg);2974RegisterSubReg R2(MI.getOperand(2));2975RegisterSubReg R3(MI.getOperand(3));2976assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg));2977LatticeCell LS2, LS3;2978// It is enough to get one of the input cells, since we will only try2979// to replace one argument---whichever happens to be a single constant.2980bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);2981if (!HasC2 && !HasC3)2982return false;2983bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||2984(HasC3 && (LS3.properties() & ConstantProperties::Zero)));2985// If one of the operands is zero, eliminate the multiplication.2986if (Zero) {2987// DefR == R1 (tied operands).2988MachineOperand &Acc = MI.getOperand(1);2989RegisterSubReg R1(Acc);2990unsigned NewR = R1.Reg;2991if (R1.SubReg) {2992// Generate COPY. FIXME: Replace with the register:subregister.2993const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);2994NewR = MRI->createVirtualRegister(RC);2995NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)2996.addReg(R1.Reg, getRegState(Acc), R1.SubReg);2997}2998replaceAllRegUsesWith(DefR.Reg, NewR);2999MRI->clearKillFlags(NewR);3000Changed = true;3001break;3002}30033004bool Swap = false;3005if (!LS3.isSingle()) {3006if (!LS2.isSingle())3007return false;3008Swap = true;3009}3010const LatticeCell &LI = Swap ? LS2 : LS3;3011const MachineOperand &OpR2 = Swap ? MI.getOperand(3)3012: MI.getOperand(2);3013// LI is single here.3014APInt A;3015if (!constToInt(LI.Value, A) || !A.isSignedIntN(8))3016return false;3017int64_t V = A.getSExtValue();3018const MCInstrDesc &D = (V >= 0) ? HII.get(Hexagon::M2_macsip)3019: HII.get(Hexagon::M2_macsin);3020if (V < 0)3021V = -V;3022const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);3023Register NewR = MRI->createVirtualRegister(RC);3024const MachineOperand &Src1 = MI.getOperand(1);3025NewMI = BuildMI(B, At, DL, D, NewR)3026.addReg(Src1.getReg(), getRegState(Src1), Src1.getSubReg())3027.addReg(OpR2.getReg(), getRegState(OpR2), OpR2.getSubReg())3028.addImm(V);3029replaceAllRegUsesWith(DefR.Reg, NewR);3030Changed = true;3031break;3032}30333034case Hexagon::A2_and:3035{3036RegisterSubReg R1(MI.getOperand(1));3037RegisterSubReg R2(MI.getOperand(2));3038assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));3039LatticeCell LS1, LS2;3040unsigned CopyOf = 0;3041// Check if any of the operands is -1 (i.e. all bits set).3042if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {3043APInt M1;3044if (constToInt(LS1.Value, M1) && !~M1)3045CopyOf = 2;3046}3047else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) {3048APInt M1;3049if (constToInt(LS2.Value, M1) && !~M1)3050CopyOf = 1;3051}3052if (!CopyOf)3053return false;3054MachineOperand &SO = MI.getOperand(CopyOf);3055RegisterSubReg SR(SO);3056RegisterSubReg DefR(MI.getOperand(0));3057unsigned NewR = SR.Reg;3058if (SR.SubReg) {3059const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);3060NewR = MRI->createVirtualRegister(RC);3061NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)3062.addReg(SR.Reg, getRegState(SO), SR.SubReg);3063}3064replaceAllRegUsesWith(DefR.Reg, NewR);3065MRI->clearKillFlags(NewR);3066Changed = true;3067}3068break;30693070case Hexagon::A2_or:3071{3072RegisterSubReg R1(MI.getOperand(1));3073RegisterSubReg R2(MI.getOperand(2));3074assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));3075LatticeCell LS1, LS2;3076unsigned CopyOf = 0;30773078using P = ConstantProperties;30793080if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))3081CopyOf = 2;3082else if (getCell(R2, Inputs, LS2) && (LS2.properties() & P::Zero))3083CopyOf = 1;3084if (!CopyOf)3085return false;3086MachineOperand &SO = MI.getOperand(CopyOf);3087RegisterSubReg SR(SO);3088RegisterSubReg DefR(MI.getOperand(0));3089unsigned NewR = SR.Reg;3090if (SR.SubReg) {3091const TargetRegisterClass *RC = MRI->getRegClass(DefR.Reg);3092NewR = MRI->createVirtualRegister(RC);3093NewMI = BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)3094.addReg(SR.Reg, getRegState(SO), SR.SubReg);3095}3096replaceAllRegUsesWith(DefR.Reg, NewR);3097MRI->clearKillFlags(NewR);3098Changed = true;3099}3100break;3101}31023103if (NewMI) {3104// clear all the kill flags of this new instruction.3105for (MachineOperand &MO : NewMI->operands())3106if (MO.isReg() && MO.isUse())3107MO.setIsKill(false);3108}31093110LLVM_DEBUG({3111if (NewMI) {3112dbgs() << "Rewrite: for " << MI;3113if (NewMI != &MI)3114dbgs() << " created " << *NewMI;3115else3116dbgs() << " modified the instruction itself and created:" << *NewMI;3117}3118});31193120return Changed;3121}31223123void HexagonConstEvaluator::replaceAllRegUsesWith(Register FromReg,3124Register ToReg) {3125assert(FromReg.isVirtual());3126assert(ToReg.isVirtual());3127for (MachineOperand &O :3128llvm::make_early_inc_range(MRI->use_operands(FromReg)))3129O.setReg(ToReg);3130}31313132bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI,3133const CellMap &Inputs) {3134MachineBasicBlock &B = *BrI.getParent();3135unsigned NumOp = BrI.getNumOperands();3136if (!NumOp)3137return false;31383139bool FallsThru;3140SetVector<const MachineBasicBlock*> Targets;3141bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);3142unsigned NumTargets = Targets.size();3143if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))3144return false;3145if (BrI.getOpcode() == Hexagon::J2_jump)3146return false;31473148LLVM_DEBUG(dbgs() << "Rewrite(" << printMBBReference(B) << "):" << BrI);3149bool Rewritten = false;3150if (NumTargets > 0) {3151assert(!FallsThru && "This should have been checked before");3152// MIB.addMBB needs non-const pointer.3153MachineBasicBlock *TargetB = const_cast<MachineBasicBlock*>(Targets[0]);3154bool Moot = B.isLayoutSuccessor(TargetB);3155if (!Moot) {3156// If we build a branch here, we must make sure that it won't be3157// erased as "non-executable". We can't mark any new instructions3158// as executable here, so we need to overwrite the BrI, which we3159// know is executable.3160const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);3161auto NI = BuildMI(B, BrI.getIterator(), BrI.getDebugLoc(), JD)3162.addMBB(TargetB);3163BrI.setDesc(JD);3164while (BrI.getNumOperands() > 0)3165BrI.removeOperand(0);3166// This ensures that all implicit operands (e.g. implicit-def %r31, etc)3167// are present in the rewritten branch.3168for (auto &Op : NI->operands())3169BrI.addOperand(Op);3170NI->eraseFromParent();3171Rewritten = true;3172}3173}31743175// Do not erase instructions. A newly created instruction could get3176// the same address as an instruction marked as executable during the3177// propagation.3178if (!Rewritten)3179replaceWithNop(BrI);3180return true;3181}31823183FunctionPass *llvm::createHexagonConstPropagationPass() {3184return new HexagonConstPropagation();3185}318631873188