Skip to content

Commit

Permalink
Extract LaneBitmask into a separate type
Browse files Browse the repository at this point in the history
Specifically avoid implicit conversions from/to integral types to
avoid potential errors when changing the underlying type. For example,
a typical initialization of a "full" mask was "LaneMask = ~0u", which
would result in a value of 0x00000000FFFFFFFF if the type was extended
to uint64_t.

Differential Revision: https://reviews.llvm.org/D27454


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289820 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Krzysztof Parzyszek committed Dec 15, 2016
1 parent 255071b commit d6ca3f0
Show file tree
Hide file tree
Showing 40 changed files with 421 additions and 326 deletions.
3 changes: 2 additions & 1 deletion include/llvm/CodeGen/LiveIntervalAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void repairOldRegInRange(MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
const SlotIndex endIdx, LiveRange &LR,
unsigned Reg, LaneBitmask LaneMask = ~0u);
unsigned Reg,
LaneBitmask LaneMask = LaneBitmask::getAll());

class HMEditor;
};
Expand Down
13 changes: 7 additions & 6 deletions include/llvm/CodeGen/MachineBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/CodeGen/MachineInstrBundleIterator.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/DataTypes.h"
#include <functional>
Expand All @@ -35,9 +36,6 @@ class StringRef;
class raw_ostream;
class MachineBranchProbabilityInfo;

// Forward declaration to avoid circular include problem with TargetRegisterInfo
typedef unsigned LaneBitmask;

template <> struct ilist_traits<MachineInstr> {
private:
friend class MachineBasicBlock; // Set by the owning MachineBasicBlock.
Expand Down Expand Up @@ -278,7 +276,8 @@ class MachineBasicBlock
/// Adds the specified register as a live in. Note that it is an error to add
/// the same register to the same set more than once unless the intention is
/// to call sortUniqueLiveIns after all registers are added.
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask = ~0u) {
void addLiveIn(MCPhysReg PhysReg,
LaneBitmask LaneMask = LaneBitmask::getAll()) {
LiveIns.push_back(RegisterMaskPair(PhysReg, LaneMask));
}
void addLiveIn(const RegisterMaskPair &RegMaskPair) {
Expand All @@ -296,10 +295,12 @@ class MachineBasicBlock
unsigned addLiveIn(MCPhysReg PhysReg, const TargetRegisterClass *RC);

/// Remove the specified register from the live in set.
void removeLiveIn(MCPhysReg Reg, LaneBitmask LaneMask = ~0u);
void removeLiveIn(MCPhysReg Reg,
LaneBitmask LaneMask = LaneBitmask::getAll());

/// Return true if the specified register is in the live in set.
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask = ~0u) const;
bool isLiveIn(MCPhysReg Reg,
LaneBitmask LaneMask = LaneBitmask::getAll()) const;

// Iteration support for live in sets. These sets are kept in sorted
// order by their register number.
Expand Down
12 changes: 6 additions & 6 deletions include/llvm/CodeGen/RegisterPressure.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class LiveRegSet {
unsigned SparseIndex = getSparseIndexFromReg(Reg);
RegSet::const_iterator I = Regs.find(SparseIndex);
if (I == Regs.end())
return 0;
return LaneBitmask::getNone();
return I->LaneMask;
}

Expand All @@ -288,11 +288,11 @@ class LiveRegSet {
unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit);
auto InsertRes = Regs.insert(IndexMaskPair(SparseIndex, Pair.LaneMask));
if (!InsertRes.second) {
unsigned PrevMask = InsertRes.first->LaneMask;
LaneBitmask PrevMask = InsertRes.first->LaneMask;
InsertRes.first->LaneMask |= Pair.LaneMask;
return PrevMask;
}
return 0;
return LaneBitmask::getNone();
}

/// Clears the \p Pair.LaneMask lanes of \p Pair.Reg (mark them as dead).
Expand All @@ -301,8 +301,8 @@ class LiveRegSet {
unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit);
RegSet::iterator I = Regs.find(SparseIndex);
if (I == Regs.end())
return 0;
unsigned PrevMask = I->LaneMask;
return LaneBitmask::getNone();
LaneBitmask PrevMask = I->LaneMask;
I->LaneMask &= ~Pair.LaneMask;
return PrevMask;
}
Expand All @@ -315,7 +315,7 @@ class LiveRegSet {
void appendTo(ContainerT &To) const {
for (const IndexMaskPair &P : Regs) {
unsigned Reg = getRegFromSparseIndex(P.Index);
if (P.LaneMask != 0)
if (!P.LaneMask.none())
To.push_back(RegisterMaskPair(Reg, P.LaneMask));
}
}
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/CodeGen/RegisterScavenging.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class RegScavenger {
}

/// Tell the scavenger a register is used.
void setRegUsed(unsigned Reg, LaneBitmask LaneMask = ~0u);
void setRegUsed(unsigned Reg, LaneBitmask LaneMask = LaneBitmask::getAll());
private:
/// Returns true if a register is reserved. It is never "unused".
bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); }
Expand Down
88 changes: 88 additions & 0 deletions include/llvm/MC/LaneBitmask.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//===-- llvm/MC/LaneBitmask.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// A common definition of LaneBitmask for use in TableGen and CodeGen.
///
/// A lane mask is a bitmask representing the covering of a register with
/// sub-registers.
///
/// This is typically used to track liveness at sub-register granularity.
/// Lane masks for sub-register indices are similar to register units for
/// physical registers. The individual bits in a lane mask can't be assigned
/// any specific meaning. They can be used to check if two sub-register
/// indices overlap.
///
/// Iff the target has a register such that:
///
/// getSubReg(Reg, A) overlaps getSubReg(Reg, B)
///
/// then:
///
/// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0

#ifndef LLVM_MC_LANEBITMASK_H
#define LLVM_MC_LANEBITMASK_H

#include "llvm/Support/Format.h"
#include "llvm/Support/Printable.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {
struct LaneBitmask {
// When changing the underlying type, change the format string as well.
typedef unsigned Type;
enum : unsigned { BitWidth = 8*sizeof(Type) };
constexpr static const char *const FormatStr = "%08X";

constexpr LaneBitmask() = default;
explicit constexpr LaneBitmask(Type V) : Mask(V) {}

constexpr bool operator== (LaneBitmask M) const { return Mask == M.Mask; }
constexpr bool operator!= (LaneBitmask M) const { return Mask != M.Mask; }
constexpr bool operator< (LaneBitmask M) const { return Mask < M.Mask; }
constexpr bool none() const { return Mask == 0; }
constexpr bool all() const { return ~Mask == 0; }

constexpr LaneBitmask operator~() const {
return LaneBitmask(~Mask);
}
constexpr LaneBitmask operator|(LaneBitmask M) const {
return LaneBitmask(Mask | M.Mask);
}
constexpr LaneBitmask operator&(LaneBitmask M) const {
return LaneBitmask(Mask & M.Mask);
}
LaneBitmask &operator|=(LaneBitmask M) {
Mask |= M.Mask;
return *this;
}
LaneBitmask &operator&=(LaneBitmask M) {
Mask &= M.Mask;
return *this;
}

constexpr Type getAsInteger() const { return Mask; }

static LaneBitmask getNone() { return LaneBitmask(0); }
static LaneBitmask getAll() { return ~LaneBitmask(0); }

private:
Type Mask = 0;
};

/// Create Printable object to print LaneBitmasks on a \ref raw_ostream.
static LLVM_ATTRIBUTE_UNUSED Printable PrintLaneMask(LaneBitmask LaneMask) {
return Printable([LaneMask](raw_ostream &OS) {
OS << format(LaneBitmask::FormatStr, LaneMask.getAsInteger());
});
}
}

#endif // LLVM_MC_LANEBITMASK_H
9 changes: 5 additions & 4 deletions include/llvm/MC/MCRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define LLVM_MC_MCREGISTERINFO_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>

Expand Down Expand Up @@ -161,7 +162,7 @@ class MCRegisterInfo {
unsigned NumRegUnits; // Number of regunits.
const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table.
const MCPhysReg *DiffLists; // Pointer to the difflists array
const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences
const LaneBitmask *RegUnitMaskSequences; // Pointer to lane mask sequences
// for register units.
const char *RegStrings; // Pointer to the string table.
const char *RegClassStrings; // Pointer to the class strings.
Expand Down Expand Up @@ -248,7 +249,7 @@ class MCRegisterInfo {
const MCPhysReg (*RURoots)[2],
unsigned NRU,
const MCPhysReg *DL,
const unsigned *RUMS,
const LaneBitmask *RUMS,
const char *Strings,
const char *ClassStrings,
const uint16_t *SubIndices,
Expand Down Expand Up @@ -584,7 +585,7 @@ class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator {
/// numerical order.
class MCRegUnitMaskIterator {
MCRegUnitIterator RUIter;
const unsigned *MaskListIter;
const LaneBitmask *MaskListIter;
public:
MCRegUnitMaskIterator() {}
/// Constructs an iterator that traverses the register units and their
Expand All @@ -596,7 +597,7 @@ class MCRegUnitMaskIterator {
}

/// Returns a (RegUnit, LaneMask) pair.
std::pair<unsigned,unsigned> operator*() const {
std::pair<unsigned,LaneBitmask> operator*() const {
return std::make_pair(*RUIter, *MaskListIter);
}

Expand Down
24 changes: 2 additions & 22 deletions include/llvm/Target/TargetRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,6 @@ class VirtRegMap;
class raw_ostream;
class LiveRegMatrix;

/// A bitmask representing the covering of a register with sub-registers.
///
/// This is typically used to track liveness at sub-register granularity.
/// Lane masks for sub-register indices are similar to register units for
/// physical registers. The individual bits in a lane mask can't be assigned
/// any specific meaning. They can be used to check if two sub-register
/// indices overlap.
///
/// Iff the target has a register such that:
///
/// getSubReg(Reg, A) overlaps getSubReg(Reg, B)
///
/// then:
///
/// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0
typedef unsigned LaneBitmask;

class TargetRegisterClass {
public:
typedef const MCPhysReg* iterator;
Expand Down Expand Up @@ -269,15 +252,15 @@ class TargetRegisterInfo : public MCRegisterInfo {
const LaneBitmask *SubRegIndexLaneMasks;

regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses
unsigned CoveringLanes;
LaneBitmask CoveringLanes;

protected:
TargetRegisterInfo(const TargetRegisterInfoDesc *ID,
regclass_iterator RegClassBegin,
regclass_iterator RegClassEnd,
const char *const *SRINames,
const LaneBitmask *SRILaneMasks,
unsigned CoveringLanes);
LaneBitmask CoveringLanes);
virtual ~TargetRegisterInfo();
public:

Expand Down Expand Up @@ -1141,9 +1124,6 @@ Printable PrintRegUnit(unsigned Unit, const TargetRegisterInfo *TRI);
/// registers on a \ref raw_ostream.
Printable PrintVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI);

/// Create Printable object to print LaneBitmasks on a \ref raw_ostream.
Printable PrintLaneMask(LaneBitmask LaneMask);

} // End llvm namespace

#endif
24 changes: 12 additions & 12 deletions lib/CodeGen/DetectDeadLanes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ void DetectDeadLanes::addUsedLanesOnOperand(const MachineOperand &MO,
VRegInfo &MORegInfo = VRegInfos[MORegIdx];
LaneBitmask PrevUsedLanes = MORegInfo.UsedLanes;
// Any change at all?
if ((UsedLanes & ~PrevUsedLanes) == 0)
if ((UsedLanes & ~PrevUsedLanes).none())
return;

// Set UsedLanes and remember instruction for further propagation.
Expand Down Expand Up @@ -303,7 +303,7 @@ void DetectDeadLanes::transferDefinedLanesStep(const MachineOperand &Use,
VRegInfo &RegInfo = VRegInfos[DefRegIdx];
LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
// Any change at all?
if ((DefinedLanes & ~PrevDefinedLanes) == 0)
if ((DefinedLanes & ~PrevDefinedLanes).none())
return;

RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
Expand Down Expand Up @@ -356,7 +356,7 @@ LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {
// Live-In or unused registers have no definition but are considered fully
// defined.
if (!MRI->hasOneDef(Reg))
return ~0u;
return LaneBitmask::getAll();

const MachineOperand &Def = *MRI->def_begin(Reg);
const MachineInstr &DefMI = *Def.getParent();
Expand All @@ -368,15 +368,15 @@ LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {
PutInWorklist(RegIdx);

if (Def.isDead())
return 0;
return LaneBitmask::getNone();

// COPY/PHI can copy across unrelated register classes (example: float/int)
// with incompatible subregister structure. Do not include these in the
// dataflow analysis since we cannot transfer lanemasks in a meaningful way.
const TargetRegisterClass *DefRC = MRI->getRegClass(Reg);

// Determine initially DefinedLanes.
LaneBitmask DefinedLanes = 0;
LaneBitmask DefinedLanes;
for (const MachineOperand &MO : DefMI.uses()) {
if (!MO.isReg() || !MO.readsReg())
continue;
Expand All @@ -386,9 +386,9 @@ LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {

LaneBitmask MODefinedLanes;
if (TargetRegisterInfo::isPhysicalRegister(MOReg)) {
MODefinedLanes = ~0u;
MODefinedLanes = LaneBitmask::getAll();
} else if (isCrossCopy(*MRI, DefMI, DefRC, MO)) {
MODefinedLanes = ~0u;
MODefinedLanes = LaneBitmask::getAll();
} else {
assert(TargetRegisterInfo::isVirtualRegister(MOReg));
if (MRI->hasOneDef(MOReg)) {
Expand All @@ -410,15 +410,15 @@ LaneBitmask DetectDeadLanes::determineInitialDefinedLanes(unsigned Reg) {
return DefinedLanes;
}
if (DefMI.isImplicitDef() || Def.isDead())
return 0;
return LaneBitmask::getNone();

assert(Def.getSubReg() == 0 &&
"Should not have subregister defs in machine SSA phase");
return MRI->getMaxLaneMaskForVReg(Reg);
}

LaneBitmask DetectDeadLanes::determineInitialUsedLanes(unsigned Reg) {
LaneBitmask UsedLanes = 0;
LaneBitmask UsedLanes = LaneBitmask::getNone();
for (const MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
if (!MO.readsReg())
continue;
Expand Down Expand Up @@ -462,7 +462,7 @@ bool DetectDeadLanes::isUndefRegAtInput(const MachineOperand &MO,
const VRegInfo &RegInfo) const {
unsigned SubReg = MO.getSubReg();
LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubReg);
return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask) == 0;
return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
}

bool DetectDeadLanes::isUndefInput(const MachineOperand &MO,
Expand All @@ -482,7 +482,7 @@ bool DetectDeadLanes::isUndefInput(const MachineOperand &MO,

const VRegInfo &DefRegInfo = VRegInfos[DefRegIdx];
LaneBitmask UsedLanes = transferUsedLanes(MI, DefRegInfo.UsedLanes, MO);
if (UsedLanes != 0)
if (!UsedLanes.none())
return false;

unsigned MOReg = MO.getReg();
Expand Down Expand Up @@ -546,7 +546,7 @@ bool DetectDeadLanes::runOnce(MachineFunction &MF) {
continue;
unsigned RegIdx = TargetRegisterInfo::virtReg2Index(Reg);
const VRegInfo &RegInfo = VRegInfos[RegIdx];
if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes == 0) {
if (MO.isDef() && !MO.isDead() && RegInfo.UsedLanes.none()) {
DEBUG(dbgs() << "Marking operand '" << MO << "' as dead in " << MI);
MO.setIsDead();
}
Expand Down
Loading

0 comments on commit d6ca3f0

Please sign in to comment.