IValueT getEncodedGPRegNum(const Variable *Var) {
assert(Var->hasReg());
- int32_t Reg = Var->getRegNum();
+ const auto Reg = Var->getRegNum();
return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
: RegARM32::getEncodedGPR(Reg);
}
IOffsetT Offset = Var->getStackOffset();
if (!Utils::IsAbsoluteUint(12, Offset))
return CantEncode;
- int32_t BaseRegNum = Var->getBaseRegNum();
- if (BaseRegNum == Variable::NoRegister)
- BaseRegNum = TInfo.FrameOrStackReg;
+ const auto BaseRegNum =
+ Var->hasReg() ? Var->getBaseRegNum() : TInfo.FrameOrStackReg;
Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset,
OperandARM32Mem::Offset);
return EncodedAsImmRegOffset;
return;
if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc))
llvm::report_fatal_error(std::string(InstName) + ": " +
- RegARM32::getRegName(Reg) +
+ RegARM32::getRegName(RegARM32::Reg_pc) +
"=pc not allowed when CC=1");
}
IValueT Inst = Asm.load<IValueT>(position());
Str << "\t"
"mov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t"
- << RegARM32::getRegName((Inst >> kRdShift) & 0xF)
+ << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF))
<< ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper")
<< "16:" << symbol(Ctx, &Asm) << "\t@ .word "
<< llvm::format_hex_no_prefix(Inst, 8) << "\n";
TargetInfo &operator=(const TargetInfo &) = delete;
public:
- TargetInfo(bool HasFramePointer, SizeT FrameOrStackReg)
+ TargetInfo(bool HasFramePointer, RegNumT FrameOrStackReg)
: HasFramePointer(HasFramePointer), FrameOrStackReg(FrameOrStackReg) {}
explicit TargetInfo(const TargetLowering *Target)
: HasFramePointer(Target->hasFramePointer()),
FrameOrStackReg(Target->getFrameOrStackReg()) {}
const bool HasFramePointer;
- const SizeT FrameOrStackReg;
+ const RegNumT FrameOrStackReg;
};
explicit AssemblerARM32(bool use_far_branches = false)
if (!Var2->hasReg())
return false;
- int32_t RegNum1 = Var1->getRegNum();
- int32_t RegNum2 = Var2->getRegNum();
+ const auto RegNum1 = Var1->getRegNum();
+ const auto RegNum2 = Var2->getRegNum();
// Quick common-case check.
if (RegNum1 == RegNum2)
return true;
return;
Liveness *Liveness = Func->getLiveness();
const LivenessBV *Live;
- const int32_t StackReg = Func->getTarget()->getStackReg();
- const int32_t FrameOrStackReg = Func->getTarget()->getFrameOrStackReg();
+ const auto StackReg = Func->getTarget()->getStackReg();
+ const auto FrameOrStackReg = Func->getTarget()->getFrameOrStackReg();
if (IsLiveIn) {
Live = &Liveness->getLiveIn(Node);
Str << "\t\t\t\t/* LiveIn=";
Variable *Var = Liveness->getVariable(i, Node);
if (!Var->hasReg())
continue;
- const int32_t RegNum = Var->getRegNum();
+ const auto RegNum = Var->getRegNum();
if (RegNum == StackReg || RegNum == FrameOrStackReg)
continue;
if (IsLiveIn)
// order.
std::sort(LiveRegs.begin(), LiveRegs.end(),
[](const Variable *V1, const Variable *V2) {
- return V1->getRegNum() < V2->getRegNum();
+ return unsigned(V1->getRegNum()) < unsigned(V2->getRegNum());
});
bool First = true;
for (Variable *Var : LiveRegs) {
Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t" << getSRegOpcode() << "\t{";
bool IsFirst = true;
- int32_t Base = BaseReg->getRegNum();
+ const auto Base = BaseReg->getRegNum();
for (SizeT i = 0; i < RegCount; ++i) {
if (IsFirst)
IsFirst = false;
else
Str << ", ";
- Str << RegARM32::getRegName(Base + i);
+ Str << RegARM32::getRegName(RegNumT::fixme(Base + i));
}
Str << "}";
}
bool isAssignedConsecutiveRegisters(const Variable *Before,
const Variable *After) {
- return RegARM32::getEncodedSReg(Before->getRegNum()) + 1 ==
- RegARM32::getEncodedSReg(After->getRegNum());
+ assert(Before->hasReg());
+ assert(After->hasReg());
+ return RegNumT::fixme(Before->getRegNum() + 1) == After->getRegNum();
}
} // end of anonymous namespace
for (SizeT i = 0; i < NumRegs; ++i) {
const Variable *Var = getStackReg(i);
assert(Var->hasReg() && "stack op only applies to registers");
- int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum());
+ const RegARM32::GPRRegister Reg =
+ RegARM32::getEncodedGPR(Var->getRegNum());
LastDest = Var;
GPRegisters |= (1 << Reg);
++IntegerCount;
// register that this instruction is accessing.
Register getDRegister(const Variable *Src, uint32_t Index) {
assert(Src->hasReg());
- const auto SrcReg = static_cast<Register>(Src->getRegNum());
+ const auto SrcReg = Src->getRegNum();
const RegARM32::RegTableType &SrcEntry = RegARM32::RegTable[SrcReg];
assert(SrcEntry.IsVec128);
// directly from an S register. This function finds the right one.
Register getSRegister(const Variable *Src, uint32_t Index) {
assert(Src->hasReg());
- const auto SrcReg = static_cast<Register>(Src->getRegNum());
+ const auto SrcReg = Src->getRegNum();
// For floating point values, we need to be allocated to Q0 - Q7, so we can
// directly access the value we want as one of the S registers.
static bool classof(const Operand *Operand) {
return Operand->getKind() == StackVariableKind;
}
- void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; }
- int32_t getBaseRegNum() const override { return BaseRegNum; }
+ void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
+ RegNumT getBaseRegNum() const override { return BaseRegNum; }
// Inherit dump() and emit() from Variable.
private:
StackVariable(Type Ty, SizeT Index)
: Variable(StackVariableKind, Ty, Index) {}
- int32_t BaseRegNum = Variable::NoRegister;
+ RegNumT BaseRegNum = RegNumT::NoRegister;
};
/// Base class for ARM instructions. While most ARM instructions can be
namespace {
-int32_t GetRematerializableOffset(Variable *Var,
+int32_t getRematerializableOffset(Variable *Var,
const Ice::X8632::TargetX8632 *Target) {
int32_t Disp = Var->getStackOffset();
- SizeT RegNum = static_cast<SizeT>(Var->getRegNum());
+ const auto RegNum = Var->getRegNum();
if (RegNum == Target->getFrameReg()) {
Disp += Target->getFrameFixedAllocaOffset();
} else if (RegNum != Target->getStackReg()) {
// physical register (esp or ebp), and update the Offset.
int32_t Disp = 0;
if (getBase() && getBase()->isRematerializable()) {
- Disp += GetRematerializableOffset(getBase(), Target);
+ Disp += getRematerializableOffset(getBase(), Target);
}
// The index should never be rematerializable. But if we ever allow it, then
// we should make sure the rematerialization offset is shifted by the Shift
const auto *Target =
static_cast<const ::Ice::X8632::TargetX8632 *>(Func->getTarget());
if (getBase() && getBase()->isRematerializable()) {
- Disp += GetRematerializableOffset(getBase(), Target);
+ Disp += getRematerializableOffset(getBase(), Target);
}
if (getBase()) {
if (Func)
validateMemOperandPIC(this, UseNonsfi);
int32_t Disp = 0;
if (getBase() && getBase()->isRematerializable()) {
- Disp += GetRematerializableOffset(getBase(), Target);
+ Disp += getRematerializableOffset(getBase(), Target);
}
// The index should never be rematerializable. But if we ever allow it, then
// we should make sure the rematerialization offset is shifted by the Shift
}
namespace {
-static int32_t
-getRematerializableOffset(Variable *Var,
- const ::Ice::X8664::TargetX8664 *Target) {
+int32_t getRematerializableOffset(Variable *Var,
+ const ::Ice::X8664::TargetX8664 *Target) {
int32_t Disp = Var->getStackOffset();
- SizeT RegNum = static_cast<SizeT>(Var->getRegNum());
+ const auto RegNum = Var->getRegNum();
if (RegNum == Target->getFrameReg()) {
Disp += Target->getFrameFixedAllocaOffset();
} else if (RegNum != Target->getStackReg()) {
const Operand *Src2Op,
const GPREmitterShiftD &Emitter);
- template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
- SReg_t (*srcEnc)(int32_t)>
+ template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+ SReg_t (*srcEnc)(RegNumT)>
static void emitIASCastRegOp(const Cfg *Func, Type DestTy,
const Variable *Dest, Type SrcTy,
const Operand *Src,
const CastEmitterRegOp<DReg_t, SReg_t> &Emitter);
- template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
- SReg_t (*srcEnc)(int32_t)>
+ template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+ SReg_t (*srcEnc)(RegNumT)>
static void
emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy, const Variable *Dest,
const Operand *Src0, const Operand *Src1,
// mov ch, ebp ==> not redundant due to different base registers
// mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting
// is handled by Inst86Zext.
- const int32_t SrcReg = SrcVar->getRegNum();
- const int32_t DestReg = this->Dest->getRegNum();
+ const auto SrcReg = SrcVar->getRegNum();
+ const auto DestReg = this->Dest->getRegNum();
return (Traits::getEncoding(SrcReg) ==
Traits::getEncoding(DestReg)) &&
(Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg));
}
template <typename TraitsType>
-template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
- SReg_t (*srcEnc)(int32_t)>
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+ SReg_t (*srcEnc)(RegNumT)>
void InstImpl<TraitsType>::emitIASCastRegOp(
const Cfg *Func, Type DestTy, const Variable *Dest, Type SrcTy,
const Operand *Src, const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
}
template <typename TraitsType>
-template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
- SReg_t (*srcEnc)(int32_t)>
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+ SReg_t (*srcEnc)(RegNumT)>
void InstImpl<TraitsType>::emitIASThreeOpImmOps(
const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
const Operand *Src1, const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
Ostream &Str = Func->getContext()->getStrEmit();
assert(this->getSrcSize() == 1);
Operand *Src0 = this->getSrc(0);
- int32_t DestReg = this->getDest()->getRegNum();
- int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
+ const auto DestReg = this->getDest()->getRegNum();
+ const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
(void)DestReg;
(void)SrcReg;
switch (Src0->getType()) {
Assembler *Asm = Func->getAssembler<Assembler>();
assert(this->getSrcSize() == 1);
Operand *Src0 = this->getSrc(0);
- int32_t DestReg = this->getDest()->getRegNum();
- int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
+ const auto DestReg = this->getDest()->getRegNum();
+ const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
(void)DestReg;
(void)SrcReg;
switch (Src0->getType()) {
Type Ty = Src0Var->getType();
// lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
// acceptable type.
- Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister)
+ Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, RegNumT::NoRegister)
->emit(Func);
} else {
Src0->emit(Func);
InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
const Operand *NewSrc = Src;
if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
- int32_t NewRegNum = Variable::NoRegister;
+ auto NewRegNum = RegNumT::NoRegister;
if (SrcVar->hasReg())
NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
if (SrcTy != DestTy)
if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
// If src1 is a register, it should always be r32.
if (Src1Var->hasReg()) {
- int32_t NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
+ const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum);
NewSrc->emit(Func);
} else {
if (BuildDefs::asserts()) {
if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
if (Src0Var->hasReg()) {
- int32_t RegNum = Src0Var->getRegNum();
- int32_t BaseRegNum = Traits::getBaseReg(RegNum);
+ const auto RegNum = Src0Var->getRegNum();
+ const auto BaseRegNum = Traits::getBaseReg(RegNum);
(void)BaseRegNum;
assert(Traits::getEncodedGPR(RegNum) ==
Traits::getEncodedGPR(BaseRegNum));
return true;
}
+const RegNumT RegNumT::NoRegister(RegNumT::NoRegisterValue);
+RegNumT::BaseType RegNumT::Limit = 0;
+
bool operator<(const RegWeight &A, const RegWeight &B) {
return A.getWeight() < B.getWeight();
}
return "__" + std::to_string(getIndex());
}
-const Variable *Variable::asType(Type Ty, int32_t NewRegNum) const {
+const Variable *Variable::asType(Type Ty, RegNumT NewRegNum) const {
// Note: This returns a Variable, even if the "this" object is a subclass of
// Variable.
if (!BuildDefs::dump() || getType() == Ty)
Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
Variable(kVariable, Ty, Number);
V->NameIndex = NameIndex;
- V->RegNum = NewRegNum == NoRegister ? RegNum : NewRegNum;
+ V->RegNum = NewRegNum == RegNumT::NoRegister ? RegNum : NewRegNum;
V->StackOffset = StackOffset;
return V;
}
} else if (Func->getTarget()->hasComputedFrame()) {
if (Func->isVerbose(IceV_RegOrigins))
Str << ":";
- int32_t BaseRegisterNumber = getBaseRegNum();
- if (BaseRegisterNumber == NoRegister)
- BaseRegisterNumber = Func->getTarget()->getFrameOrStackReg();
+ const auto BaseRegisterNumber =
+ hasReg() ? getBaseRegNum() : Func->getTarget()->getFrameOrStackReg();
Str << "["
<< Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
int32_t Offset = getStackOffset();
ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {}
};
+/// RegNumT is for holding target-specific register numbers, plus the sentinel
+/// value NoRegister. Its public ctor allows direct use of enum values, such as
+/// RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1). This is to try to
+/// prevent inappropriate assumptions about enum ordering. If needed, the
+/// fromInt() method can be used, such as when a RegNumT is based on a bitvector
+/// index.
+class RegNumT {
+public:
+ using BaseType = uint32_t;
+ RegNumT() = default;
+ RegNumT(const RegNumT &) = default;
+ template <typename AnyEnum>
+ RegNumT(AnyEnum Value,
+ typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0)
+ : Value(Value) {
+ validate(Value);
+ }
+ RegNumT &operator=(const RegNumT &) = default;
+ operator unsigned() const { return Value; }
+ /// Asserts that the register is valid, i.e. not NoRegisterValue. Note that
+ /// the ctor already does the target-specific limit check.
+ void assertIsValid() const { assert(Value != NoRegisterValue); }
+ static RegNumT fromInt(BaseType Value) { return RegNumT(Value); }
+ /// Marks cases that inappropriately add/subtract RegNumT values, and
+ /// therefore need to be fixed because they make assumptions about register
+ /// enum value ordering. TODO(stichnot): Remove fixme() as soon as all
+ /// current uses are fixed/removed.
+ static RegNumT fixme(BaseType Value) { return RegNumT(Value); }
+ /// The target's staticInit() method should call setLimit() to register the
+ /// upper bound of allowable values.
+ static void setLimit(BaseType Value) {
+ // Make sure it's only called once.
+ assert(Limit == 0);
+ assert(Value != 0);
+ Limit = Value;
+ }
+ // Define NoRegisterValue as an enum value so that it can be used as an
+ // argument for the public ctor if desired.
+ enum { NoRegisterValue = std::numeric_limits<BaseType>::max() };
+ const static RegNumT NoRegister /* = NoRegisterValue */;
+
+private:
+ BaseType Value = NoRegisterValue;
+ static BaseType Limit;
+ /// Private ctor called only by fromInt() and fixme().
+ RegNumT(BaseType Value) : Value(Value) { validate(Value); }
+ /// The ctor calls this to validate against the target-supplied limit.
+ static void validate(BaseType Value) {
+ (void)Value;
+ assert(Value == NoRegisterValue || Value < Limit);
+ }
+ /// Disallow operators that inappropriately make assumptions about register
+ /// enum value ordering.
+ bool operator<(const RegNumT &) = delete;
+ bool operator<=(const RegNumT &) = delete;
+ bool operator>(const RegNumT &) = delete;
+ bool operator>=(const RegNumT &) = delete;
+};
+
+/// RegNumBVIter wraps llvm::SmallBitVector so that instead of this pattern:
+///
+/// for (int i = V.find_first(); i != -1; i = V.find_next(i)) {
+/// RegNumT RegNum = RegNumT::fromInt(i);
+/// ...
+/// }
+///
+/// this cleaner pattern can be used:
+///
+/// for (RegNumT RegNum : RegNumBVIter(V)) {
+/// ...
+/// }
+class RegNumBVIter {
+ using T = llvm::SmallBitVector;
+ static constexpr int Sentinel = -1;
+ RegNumBVIter() = delete;
+ RegNumBVIter(const RegNumBVIter &) = delete;
+ RegNumBVIter &operator=(const RegNumBVIter &) = delete;
+
+public:
+ class Iterator {
+ Iterator() = delete;
+ Iterator &operator=(const Iterator &) = delete;
+
+ public:
+ explicit Iterator(const T &V) : V(V), Current(V.find_first()) {}
+ Iterator(const T &V, int Value) : V(V), Current(Value) {}
+ Iterator(const Iterator &) = default;
+ RegNumT operator*() {
+ assert(Current != Sentinel);
+ return RegNumT::fromInt(Current);
+ }
+ Iterator &operator++() {
+ assert(Current != Sentinel);
+ Current = V.find_next(Current);
+ return *this;
+ }
+ bool operator!=(Iterator &Other) { return Current != Other.Current; }
+
+ private:
+ const T &V;
+ int Current;
+ };
+
+ explicit RegNumBVIter(const T &V) : V(V) {}
+ Iterator begin() { return Iterator(V); }
+ Iterator end() { return Iterator(V, Sentinel); }
+
+private:
+ const T &V;
+};
+
/// RegWeight is a wrapper for a uint32_t weight value, with a special value
/// that represents infinite weight, and an addWeight() method that ensures that
/// W+infinity=infinity.
class RegWeight {
public:
+ using BaseType = uint32_t;
RegWeight() = default;
- explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
+ explicit RegWeight(BaseType Weight) : Weight(Weight) {}
RegWeight(const RegWeight &) = default;
RegWeight &operator=(const RegWeight &) = default;
- constexpr static uint32_t Inf = ~0; /// Force regalloc to give a register
- constexpr static uint32_t Zero = 0; /// Force regalloc NOT to give a register
- constexpr static uint32_t Max = Inf - 1; /// Max natural weight.
- void addWeight(uint32_t Delta) {
+ constexpr static BaseType Inf = ~0; /// Force regalloc to give a register
+ constexpr static BaseType Zero = 0; /// Force regalloc NOT to give a register
+ constexpr static BaseType Max = Inf - 1; /// Max natural weight.
+ void addWeight(BaseType Delta) {
if (Delta == Inf)
Weight = Inf;
else if (Weight != Inf)
Weight = Max;
}
void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
- void setWeight(uint32_t Val) { Weight = Val; }
- uint32_t getWeight() const { return Weight; }
+ void setWeight(BaseType Val) { Weight = Val; }
+ BaseType getWeight() const { return Weight; }
private:
- uint32_t Weight = 0;
+ BaseType Weight = 0;
};
Ostream &operator<<(Ostream &Str, const RegWeight &W);
bool operator<(const RegWeight &A, const RegWeight &B);
return "lv$" + getName(Func);
}
- static constexpr int32_t NoRegister = -1;
- bool hasReg() const { return getRegNum() != NoRegister; }
- int32_t getRegNum() const { return RegNum; }
- void setRegNum(int32_t NewRegNum) {
+ bool hasReg() const { return getRegNum() != RegNumT::NoRegister; }
+ RegNumT getRegNum() const { return RegNum; }
+ void setRegNum(RegNumT NewRegNum) {
// Regnum shouldn't be set more than once.
assert(!hasReg() || RegNum == NewRegNum);
RegNum = NewRegNum;
}
- bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
- int32_t getRegNumTmp() const { return RegNumTmp; }
- void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
+ bool hasRegTmp() const { return getRegNumTmp() != RegNumT::NoRegister; }
+ RegNumT getRegNumTmp() const { return RegNumTmp; }
+ void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; }
RegWeight getWeight(const Cfg *Func) const;
bool mustNotHaveReg() const {
return RegRequirement == RR_MustNotHaveRegister;
}
- void setRematerializable(int32_t NewRegNum, int32_t NewOffset) {
+ void setRematerializable(RegNumT NewRegNum, int32_t NewOffset) {
IsRematerializable = true;
setRegNum(NewRegNum);
setStackOffset(NewOffset);
/// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
/// VarsReal. If NewRegNum!=NoRegister, then that register assignment is made
/// instead of copying the existing assignment.
- const Variable *asType(Type Ty, int32_t NewRegNum) const;
+ const Variable *asType(Type Ty, RegNumT NewRegNum) const;
void emit(const Cfg *Func) const override;
using Operand::dump;
void dump(const Cfg *Func, Ostream &Str) const override;
/// Return reg num of base register, if different from stack/frame register.
- virtual int32_t getBaseRegNum() const { return NoRegister; }
+ virtual RegNumT getBaseRegNum() const { return RegNumT::NoRegister; }
static bool classof(const Operand *Operand) {
OperandKind Kind = Operand->getKind();
RegClass RegisterClass;
/// RegNum is the allocated register, or NoRegister if it isn't
/// register-allocated.
- int32_t RegNum = NoRegister;
+ RegNumT RegNum = RegNumT::NoRegister;
/// RegNumTmp is the tentative assignment during register allocation.
- int32_t RegNumTmp = NoRegister;
+ RegNumT RegNumTmp = RegNumT::NoRegister;
/// StackOffset is the canonical location on stack (only if
/// RegNum==NoRegister || IsArgument).
int32_t StackOffset = 0;
return;
Ostream &Str = Func->getContext()->getStrDump();
char buf[30];
- snprintf(buf, llvm::array_lengthof(buf), "%2d", Var->getRegNumTmp());
+ snprintf(buf, llvm::array_lengthof(buf), "%2u",
+ unsigned(Var->getRegNumTmp()));
Str << "R=" << buf << " V=";
Var->dump(Func);
Str << " Range=" << Var->getLiveRange();
int32_t findMinWeightIndex(
const llvm::SmallBitVector &RegMask,
const llvm::SmallVector<RegWeight, LinearScan::REGS_SIZE> &Weights) {
- int32_t MinWeightIndex = RegMask.find_first();
- assert(MinWeightIndex >= 0);
- for (int32_t i = RegMask.find_next(MinWeightIndex); i != -1;
- i = RegMask.find_next(i)) {
- if (Weights[i] < Weights[MinWeightIndex])
+ int MinWeightIndex = -1;
+ for (RegNumT i : RegNumBVIter(RegMask)) {
+ if (MinWeightIndex < 0 || Weights[i] < Weights[MinWeightIndex])
MinWeightIndex = i;
}
+ assert(MinWeightIndex >= 0);
return MinWeightIndex;
}
SizeT NumRegs = Target->getNumRegisters();
RegAliases.resize(NumRegs);
for (SizeT Reg = 0; Reg < NumRegs; ++Reg) {
- RegAliases[Reg] = &Target->getAliasesForRegister(Reg);
+ RegAliases[Reg] = &Target->getAliasesForRegister(RegNumT::fromInt(Reg));
}
switch (Kind) {
if (!Var->hasRegTmp())
continue;
const llvm::SmallBitVector &Aliases = *RegAliases[Var->getRegNumTmp()];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
Iter.RegMask[RegAlias] = false;
}
}
assert(SpillPoint != Insts.end());
assert(FillPoint != Insts.end());
++FillPoint;
- // TODO(stichnot): Randomize instead of find_first().
- int32_t RegNum = Iter.RegMask.find_first();
- assert(RegNum != -1);
+ // TODO(stichnot): Randomize instead of *.begin() which maps to find_first().
+ const RegNumT RegNum = *RegNumBVIter(Iter.RegMask).begin();
Iter.Cur->setRegNumTmp(RegNum);
Variable *Preg = Target->getPhysicalRegister(RegNum, Iter.Cur->getType());
// TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc
// Decrement Item from RegUses[].
assert(Item->hasRegTmp());
const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
--RegUses[RegAlias];
assert(RegUses[RegAlias] >= 0);
}
// Increment Item in RegUses[].
assert(Item->hasRegTmp());
const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
// not appear within the current Variable's live range.
void LinearScan::findRegisterPreference(IterationState &Iter) {
Iter.Prefer = nullptr;
- Iter.PreferReg = Variable::NoRegister;
+ Iter.PreferReg = RegNumT::NoRegister;
Iter.AllowOverlap = false;
if (!FindPreference)
// That register must be one in the RegMask set, e.g. don't try to prefer
// the stack pointer as a result of the stacksave intrinsic.
const llvm::SmallBitVector &Aliases = *RegAliases[SrcVar->getRegNumTmp()];
- const int32_t SrcReg = (Iter.RegMask & Aliases).find_first();
+ const int SrcReg = (Iter.RegMask & Aliases).find_first();
if (SrcReg == -1)
continue;
}
if (Iter.AllowOverlap || Iter.Free[SrcReg]) {
Iter.Prefer = SrcVar;
- Iter.PreferReg = SrcReg;
+ Iter.PreferReg = RegNumT::fromInt(SrcReg);
// Stop looking for a preference after the first valid preference is
// found. One might think that we should look at all instruction
// variables to find the best <Prefer,AllowOverlap> combination, but note
if (!Item->rangeOverlaps(Iter.Cur))
continue;
const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
- // TODO(stichnot): Do this with bitvector ops, not a loop, for efficiency.
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
- // Don't assert(Iter.Free[RegNum]) because in theory (though probably
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
+ // Don't assert(Iter.Free[RegAlias]) because in theory (though probably
// never in practice) there could be two inactive variables that were
// marked with AllowOverlap.
Iter.Free[RegAlias] = false;
continue;
const llvm::SmallBitVector &Aliases =
*RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
Iter.Weights[RegAlias].setWeight(RegWeight::Inf);
Iter.Free[RegAlias] = false;
Iter.FreeUnfiltered[RegAlias] = false;
}
void LinearScan::allocatePrecoloredRegister(Variable *Cur) {
- int32_t RegNum = Cur->getRegNum();
+ const auto RegNum = Cur->getRegNum();
// RegNumTmp should have already been set above.
assert(Cur->getRegNumTmp() == RegNum);
dumpLiveRangeTrace("Precoloring ", Cur);
Active.push_back(Cur);
const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
Iter.Cur->setRegNumTmp(Iter.PreferReg);
dumpLiveRangeTrace("Preferring ", Iter.Cur);
const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
}
void LinearScan::allocateFreeRegister(IterationState &Iter, bool Filtered) {
- const int32_t RegNum =
- Filtered ? Iter.Free.find_first() : Iter.FreeUnfiltered.find_first();
+ const RegNumT RegNum =
+ *RegNumBVIter(Filtered ? Iter.Free : Iter.FreeUnfiltered).begin();
Iter.Cur->setRegNumTmp(RegNum);
if (Filtered)
dumpLiveRangeTrace("Allocating ", Iter.Cur);
else
dumpLiveRangeTrace("Allocating X ", Iter.Cur);
const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
// should we decide to pick any of them, then we would incur that many
// memory accesses.
RegWeight W = Item->getWeight(Func);
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
Iter.Weights[RegAlias].addWeight(W);
}
}
assert(Item->hasRegTmp());
const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
RegWeight W = Item->getWeight(Func);
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
Iter.Weights[RegAlias].addWeight(W);
}
}
for (SizeT I = Active.size(); I > 0; --I) {
const SizeT Index = I - 1;
Variable *Item = Active[Index];
- int32_t RegNum = Item->getRegNumTmp();
+ const auto RegNum = Item->getRegNumTmp();
if (Aliases[RegNum]) {
dumpLiveRangeTrace("Evicting A ", Item);
const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
--RegUses[RegAlias];
assert(RegUses[RegAlias] >= 0);
}
- Item->setRegNumTmp(Variable::NoRegister);
+ Item->setRegNumTmp(RegNumT::NoRegister);
moveItem(Active, Index, Handled);
Evicted.push_back(Item);
}
// instructions.
if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) {
dumpLiveRangeTrace("Evicting I ", Item);
- Item->setRegNumTmp(Variable::NoRegister);
+ Item->setRegNumTmp(RegNumT::NoRegister);
moveItem(Inactive, Index, Handled);
Evicted.push_back(Item);
}
}
// Assign the register to Cur.
- Iter.Cur->setRegNumTmp(MinWeightIndex);
- for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
- RegAlias = Aliases.find_next(RegAlias)) {
+ Iter.Cur->setRegNumTmp(RegNumT::fromInt(MinWeightIndex));
+ for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
const llvm::SmallBitVector &RegMaskFull,
const llvm::SmallBitVector &PreDefinedRegisters, bool Randomized) {
const size_t NumRegisters = RegMaskFull.size();
- llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters);
+ llvm::SmallVector<RegNumT, REGS_SIZE> Permutation(NumRegisters);
if (Randomized) {
// Create a random number generator for regalloc randomization. Merge
// function's sequence and Kind value as the Salt. Because regAlloc() is
// Finish up by setting RegNum = RegNumTmp (or a random permutation thereof)
// for each Variable.
for (Variable *Item : Handled) {
- int32_t RegNum = Item->getRegNumTmp();
- int32_t AssignedRegNum = RegNum;
+ const auto RegNum = Item->getRegNumTmp();
+ auto AssignedRegNum = RegNum;
if (Randomized && Item->hasRegTmp() && !Item->hasReg()) {
AssignedRegNum = Permutation[RegNum];
if (Iter.AllowOverlap) {
const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
for (const Variable *Item : Active) {
- int32_t RegNum = Item->getRegNumTmp();
+ const RegNumT RegNum = Item->getRegNumTmp();
if (Item != Iter.Prefer && Aliases[RegNum] &&
overlapsDefs(Func, Iter.Cur, Item)) {
Iter.AllowOverlap = false;
if (Iter.Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) {
Iter.Free.reset(KillsMask);
Iter.FreeUnfiltered.reset(KillsMask);
- for (int i = KillsMask.find_first(); i != -1;
- i = KillsMask.find_next(i)) {
+ for (RegNumT i : RegNumBVIter(KillsMask)) {
Iter.Weights[i].setWeight(RegWeight::Inf);
if (Iter.PreferReg == i)
Iter.AllowOverlap = false;
// Print info about physical register availability.
if (BuildDefs::dump() && Verbose) {
Ostream &Str = Ctx->getStrDump();
- for (SizeT i = 0; i < Iter.RegMask.size(); ++i) {
- if (Iter.RegMaskUnfiltered[i]) {
- Str << Target->getRegName(i, Iter.Cur->getType())
- << "(U=" << RegUses[i] << ",F=" << Iter.Free[i]
- << ",P=" << Iter.PrecoloredUnhandledMask[i] << ") ";
- }
+ for (RegNumT i : RegNumBVIter(Iter.RegMaskUnfiltered)) {
+ Str << Target->getRegName(i, Iter.Cur->getType()) << "(U=" << RegUses[i]
+ << ",F=" << Iter.Free[i] << ",P=" << Iter.PrecoloredUnhandledMask[i]
+ << ") ";
}
Str << "\n";
}
IterationState() = default;
Variable *Cur = nullptr;
Variable *Prefer = nullptr;
- int32_t PreferReg = Variable::NoRegister;
+ RegNumT PreferReg = RegNumT::NoRegister;
bool AllowOverlap = false;
llvm::SmallBitVector RegMask;
llvm::SmallBitVector RegMaskUnfiltered;
#undef NUM_ALIASES_BITS
} RegTable[Reg_NUM];
-static inline bool isGPRegister(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline void assertValidRegNum(RegNumT RegNum) {
+ (void)RegNum;
+ assert(RegNum != RegNumT::NoRegister);
+}
+
+static inline bool isGPRegister(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].IsGPR;
}
;
}
-static inline GPRRegister getEncodedGPR(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
+ RegNum.assertIsValid();
return GPRRegister(RegTable[RegNum].Encoding);
}
;
}
-static inline bool isGPR(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline bool isGPR(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].IsGPR;
}
-static inline GPRRegister getI64PairFirstGPRNum(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline GPRRegister getI64PairFirstGPRNum(RegNumT RegNum) {
+ RegNum.assertIsValid();
return GPRRegister(RegTable[RegNum].Encoding);
}
-static inline GPRRegister getI64PairSecondGPRNum(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline GPRRegister getI64PairSecondGPRNum(RegNumT RegNum) {
+ RegNum.assertIsValid();
return GPRRegister(RegTable[RegNum].Encoding + 1);
}
-static inline bool isI64RegisterPair(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline bool isI64RegisterPair(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].IsI64Pair;
}
-static inline bool isEncodedSReg(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline bool isEncodedSReg(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].IsFP32;
}
;
}
-static inline SRegister getEncodedSReg(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline SRegister getEncodedSReg(RegNumT RegNum) {
+ RegNum.assertIsValid();
return SRegister(RegTable[RegNum].Encoding);
}
-static inline bool isEncodedDReg(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline bool isEncodedDReg(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].IsFP64;
}
;
}
-static inline DRegister getEncodedDReg(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline DRegister getEncodedDReg(RegNumT RegNum) {
+ RegNum.assertIsValid();
return DRegister(RegTable[RegNum].Encoding);
}
-static inline bool isEncodedQReg(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline bool isEncodedQReg(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].IsVec128;
}
-static inline QRegister getEncodedQReg(int32_t RegNum) {
+static inline QRegister getEncodedQReg(RegNumT RegNum) {
assert(isEncodedQReg(RegNum));
return QRegister(RegTable[RegNum].Encoding);
}
-static inline IceString getRegName(int32_t RegNum) {
- assert(RegNum >= 0);
- assert(RegNum < Reg_NUM);
+static inline IceString getRegName(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegTable[RegNum].Name;
}
// TODO(jvoung): Floating point and vector registers...
// Need to model overlap and difference in encoding too.
-static inline GPRRegister getEncodedGPR(int32_t RegNum) {
- assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
+static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
+ assert(int(Reg_GPR_First) <= int(RegNum));
+ assert(unsigned(RegNum) <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
}
-const char *getRegName(int32_t RegNum);
+const char *getRegName(RegNumT RegNum);
} // end of namespace RegMIPS32
Encoded_Not_X87STReg = -1
};
- static inline X87STRegister getEncodedSTReg(int32_t RegNum) {
- assert(Encoded_X87ST_First <= RegNum);
- assert(RegNum <= Encoded_X87ST_Last);
- return X87STRegister(RegNum);
+ static inline X87STRegister getEncodedSTReg(uint32_t X87RegNum) {
+ assert(int(Encoded_X87ST_First) <= int(X87RegNum));
+ assert(X87RegNum <= Encoded_X87ST_Last);
+ return X87STRegister(X87RegNum);
}
};
namespace {
void printRegisterSet(Ostream &Str, const llvm::SmallBitVector &Bitset,
- std::function<IceString(int32_t)> getRegName,
+ std::function<IceString(RegNumT)> getRegName,
const IceString &LineIndentString) {
constexpr size_t RegistersPerLine = 16;
size_t Count = 0;
- for (int i = Bitset.find_first(); i != -1; i = Bitset.find_next(i)) {
+ for (RegNumT RegNum : RegNumBVIter(Bitset)) {
if (Count == 0) {
Str << LineIndentString;
} else {
if (Count > 0 && Count % RegistersPerLine == 0)
Str << "\n" << LineIndentString;
++Count;
- Str << getRegName(i);
+ Str << getRegName(RegNum);
}
if (Count)
Str << "\n";
void TargetLowering::filterTypeToRegisterSet(
GlobalContext *Ctx, int32_t NumRegs,
llvm::SmallBitVector TypeToRegisterSet[], size_t TypeToRegisterSetSize,
- std::function<IceString(int32_t)> getRegName,
+ std::function<IceString(RegNumT)> getRegName,
std::function<IceString(RegClass)> getRegClassName) {
std::vector<llvm::SmallBitVector> UseSet(TypeToRegisterSetSize,
llvm::SmallBitVector(NumRegs));
std::vector<llvm::SmallBitVector> ExcludeSet(TypeToRegisterSetSize,
llvm::SmallBitVector(NumRegs));
- std::unordered_map<IceString, int32_t> RegNameToIndex;
- for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex)
- RegNameToIndex[getRegName(RegIndex)] = RegIndex;
+ std::unordered_map<IceString, RegNumT> RegNameToIndex;
+ for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex) {
+ const auto RegNum = RegNumT::fromInt(RegIndex);
+ RegNameToIndex[getRegName(RegNum)] = RegNum;
+ }
ClFlags::StringVector BadRegNames;
/// generally used to get very direct access to the register such as in the
/// prolog or epilog or for marking scratch registers as killed by a call. If
/// a Type is not provided, a target-specific default type is used.
- virtual Variable *getPhysicalRegister(SizeT RegNum,
+ virtual Variable *getPhysicalRegister(RegNumT RegNum,
Type Ty = IceType_void) = 0;
/// Returns a printable name for the register.
- virtual IceString getRegName(SizeT RegNum, Type Ty) const = 0;
+ virtual IceString getRegName(RegNumT RegNum, Type Ty) const = 0;
virtual bool hasFramePointer() const { return false; }
virtual void setHasFramePointer() = 0;
- virtual SizeT getStackReg() const = 0;
- virtual SizeT getFrameReg() const = 0;
- virtual SizeT getFrameOrStackReg() const = 0;
+ virtual RegNumT getStackReg() const = 0;
+ virtual RegNumT getFrameReg() const = 0;
+ virtual RegNumT getFrameOrStackReg() const = 0;
virtual size_t typeWidthInBytesOnStack(Type Ty) const = 0;
virtual uint32_t getStackAlignment() const = 0;
virtual void reserveFixedAllocaArea(size_t Size, size_t Align) = 0;
/// command line.
virtual const llvm::SmallBitVector &
getAllRegistersForVariable(const Variable *Var) const = 0;
- virtual const llvm::SmallBitVector &getAliasesForRegister(SizeT) const = 0;
+ virtual const llvm::SmallBitVector &getAliasesForRegister(RegNumT) const = 0;
void regAlloc(RegAllocKind Kind);
virtual void
- makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+ makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const = 0;
filterTypeToRegisterSet(GlobalContext *Ctx, int32_t NumRegs,
llvm::SmallBitVector TypeToRegisterSet[],
size_t TypeToRegisterSetSize,
- std::function<IceString(int32_t)> getRegName,
+ std::function<IceString(RegNumT)> getRegName,
std::function<IceString(RegClass)> getRegClassName);
virtual void lowerAlloca(const InstAlloca *Instr) = 0;
virtual void lowerArithmetic(const InstArithmetic *Instr) = 0;
REGARM32_GPR_TABLE
#undef X
;
-std::array<uint32_t, NumGPRArgs> GPRArgInitializer;
+std::array<RegNumT, NumGPRArgs> GPRArgInitializer;
constexpr SizeT NumI64Args =
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
REGARM32_I64PAIR_TABLE
#undef X
;
-std::array<uint32_t, NumI64Args> I64ArgInitializer;
+std::array<RegNumT, NumI64Args> I64ArgInitializer;
constexpr SizeT NumFP32Args =
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
REGARM32_FP32_TABLE
#undef X
;
-std::array<uint32_t, NumFP32Args> FP32ArgInitializer;
+std::array<RegNumT, NumFP32Args> FP32ArgInitializer;
constexpr SizeT NumFP64Args =
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
REGARM32_FP64_TABLE
#undef X
;
-std::array<uint32_t, NumFP64Args> FP64ArgInitializer;
+std::array<RegNumT, NumFP64Args> FP64ArgInitializer;
constexpr SizeT NumVec128Args =
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
REGARM32_VEC128_TABLE
#undef X
;
-std::array<uint32_t, NumVec128Args> Vec128ArgInitializer;
+std::array<RegNumT, NumVec128Args> Vec128ArgInitializer;
IceString getRegClassName(RegClass C) {
auto ClassNum = static_cast<RegARM32::RegClassARM32>(C);
CPUFeatures(Func->getContext()->getFlags()) {}
void TargetARM32::staticInit(GlobalContext *Ctx) {
-
+ RegNumT::setLimit(RegARM32::Reg_NUM);
// Limit this size (or do all bitsets need to be the same width)???
llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM);
llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM);
if (Entry.CCArg <= 0) {
continue;
}
+ const auto RegNum = RegNumT::fromInt(i);
if (Entry.IsGPR) {
- GPRArgInitializer[Entry.CCArg - 1] = i;
+ GPRArgInitializer[Entry.CCArg - 1] = RegNum;
} else if (Entry.IsI64Pair) {
- I64ArgInitializer[Entry.CCArg - 1] = i;
+ I64ArgInitializer[Entry.CCArg - 1] = RegNum;
} else if (Entry.IsFP32) {
- FP32ArgInitializer[Entry.CCArg - 1] = i;
+ FP32ArgInitializer[Entry.CCArg - 1] = RegNum;
} else if (Entry.IsFP64) {
- FP64ArgInitializer[Entry.CCArg - 1] = i;
+ FP64ArgInitializer[Entry.CCArg - 1] = RegNum;
} else if (Entry.IsVec128) {
- Vec128ArgInitializer[Entry.CCArg - 1] = i;
+ Vec128ArgInitializer[Entry.CCArg - 1] = RegNum;
}
}
TypeToRegisterSet[IceType_void] = InvalidRegisters;
filterTypeToRegisterSet(
Ctx, RegARM32::Reg_NUM, TypeToRegisterSet,
- llvm::array_lengthof(TypeToRegisterSet), [](int32_t RegNum) -> IceString {
+ llvm::array_lengthof(TypeToRegisterSet), [](RegNumT RegNum) -> IceString {
// This function simply removes ", " from the register name.
IceString Name = RegARM32::getRegName(RegNum);
constexpr const char RegSeparator[] = ", ";
if (!Var64->hasReg()) {
continue;
}
- SizeT FirstReg = RegARM32::getI64PairFirstGPRNum(Var->getRegNum());
+ const auto FirstReg =
+ RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Var->getRegNum()));
// This assumes little endian.
Variable *Lo = Var64->getLo();
Variable *Hi = Var64->getHi();
}
Lo->setRegNum(FirstReg);
Lo->setMustHaveReg();
- Hi->setRegNum(FirstReg + 1);
+ Hi->setRegNum(RegNumT::fixme(FirstReg + 1));
Hi->setMustHaveReg();
}
}
uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) {
TargetARM32::CallingConv CC;
- int32_t DummyReg;
+ RegNumT DummyReg;
size_t OutArgsSizeBytes = 0;
for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) {
Operand *Arg = legalizeUndef(Call->getArg(i));
return false;
}
-IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const {
- assert(RegNum < RegARM32::Reg_NUM);
+IceString TargetARM32::getRegName(RegNumT RegNum, Type Ty) const {
(void)Ty;
return RegARM32::getRegName(RegNum);
}
-Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) {
+Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) {
static const Type DefaultType[] = {
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
#undef X
};
- assert(RegNum < RegARM32::Reg_NUM);
if (Ty == IceType_void) {
- assert(RegNum < llvm::array_lengthof(DefaultType));
+ assert(unsigned(RegNum) < llvm::array_lengthof(DefaultType));
Ty = DefaultType[RegNum];
}
if (PhysicalRegisters[Ty].empty())
PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM);
- assert(RegNum < PhysicalRegisters[Ty].size());
+ assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
Variable *Reg = PhysicalRegisters[Ty][RegNum];
if (Reg == nullptr) {
Reg = Func->makeVariable(Ty);
}
assert(!Var->isRematerializable());
int32_t Offset = Var->getStackOffset();
- int32_t BaseRegNum = Var->getBaseRegNum();
- if (BaseRegNum == Variable::NoRegister) {
+ auto BaseRegNum = Var->getBaseRegNum();
+ if (BaseRegNum == RegNumT::NoRegister) {
BaseRegNum = getFrameOrStackReg();
}
const Type VarTy = Var->getType();
FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()),
Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {}
-bool TargetARM32::CallingConv::argInGPR(Type Ty, int32_t *Reg) {
- CfgVector<SizeT> *Source;
+bool TargetARM32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
+ CfgVector<RegNumT> *Source;
switch (Ty) {
default: {
// we remove all of its aliases from the pool of available GPRs. This has the
// effect of computing the "closure" on the GPR registers.
void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases(
- CfgVector<SizeT> *Regs) {
+ CfgVector<RegNumT> *Regs) {
while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
GPRegsUsed |= RegisterAliases[Regs->back()];
Regs->pop_back();
}
}
-bool TargetARM32::CallingConv::argInVFP(Type Ty, int32_t *Reg) {
- CfgVector<SizeT> *Source;
+bool TargetARM32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) {
+ CfgVector<RegNumT> *Source;
switch (Ty) {
default: {
// Arguments in VFP registers are not packed, so we don't mark the popped
// registers' aliases as unavailable.
void TargetARM32::CallingConv::discardUnavailableVFPRegs(
- CfgVector<SizeT> *Regs) {
+ CfgVector<RegNumT> *Regs) {
while (!Regs->empty() && VFPRegsUsed[Regs->back()]) {
Regs->pop_back();
}
for (SizeT I = 0, E = Args.size(); I < E; ++I) {
Variable *Arg = Args[I];
Type Ty = Arg->getType();
- int RegNum;
+ RegNumT RegNum;
if (isScalarIntegerType(Ty)) {
if (!CC.argInGPR(Ty, &RegNum)) {
continue;
auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg);
RegisterArg64->initHiLo(Func);
RegisterArg64->getLo()->setRegNum(
- RegARM32::getI64PairFirstGPRNum(RegNum));
+ RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(RegNum)));
RegisterArg64->getHi()->setRegNum(
- RegARM32::getI64PairSecondGPRNum(RegNum));
+ RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(RegNum)));
} break;
}
Context.insert<InstAssign>(Arg, RegisterArg);
continue;
}
++NumCallee;
- Variable *PhysicalRegister = getPhysicalRegister(Reg);
+ Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg));
PreservedRegsSizeBytes +=
typeWidthInBytesOnStack(PhysicalRegister->getType());
PreservedRegsInClass->push_back(PhysicalRegister);
size_t InArgsSizeBytes = 0;
TargetARM32::CallingConv CC;
for (Variable *Arg : Args) {
- int32_t DummyReg;
+ RegNumT DummyReg;
const Type Ty = Arg->getType();
// Skip arguments passed in registers.
}
Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister(
- Variable *Base, int32_t Offset, int32_t ScratchRegNum) {
+ Variable *Base, int32_t Offset, RegNumT ScratchRegNum) {
// Legalize will likely need a movw/movt combination, but if the top bits are
// all 0 from negating the offset and subtracting, we could use that instead.
const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0;
if (ScratchRegNum == Target->getReservedTmpReg()) {
const bool BaseIsStackOrFramePtr =
- Base->getRegNum() == static_cast<int32_t>(Target->getFrameOrStackReg());
+ Base->getRegNum() == Target->getFrameOrStackReg();
// There is currently no code path that would trigger this assertion, so we
// leave this assertion here in case it is ever violated. This is not a
// fatal error (thus the use of assert() and not llvm::report_fatal_error)
// ExtraOffset is only needed for frame-pointer based frames as we have
// to account for spill storage.
- const int32_t ExtraOffset =
- (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg())
- ? Target->getFrameFixedAllocaOffset()
- : 0;
+ const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg())
+ ? Target->getFrameFixedAllocaOffset()
+ : 0;
const int32_t Offset = Var->getStackOffset() + ExtraOffset;
Variable *Base = Target->getPhysicalRegister(Var->getRegNum());
Variable *Base = Mem->getBase();
int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue();
if (Base->isRematerializable()) {
- const int32_t ExtraOffset =
- (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg())
- ? Target->getFrameFixedAllocaOffset()
- : 0;
+ const int32_t ExtraOffset = (Base->getRegNum() == Target->getFrameReg())
+ ? Target->getFrameFixedAllocaOffset()
+ : 0;
Offset += Base->getStackOffset() + ExtraOffset;
Base = Target->getPhysicalRegister(Base->getRegNum());
assert(!Base->isRematerializable());
RegSetMask Exclude) const {
llvm::SmallBitVector Registers(RegARM32::Reg_NUM);
- for (int32_t i = 0; i < RegARM32::Reg_NUM; ++i) {
+ for (uint32_t i = 0; i < RegARM32::Reg_NUM; ++i) {
const auto &Entry = RegARM32::RegTable[i];
if (Entry.Scratch && (Include & RegSet_CallerSave))
Registers[i] = true;
// Assign arguments to registers and stack. Also reserve stack.
TargetARM32::CallingConv CC;
// Pair of Arg Operand -> GPR number assignments.
- llvm::SmallVector<std::pair<Operand *, int32_t>, NumGPRArgs> GPRArgs;
- llvm::SmallVector<std::pair<Operand *, int32_t>, NumFP32Args> FPArgs;
+ llvm::SmallVector<std::pair<Operand *, RegNumT>, NumGPRArgs> GPRArgs;
+ llvm::SmallVector<std::pair<Operand *, RegNumT>, NumFP32Args> FPArgs;
// Pair of Arg Operand -> stack offset.
llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs;
size_t ParameterAreaSizeBytes = 0;
Operand *Arg = legalizeUndef(Instr->getArg(i));
const Type Ty = Arg->getType();
bool InReg = false;
- int32_t Reg;
+ RegNumT Reg;
if (isScalarIntegerType(Ty)) {
InReg = CC.argInGPR(Ty, &Reg);
} else {
if (Ty == IceType_i64) {
Operand *Lo = loOperand(Arg);
Operand *Hi = hiOperand(Arg);
- GPRArgs.push_back(
- std::make_pair(Lo, RegARM32::getI64PairFirstGPRNum(Reg)));
- GPRArgs.push_back(
- std::make_pair(Hi, RegARM32::getI64PairSecondGPRNum(Reg)));
+ GPRArgs.push_back(std::make_pair(
+ Lo, RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Reg))));
+ GPRArgs.push_back(std::make_pair(
+ Hi, RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(Reg))));
} else if (isScalarIntegerType(Ty)) {
GPRArgs.push_back(std::make_pair(Arg, Reg));
} else {
PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func);
}
-Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
+Variable *TargetARM32::makeVectorOfZeros(Type Ty, RegNumT RegNum) {
Variable *Reg = makeReg(Ty, RegNum);
Context.insert<InstFakeDef>(Reg);
assert(isVectorType(Ty));
// Helper for legalize() to emit the right code to lower an operand to a
// register of the appropriate type.
-Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) {
+Variable *TargetARM32::copyToReg(Operand *Src, RegNumT RegNum) {
Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum);
if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
// TODO(jpp): remove unneeded else clauses in legalize.
Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
- int32_t RegNum) {
+ RegNumT RegNum) {
Type Ty = From->getType();
// Assert that a physical register is allowed. To date, all calls to
// legalize() allow a physical register. Legal_Flex converts registers to the
assert(Allowed & Legal_Reg);
// Copied ipsis literis from TargetX86Base<Machine>.
- if (RegNum == Variable::NoRegister) {
+ if (RegNum == RegNumT::NoRegister) {
if (Variable *Subst = getContext().availabilityGet(From)) {
// At this point we know there is a potential substitution available.
if (!Subst->isRematerializable() && Subst->mustHaveReg() &&
// register, or
// RegNum is required and Var->getRegNum() doesn't match.
if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
- (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+ (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
From = copyToReg(From, RegNum);
}
return From;
}
/// Provide a trivial wrapper to legalize() for this common usage.
-Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) {
+Variable *TargetARM32::legalizeToReg(Operand *From, RegNumT RegNum) {
return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
}
/// Legalize undef values to concrete values.
-Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) {
+Operand *TargetARM32::legalizeUndef(Operand *From, RegNumT RegNum) {
Type Ty = From->getType();
if (llvm::isa<ConstantUndef>(From)) {
// Lower undefs to zero. Another option is to lower undefs to an
return Reg;
}
-Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) {
+Variable *TargetARM32::makeReg(Type Type, RegNumT RegNum) {
// There aren't any 64-bit integer registers for ARM32.
assert(Type != IceType_i64);
- assert(AllowTemporaryWithNoReg || RegNum != Variable::NoRegister);
+ assert(AllowTemporaryWithNoReg || RegNum != RegNumT::NoRegister);
Variable *Reg = Func->makeVariable(Type);
- if (RegNum == Variable::NoRegister)
+ if (RegNum == RegNumT::NoRegister)
Reg->setMustHaveReg();
else
Reg->setRegNum(RegNum);
}
void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align,
- int32_t TmpRegNum) {
+ RegNumT TmpRegNum) {
assert(llvm::isPowerOf2_32(Align));
uint32_t RotateAmt;
uint32_t Immed_8;
}
void TargetARM32::makeRandomRegisterPermutation(
- llvm::SmallVectorImpl<int32_t> &Permutation,
+ llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
(void)Permutation;
(void)ExcludeRegisters;
bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
- Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
- IceString getRegName(SizeT RegNum, Type Ty) const override;
+ Variable *getPhysicalRegister(RegNumT RegNum,
+ Type Ty = IceType_void) override;
+ IceString getRegName(RegNumT RegNum, Type Ty) const override;
llvm::SmallBitVector getRegisterSet(RegSetMask Include,
RegSetMask Exclude) const override;
const llvm::SmallBitVector &
assert((RegARM32::RegClassARM32)RC < RegARM32::RCARM32_NUM);
return TypeToRegisterSetUnfiltered[RC];
}
- const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+ const llvm::SmallBitVector &
+ getAliasesForRegister(RegNumT Reg) const override {
return RegisterAliases[Reg];
}
bool hasFramePointer() const override { return UsesFramePointer; }
void setHasFramePointer() override { UsesFramePointer = true; }
- SizeT getStackReg() const override { return RegARM32::Reg_sp; }
- SizeT getFrameReg() const override { return RegARM32::Reg_fp; }
- SizeT getFrameOrStackReg() const override {
+ RegNumT getStackReg() const override { return RegARM32::Reg_sp; }
+ RegNumT getFrameReg() const override { return RegARM32::Reg_fp; }
+ RegNumT getFrameOrStackReg() const override {
return UsesFramePointer ? getFrameReg() : getStackReg();
}
- int32_t getReservedTmpReg() const { return RegARM32::Reg_ip; }
+ RegNumT getReservedTmpReg() const { return RegARM32::Reg_ip; }
size_t typeWidthInBytesOnStack(Type Ty) const override {
// Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
};
using LegalMask = uint32_t;
- Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
+ Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
- int32_t RegNum = Variable::NoRegister);
- Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
+ RegNumT RegNum = RegNumT::NoRegister);
+ Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
assert(ShAmtImm < 32);
OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Variable64On32 *makeI64RegPair();
- Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
+ Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
static Type stackSlotType();
- Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
+ Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
void alignRegisterPow2(Variable *Reg, uint32_t Align,
- int32_t TmpRegNum = Variable::NoRegister);
+ RegNumT TmpRegNum = RegNumT::NoRegister);
/// Returns a vector in a register with the given constant entries.
- Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
+ Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
void
- makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+ makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
private:
/// Creates a new Base register centered around [Base, +/- Offset].
Variable *newBaseRegister(Variable *Base, int32_t Offset,
- int32_t ScratchRegNum);
+ RegNumT ScratchRegNum);
/// Creates a new, legal OperandARM32Mem for accessing Base + Offset.
/// The returned mem operand is a legal operand for accessing memory that is
/// type, and false otherwise. If it returns true, Reg is set to the
/// appropriate register number. Note that, when Ty == IceType_i64, Reg will
/// be an I64 register pair.
- bool argInGPR(Type Ty, int32_t *Reg);
+ bool argInGPR(Type Ty, RegNumT *Reg);
/// argInVFP is to floating-point/vector types what argInGPR is for integer
/// types.
- bool argInVFP(Type Ty, int32_t *Reg);
+ bool argInVFP(Type Ty, RegNumT *Reg);
private:
- void discardUnavailableGPRsAndTheirAliases(CfgVector<SizeT> *Regs);
+ void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
llvm::SmallBitVector GPRegsUsed;
- CfgVector<SizeT> GPRArgs;
- CfgVector<SizeT> I64Args;
+ CfgVector<RegNumT> GPRArgs;
+ CfgVector<RegNumT> I64Args;
- void discardUnavailableVFPRegs(CfgVector<SizeT> *Regs);
+ void discardUnavailableVFPRegs(CfgVector<RegNumT> *Regs);
llvm::SmallBitVector VFPRegsUsed;
- CfgVector<SizeT> FP32Args;
- CfgVector<SizeT> FP64Args;
- CfgVector<SizeT> Vec128Args;
+ CfgVector<RegNumT> FP32Args;
+ CfgVector<RegNumT> FP64Args;
+ CfgVector<RegNumT> Vec128Args;
};
private:
void TargetMIPS32::staticInit(GlobalContext *Ctx) {
(void)Ctx;
+ RegNumT::setLimit(RegMIPS32::Reg_NUM);
llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM);
llvm::SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM);
llvm::SmallBitVector Float32Registers(RegMIPS32::Reg_NUM);
} // end of anonymous namespace
-const char *RegMIPS32::getRegName(int32_t RegNum) {
- assert(RegNum < RegMIPS32::Reg_NUM);
+const char *RegMIPS32::getRegName(RegNumT RegNum) {
+ RegNum.assertIsValid();
return RegNames[RegNum];
}
-IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const {
+IceString TargetMIPS32::getRegName(RegNumT RegNum, Type Ty) const {
(void)Ty;
return RegMIPS32::getRegName(RegNum);
}
-Variable *TargetMIPS32::getPhysicalRegister(SizeT RegNum, Type Ty) {
+Variable *TargetMIPS32::getPhysicalRegister(RegNumT RegNum, Type Ty) {
if (Ty == IceType_void)
Ty = IceType_i32;
if (PhysicalRegisters[Ty].empty())
PhysicalRegisters[Ty].resize(RegMIPS32::Reg_NUM);
- assert(RegNum < PhysicalRegisters[Ty].size());
+ RegNum.assertIsValid();
Variable *Reg = PhysicalRegisters[Ty][RegNum];
if (Reg == nullptr) {
Reg = Func->makeVariable(Ty);
}
/// Provide a trivial wrapper to legalize() for this common usage.
-Variable *TargetMIPS32::legalizeToReg(Operand *From, int32_t RegNum) {
+Variable *TargetMIPS32::legalizeToReg(Operand *From, RegNumT RegNum) {
return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
}
/// Legalize undef values to concrete values.
-Operand *TargetMIPS32::legalizeUndef(Operand *From, int32_t RegNum) {
+Operand *TargetMIPS32::legalizeUndef(Operand *From, RegNumT RegNum) {
(void)RegNum;
Type Ty = From->getType();
if (llvm::isa<ConstantUndef>(From)) {
return From;
}
-Variable *TargetMIPS32::makeReg(Type Type, int32_t RegNum) {
+Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) {
// There aren't any 64-bit integer registers for Mips32.
assert(Type != IceType_i64);
Variable *Reg = Func->makeVariable(Type);
- if (RegNum == Variable::NoRegister)
+ if (RegNum == RegNumT::NoRegister)
Reg->setMustHaveReg();
else
Reg->setRegNum(RegNum);
if (Ty == IceType_i64) {
if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
continue;
- int32_t RegLo = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
- int32_t RegHi = RegLo + 1;
+ auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed);
+ auto RegHi = RegNumT::fixme(RegLo + 1);
++NumGPRRegsUsed;
// Always start i64 registers at an even register, so this may end
// up padding away a register.
if (RegLo % 2 != 0) {
- ++RegLo;
+ RegLo = RegNumT::fixme(RegLo + 1);
++NumGPRRegsUsed;
}
// If this leaves us without room to consume another register,
// leave any previously speculatively consumed registers as consumed.
if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
continue;
- // RegHi = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+ // RegHi = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed);
++NumGPRRegsUsed;
Variable *RegisterArg = Func->makeVariable(Ty);
auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg);
assert(Ty == IceType_i32);
if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
continue;
- int32_t RegNum = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+ const auto RegNum = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed);
++NumGPRRegsUsed;
Variable *RegisterArg = Func->makeVariable(Ty);
if (BuildDefs::dump()) {
}
void TargetMIPS32::makeRandomRegisterPermutation(
- llvm::SmallVectorImpl<int32_t> &Permutation,
+ llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
(void)Permutation;
(void)ExcludeRegisters;
// Helper for legalize() to emit the right code to lower an operand to a
// register of the appropriate type.
-Variable *TargetMIPS32::copyToReg(Operand *Src, int32_t RegNum) {
+Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) {
Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum);
if (isVectorType(Ty) || isFloatingType(Ty)) {
}
Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
- int32_t RegNum) {
+ RegNumT RegNum) {
Type Ty = From->getType();
// Assert that a physical register is allowed. To date, all calls
// to legalize() allow a physical register. Legal_Flex converts
// Also try the inverse and use MVN if possible.
// Do a movw/movt to a register.
Variable *Reg;
- if (RegNum == Variable::NoRegister)
+ if (RegNum == RegNumT::NoRegister)
Reg = makeReg(Ty, RegNum);
else
Reg = getPhysicalRegister(RegNum);
// register, or
// RegNum is required and Var->getRegNum() doesn't match.
if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
- (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+ (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
From = copyToReg(From, RegNum);
}
return From;
bool doBranchOpt(Inst *Instr, const CfgNode *NextNode) override;
SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
- Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
- IceString getRegName(SizeT RegNum, Type Ty) const override;
+ Variable *getPhysicalRegister(RegNumT RegNum,
+ Type Ty = IceType_void) override;
+ IceString getRegName(RegNumT RegNum, Type Ty) const override;
llvm::SmallBitVector getRegisterSet(RegSetMask Include,
RegSetMask Exclude) const override;
const llvm::SmallBitVector &
assert(RC < RC_Target);
return TypeToRegisterSetUnfiltered[RC];
}
- const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+ const llvm::SmallBitVector &
+ getAliasesForRegister(RegNumT Reg) const override {
return RegisterAliases[Reg];
}
bool hasFramePointer() const override { return UsesFramePointer; }
void setHasFramePointer() override { UsesFramePointer = true; }
- SizeT getStackReg() const override { return RegMIPS32::Reg_SP; }
- SizeT getFrameReg() const override { return RegMIPS32::Reg_FP; }
- SizeT getFrameOrStackReg() const override {
+ RegNumT getStackReg() const override { return RegMIPS32::Reg_SP; }
+ RegNumT getFrameReg() const override { return RegMIPS32::Reg_FP; }
+ RegNumT getFrameOrStackReg() const override {
return UsesFramePointer ? getFrameReg() : getStackReg();
}
size_t typeWidthInBytesOnStack(Type Ty) const override {
};
typedef uint32_t LegalMask;
Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
- int32_t RegNum = Variable::NoRegister);
+ RegNumT RegNum = RegNumT::NoRegister);
- Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
+ Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
- Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
+ Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
- Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
+ Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
static Type stackSlotType();
- Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
+ Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
void addProlog(CfgNode *Node) override;
void addEpilog(CfgNode *Node) override;
Operand *loOperand(Operand *Operand);
Operand *hiOperand(Operand *Operand);
- Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
+ Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
protected:
explicit TargetMIPS32(Cfg *Func);
void randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) override;
void
- makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+ makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
using Cond = ::Ice::CondX86;
using RegisterSet = ::Ice::RegX8632;
- static constexpr SizeT StackPtr = RegX8632::Reg_esp;
- static constexpr SizeT FramePtr = RegX8632::Reg_ebp;
+ static constexpr RegisterSet::AllRegisters StackPtr = RegX8632::Reg_esp;
+ static constexpr RegisterSet::AllRegisters FramePtr = RegX8632::Reg_ebp;
static constexpr GPRRegister Encoded_Reg_Accumulator =
RegX8632::Encoded_Reg_eax;
static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
static const char *TargetName;
static constexpr Type WordType = IceType_i32;
- static IceString getRegName(int32_t RegNum) {
+ static IceString getRegName(RegNumT RegNum) {
static const char *const RegNames[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
REGX8632_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
return RegNames[RegNum];
}
- static GPRRegister getEncodedGPR(int32_t RegNum) {
+ static GPRRegister getEncodedGPR(RegNumT RegNum) {
static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
REGX8632_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
return GPRRegs[RegNum];
}
- static ByteRegister getEncodedByteReg(int32_t RegNum) {
+ static ByteRegister getEncodedByteReg(RegNumT RegNum) {
static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
REGX8632_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
return ByteRegs[RegNum];
}
- static XmmRegister getEncodedXmm(int32_t RegNum) {
+ static XmmRegister getEncodedXmm(RegNumT RegNum) {
static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
REGX8632_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
return XmmRegs[RegNum];
}
- static uint32_t getEncoding(int32_t RegNum) {
+ static uint32_t getEncoding(RegNumT RegNum) {
static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
REGX8632_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
return Encoding[RegNum];
}
- static int32_t getBaseReg(int32_t RegNum) {
- static const int32_t BaseRegs[RegisterSet::Reg_NUM] = {
+ static RegNumT getBaseReg(RegNumT RegNum) {
+ static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
isTrunc8Rcvr, isAhRcvr, aliases) \
REGX8632_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
return BaseRegs[RegNum];
}
private:
- static int32_t getFirstGprForType(Type Ty) {
+ static RegisterSet::AllRegisters getFirstGprForType(Type Ty) {
switch (Ty) {
default:
llvm_unreachable("Invalid type for GPR.");
public:
// Return a register in RegNum's alias set that is suitable for Ty.
- static int32_t getGprForType(Type Ty, int32_t RegNum) {
- assert(RegNum != Variable::NoRegister);
+ static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
+ assert(RegNum != RegNumT::NoRegister);
if (!isScalarIntegerType(Ty)) {
return RegNum;
return RegNum;
}
- const int32_t FirstGprForType = getFirstGprForType(Ty);
+ const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty);
switch (RegNum) {
default:
return RegisterSet::val; \
assert((is32) || (is16) || (is8) || \
getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp); \
- constexpr int32_t FirstGprWithRegNumSize = \
+ constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize = \
(((is32) || RegisterSet::val == RegisterSet::Reg_esp) \
? RegisterSet::Reg_eax \
: (((is16) || RegisterSet::val == RegisterSet::Reg_sp) \
? RegisterSet::Reg_ax \
: RegisterSet::Reg_al)); \
- const int32_t NewRegNum = \
- RegNum - FirstGprWithRegNumSize + FirstGprForType; \
+ const RegNumT NewRegNum = \
+ RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType); \
assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \
"Error involving " #val); \
return NewRegNum; \
static void
makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
- llvm::SmallVectorImpl<int32_t> &Permutation,
+ llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) {
// TODO(stichnot): Declaring Permutation this way loses type/size
// class. For x86-32, this would comprise the 8 XMM registers. This is for
// performance, not correctness.
static const unsigned MaxEquivalenceClassSize = 8;
- using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>;
+ using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
EquivalenceClassMap EquivalenceClasses;
SizeT NumShuffled = 0, NumPreserved = 0;
Str << "{";
const RegisterList &List = I.second;
bool First = true;
- for (int32_t Register : List) {
+ for (RegNumT Register : List) {
if (!First)
Str << " ";
First = false;
}
}
- static int32_t getRaxOrDie() {
+ static RegNumT getRaxOrDie() {
llvm::report_fatal_error("no rax in non-64-bit mode.");
}
- static int32_t getRdxOrDie() {
+ static RegNumT getRdxOrDie() {
llvm::report_fatal_error("no rdx in non-64-bit mode.");
}
/// Whether scalar floating point arguments are passed in XMM registers
static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false;
/// Get the register for a given argument slot in the XMM registers.
- static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
+ static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
// TODO(sehr): Change to use the CCArg technique used in ARM32.
static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
"Inconsistency between XMM register numbers and ordinals");
if (ArgNum >= X86_MAX_XMM_ARGS) {
- return Variable::NoRegister;
+ return RegNumT::NoRegister;
}
- return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
+ return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
}
/// Get the register for a given argument slot in the GPRs.
- static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+ static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
assert(Ty == IceType_i64 || Ty == IceType_i32);
(void)Ty;
(void)ArgNum;
- return Variable::NoRegister;
+ return RegNumT::NoRegister;
}
/// The number of bits in a byte
return false;
}
- const int32_t RegNum = Var->getRegNum();
+ const auto RegNum = Var->getRegNum();
if ((RegNum == Traits::RegisterSet::Reg_rsp) ||
(RegNum == Traits::RegisterSet::Reg_rbp)) {
return true;
}
}
- int32_t RegNum = Variable::NoRegister;
- int32_t RegNum32 = Variable::NoRegister;
+ auto RegNum = RegNumT::NoRegister;
+ auto RegNum32 = RegNumT::NoRegister;
if (T != nullptr) {
if (T->hasReg()) {
RegNum = Traits::getGprForType(IceType_i64, T->getRegNum());
using Cond = ::Ice::CondX8664;
using RegisterSet = ::Ice::RegX8664;
- static constexpr SizeT StackPtr = RegX8664::Reg_rsp;
- static constexpr SizeT FramePtr = RegX8664::Reg_rbp;
+ static constexpr RegisterSet::AllRegisters StackPtr = RegX8664::Reg_rsp;
+ static constexpr RegisterSet::AllRegisters FramePtr = RegX8664::Reg_rbp;
static constexpr GPRRegister Encoded_Reg_Accumulator =
RegX8664::Encoded_Reg_eax;
static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx;
static const char *TargetName;
static constexpr Type WordType = IceType_i64;
- static IceString getRegName(int32_t RegNum) {
+ static IceString getRegName(RegNumT RegNum) {
static const char *const RegNames[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
REGX8664_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
return RegNames[RegNum];
}
- static GPRRegister getEncodedGPR(int32_t RegNum) {
+ static GPRRegister getEncodedGPR(RegNumT RegNum) {
static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
REGX8664_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
return GPRRegs[RegNum];
}
- static ByteRegister getEncodedByteReg(int32_t RegNum) {
+ static ByteRegister getEncodedByteReg(RegNumT RegNum) {
static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
REGX8664_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
return ByteRegs[RegNum];
}
- static XmmRegister getEncodedXmm(int32_t RegNum) {
+ static XmmRegister getEncodedXmm(RegNumT RegNum) {
static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
REGX8664_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
return XmmRegs[RegNum];
}
- static uint32_t getEncoding(int32_t RegNum) {
+ static uint32_t getEncoding(RegNumT RegNum) {
static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
REGX8664_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
return Encoding[RegNum];
}
- static inline int32_t getBaseReg(int32_t RegNum) {
- static const int32_t BaseRegs[RegisterSet::Reg_NUM] = {
+ static inline RegNumT getBaseReg(RegNumT RegNum) {
+ static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
- encode,
+ RegisterSet::base,
REGX8664_TABLE
#undef X
};
- assert(RegNum >= 0);
- assert(RegNum < RegisterSet::Reg_NUM);
+ RegNum.assertIsValid();
return BaseRegs[RegNum];
}
private:
- static int32_t getFirstGprForType(Type Ty) {
+ static RegNumT getFirstGprForType(Type Ty) {
switch (Ty) {
default:
llvm_unreachable("Invalid type for GPR.");
}
public:
- static int32_t getGprForType(Type Ty, int32_t RegNum) {
- assert(RegNum != Variable::NoRegister);
+ static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
+ assert(RegNum != RegNumT::NoRegister);
if (!isScalarIntegerType(Ty)) {
return RegNum;
assert(RegNum != RegisterSet::Reg_ch);
assert(RegNum != RegisterSet::Reg_dh);
- const int32_t FirstGprForType = getFirstGprForType(Ty);
+ const RegNumT FirstGprForType = getFirstGprForType(Ty);
switch (RegNum) {
default:
return RegisterSet::val; \
assert((is64) || (is32) || (is16) || (is8) || \
getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp); \
- constexpr int32_t FirstGprWithRegNumSize = \
+ constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize = \
((is64) || RegisterSet::val == RegisterSet::Reg_rsp) \
? RegisterSet::Reg_rax \
: (((is32) || RegisterSet::val == RegisterSet::Reg_esp) \
: (((is16) || RegisterSet::val == RegisterSet::Reg_sp) \
? RegisterSet::Reg_ax \
: RegisterSet::Reg_al)); \
- const int32_t NewRegNum = \
- RegNum - FirstGprWithRegNumSize + FirstGprForType; \
+ const auto NewRegNum = \
+ RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType); \
assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \
"Error involving " #val); \
return NewRegNum; \
static void
makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
- llvm::SmallVectorImpl<int32_t> &Permutation,
+ llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) {
// TODO(stichnot): Declaring Permutation this way loses type/size
// class. For x86-64, this would comprise the 16 XMM registers. This is
// for performance, not correctness.
static const unsigned MaxEquivalenceClassSize = 8;
- using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>;
+ using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
EquivalenceClassMap EquivalenceClasses;
SizeT NumShuffled = 0, NumPreserved = 0;
Str << "{";
const RegisterList &List = I.second;
bool First = true;
- for (int32_t Register : List) {
+ for (RegNumT Register : List) {
if (!First)
Str << " ";
First = false;
}
}
- static int32_t getRaxOrDie() { return RegisterSet::Reg_rax; }
+ static RegNumT getRaxOrDie() { return RegisterSet::Reg_rax; }
- static int32_t getRdxOrDie() { return RegisterSet::Reg_rdx; }
+ static RegNumT getRdxOrDie() { return RegisterSet::Reg_rdx; }
// x86-64 calling convention:
//
/// Whether scalar floating point arguments are passed in XMM registers
static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true;
/// Get the register for a given argument slot in the XMM registers.
- static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
+ static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
// TODO(sehr): Change to use the CCArg technique used in ARM32.
static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
"Inconsistency between XMM register numbers and ordinals");
if (ArgNum >= X86_MAX_XMM_ARGS) {
- return Variable::NoRegister;
+ return RegNumT::NoRegister;
}
- return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
+ return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
}
/// Get the register for a given argument slot in the GPRs.
- static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+ static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
if (ArgNum >= X86_MAX_GPR_ARGS) {
- return Variable::NoRegister;
+ return RegNumT::NoRegister;
}
static const RegisterSet::AllRegisters GprForArgNum[] = {
RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
"Mismatch between MAX_GPR_ARGS and GprForArgNum.");
assert(Ty == IceType_i64 || Ty == IceType_i32);
- return static_cast<int32_t>(getGprForType(Ty, GprForArgNum[ArgNum]));
+ return getGprForType(Ty, GprForArgNum[ArgNum]);
}
/// The number of bits in a byte
SizeT getNumRegisters() const override {
return Traits::RegisterSet::Reg_NUM;
}
- Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
- IceString getRegName(SizeT RegNum, Type Ty) const override;
+ Variable *getPhysicalRegister(RegNumT RegNum,
+ Type Ty = IceType_void) override;
+ IceString getRegName(RegNumT RegNum, Type Ty) const override;
static IceString getRegClassName(RegClass C) {
auto ClassNum = static_cast<RegClassX86>(C);
assert(ClassNum < RCX86_NUM);
return TypeToRegisterSetUnfiltered[RC];
}
- const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
- assert(Reg < Traits::RegisterSet::Reg_NUM);
+ const llvm::SmallBitVector &
+ getAliasesForRegister(RegNumT Reg) const override {
+ Reg.assertIsValid();
return RegisterAliases[Reg];
}
bool hasFramePointer() const override { return IsEbpBasedFrame; }
void setHasFramePointer() override { IsEbpBasedFrame = true; }
- SizeT getStackReg() const override { return Traits::StackPtr; }
- SizeT getFrameReg() const override { return Traits::FramePtr; }
- SizeT getFrameOrStackReg() const override {
+ RegNumT getStackReg() const override { return Traits::StackPtr; }
+ RegNumT getFrameReg() const override { return Traits::FramePtr; }
+ RegNumT getFrameOrStackReg() const override {
return IsEbpBasedFrame ? getFrameReg() : getStackReg();
}
size_t typeWidthInBytesOnStack(Type Ty) const override {
X86Address stackVarToAsmOperand(const Variable *Var) const;
InstructionSetEnum getInstructionSet() const { return InstructionSet; }
- Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
+ Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
protected:
const bool NeedSandboxing;
};
using LegalMask = uint32_t;
Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
- int32_t RegNum = Variable::NoRegister);
- Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
+ RegNumT RegNum = RegNumT::NoRegister);
+ Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
/// Legalize the first source operand for use in the cmp instruction.
Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
/// Turn a pointer operand into a memory operand that can be used by a real
X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
bool DoLegalize = true);
- Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
+ Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
static Type stackSlotType();
static constexpr uint32_t NoSizeLimit = 0;
static Type firstTypeThatFitsSize(uint32_t Size,
uint32_t MaxSize = NoSizeLimit);
- Variable *copyToReg8(Operand *Src, int32_t RegNum = Variable::NoRegister);
- Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
+ Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
+ Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
/// Returns a register containing all zeros, without affecting the FLAGS
/// register, using the best instruction for the type.
- Variable *makeZeroedRegister(Type Ty, int32_t RegNum = Variable::NoRegister);
+ Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
/// \name Returns a vector in a register with the given constant entries.
/// @{
- Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
- Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister);
+ Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+ Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
Variable *makeVectorOfMinusOnes(Type Ty,
- int32_t RegNum = Variable::NoRegister);
+ RegNumT RegNum = RegNumT::NoRegister);
Variable *makeVectorOfHighOrderBits(Type Ty,
- int32_t RegNum = Variable::NoRegister);
- Variable *makeVectorOfFabsMask(Type Ty,
- int32_t RegNum = Variable::NoRegister);
+ RegNumT RegNum = RegNumT::NoRegister);
+ Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
/// @}
/// Return a memory operand corresponding to a stack allocated Variable.
uint32_t Offset = 0);
void
- makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+ makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
/// infinite register allocation weight, and returned through the in/out Dest
/// argument.
typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
- int32_t RegNum = Variable::NoRegister) {
+ RegNumT RegNum = RegNumT::NoRegister) {
if (Dest == nullptr)
Dest = makeReg(Src0->getType(), RegNum);
AutoMemorySandboxer<> _(this, &Dest, &Src0);
/// Randomize a given immediate operand
Operand *randomizeOrPoolImmediate(Constant *Immediate,
- int32_t RegNum = Variable::NoRegister);
- X86OperandMem *
- randomizeOrPoolImmediate(X86OperandMem *MemOperand,
- int32_t RegNum = Variable::NoRegister);
+ RegNumT RegNum = RegNumT::NoRegister);
+ X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
+ RegNumT RegNum = RegNumT::NoRegister);
bool RandomizationPoolingPaused = false;
private:
template <typename TraitsType>
void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) {
+ RegNumT::setLimit(Traits::RegisterSet::Reg_NUM);
Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet,
&RegisterAliases);
for (size_t i = 0; i < TypeToRegisterSet.size(); ++i)
}
template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::getPhysicalRegister(SizeT RegNum,
+Variable *TargetX86Base<TraitsType>::getPhysicalRegister(RegNumT RegNum,
Type Ty) {
if (Ty == IceType_void)
Ty = IceType_i32;
if (PhysicalRegisters[Ty].empty())
PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM);
- assert(RegNum < PhysicalRegisters[Ty].size());
+ assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
Variable *Reg = PhysicalRegisters[Ty][RegNum];
if (Reg == nullptr) {
Reg = Func->makeVariable(Ty);
// Don't bother tracking the live range of a named physical register.
Reg->setIgnoreLiveness();
}
- assert(Traits::getGprForType(Ty, RegNum) == static_cast<int32_t>(RegNum));
+ assert(Traits::getGprForType(Ty, RegNum) == RegNum);
return Reg;
}
template <typename TraitsType>
-IceString TargetX86Base<TraitsType>::getRegName(SizeT RegNum, Type Ty) const {
+IceString TargetX86Base<TraitsType>::getRegName(RegNumT RegNum, Type Ty) const {
return Traits::getRegName(Traits::getGprForType(Ty, RegNum));
}
Func->getFunctionName());
}
const int32_t Offset = Var->getStackOffset();
- int32_t BaseRegNum = Var->getBaseRegNum();
- if (BaseRegNum == Variable::NoRegister)
+ auto BaseRegNum = Var->getBaseRegNum();
+ if (BaseRegNum == RegNumT::NoRegister)
BaseRegNum = getFrameOrStackReg();
// Print in the form "Offset(%reg)", taking care that:
// - Offset is never printed when it is 0
Func->getFunctionName());
}
int32_t Offset = Var->getStackOffset();
- int32_t BaseRegNum = Var->getBaseRegNum();
- if (Var->getBaseRegNum() == Variable::NoRegister)
+ auto BaseRegNum = Var->getBaseRegNum();
+ if (Var->getBaseRegNum() == RegNumT::NoRegister)
BaseRegNum = getFrameOrStackReg();
return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset,
AssemblerFixup::NoFixup);
uint32_t NumCallee = 0;
size_t PreservedRegsSizeBytes = 0;
llvm::SmallBitVector Pushed(CalleeSaves.size());
- for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
- const int32_t Canonical = Traits::getBaseReg(i);
+ for (RegNumT i : RegNumBVIter(CalleeSaves)) {
+ const auto Canonical = Traits::getBaseReg(i);
assert(Canonical == Traits::getBaseReg(Canonical));
- if (CalleeSaves[i] && RegsUsed[i]) {
+ if (RegsUsed[i]) {
Pushed[Canonical] = true;
}
}
- for (SizeT i = 0; i < Pushed.size(); ++i) {
- if (!Pushed[i])
- continue;
- assert(static_cast<int32_t>(i) == Traits::getBaseReg(i));
+ for (RegNumT RegNum : RegNumBVIter(Pushed)) {
+ assert(RegNum == Traits::getBaseReg(RegNum));
++NumCallee;
PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType);
- _push_reg(getPhysicalRegister(i, Traits::WordType));
+ _push_reg(getPhysicalRegister(RegNum, Traits::WordType));
}
Ctx->statsUpdateRegistersSaved(NumCallee);
for (Variable *Arg : Args) {
// Skip arguments passed in registers.
if (isVectorType(Arg->getType())) {
- if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != Variable::NoRegister) {
+ if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) {
++NumXmmArgs;
continue;
}
} else if (isScalarFloatingType(Arg->getType())) {
if (Traits::X86_PASS_SCALAR_FP_IN_XMM &&
- Traits::getRegisterForXmmArgNum(NumXmmArgs) != Variable::NoRegister) {
+ Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) {
++NumXmmArgs;
continue;
}
} else {
assert(isScalarIntegerType(Arg->getType()));
if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) !=
- Variable::NoRegister) {
+ RegNumT::NoRegister) {
++NumGPRArgs;
continue;
}
getRegisterSet(RegSet_CalleeSave, RegSet_None);
llvm::SmallBitVector Popped(CalleeSaves.size());
for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) {
- if (static_cast<SizeT>(i) == getFrameReg() && IsEbpBasedFrame)
+ const auto RegNum = RegNumT::fromInt(i);
+ if (RegNum == getFrameReg() && IsEbpBasedFrame)
continue;
- const SizeT Canonical = Traits::getBaseReg(i);
+ const RegNumT Canonical = Traits::getBaseReg(RegNum);
if (CalleeSaves[i] && RegsUsed[i]) {
Popped[Canonical] = true;
}
for (int32_t i = Popped.size() - 1; i >= 0; --i) {
if (!Popped[i])
continue;
- assert(i == Traits::getBaseReg(i));
- _pop(getPhysicalRegister(i, Traits::WordType));
+ const auto RegNum = RegNumT::fromInt(i);
+ assert(RegNum == Traits::getBaseReg(RegNum));
+ _pop(getPhysicalRegister(RegNum, Traits::WordType));
}
if (!NeedSandboxing) {
Variable *Arg = Args[i];
Type Ty = Arg->getType();
Variable *RegisterArg = nullptr;
- int32_t RegNum = Variable::NoRegister;
+ auto RegNum = RegNumT::NoRegister;
if (isVectorType(Ty)) {
RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs);
- if (RegNum == Variable::NoRegister) {
+ if (RegNum == RegNumT::NoRegister) {
XmmSlotsRemain = false;
continue;
}
continue;
}
RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs);
- if (RegNum == Variable::NoRegister) {
+ if (RegNum == RegNumT::NoRegister) {
XmmSlotsRemain = false;
continue;
}
RegisterArg = Func->makeVariable(Ty);
} else if (isScalarIntegerType(Ty)) {
RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs);
- if (RegNum == Variable::NoRegister) {
+ if (RegNum == RegNumT::NoRegister) {
GprSlotsRemain = false;
continue;
}
++NumGprArgs;
RegisterArg = Func->makeVariable(Ty);
}
- assert(RegNum != Variable::NoRegister);
+ assert(RegNum != RegNumT::NoRegister);
assert(RegisterArg != nullptr);
// Replace Arg in the argument list with the home register. Then generate
// an instruction in the prolog to copy the home register to the assigned
// div and idiv are the few arithmetic operators that do not allow
// immediates as the operand.
Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
- uint32_t Eax;
- uint32_t Edx;
+ RegNumT Eax;
+ RegNumT Edx;
switch (Ty) {
default:
llvm::report_fatal_error("Bad type for udiv");
break;
case InstArithmetic::Urem: {
Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
- uint32_t Eax;
- uint32_t Edx;
+ RegNumT Eax;
+ RegNumT Edx;
switch (Ty) {
default:
llvm::report_fatal_error("Bad type for urem");
}
}
Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
- uint32_t Eax;
- uint32_t Edx;
+ RegNumT Eax;
+ RegNumT Edx;
switch (Ty) {
default:
llvm::report_fatal_error("Bad type for srem");
// The PNaCl ABI requires the width of arguments to be at least 32 bits.
assert(typeWidthInBytes(Ty) >= 4);
if (isVectorType(Ty) && (Traits::getRegisterForXmmArgNum(XmmArgs.size()) !=
- Variable::NoRegister)) {
+ RegNumT::NoRegister)) {
XmmArgs.push_back(Arg);
} else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
(Traits::getRegisterForXmmArgNum(XmmArgs.size()) !=
- Variable::NoRegister)) {
+ RegNumT::NoRegister)) {
XmmArgs.push_back(Arg);
} else if (isScalarIntegerType(Ty) &&
(Traits::getRegisterForGprArgNum(Ty, GprArgs.size()) !=
- Variable::NoRegister)) {
+ RegNumT::NoRegister)) {
GprArgs.emplace_back(Ty, Arg);
} else {
// Place on stack.
_mov(DestHi, T_edx);
return;
}
- int32_t Eax;
+ RegNumT Eax;
switch (Ty) {
default:
llvm::report_fatal_error("Bad type for cmpxchg");
return;
}
X86OperandMem *Addr = formMemoryOperand(Ptr, Ty);
- int32_t Eax;
+ RegNumT Eax;
switch (Ty) {
default:
llvm::report_fatal_error("Bad type for atomicRMW");
// We use lowerStore() to copy out-args onto the stack. This creates a memory
// operand with the stack pointer as the base register. Don't do bounds
// checks on that.
- if (Var->getRegNum() == static_cast<int32_t>(getStackReg()))
+ if (Var->getRegNum() == getStackReg())
return;
auto *Label = InstX86Label::create(Func, this);
template <typename TraitsType>
Variable *TargetX86Base<TraitsType>::makeZeroedRegister(Type Ty,
- int32_t RegNum) {
+ RegNumT RegNum) {
Variable *Reg = makeReg(Ty, RegNum);
switch (Ty) {
case IceType_i1:
template <typename TraitsType>
Variable *TargetX86Base<TraitsType>::makeVectorOfZeros(Type Ty,
- int32_t RegNum) {
+ RegNumT RegNum) {
return makeZeroedRegister(Ty, RegNum);
}
template <typename TraitsType>
Variable *TargetX86Base<TraitsType>::makeVectorOfMinusOnes(Type Ty,
- int32_t RegNum) {
+ RegNumT RegNum) {
Variable *MinusOnes = makeReg(Ty, RegNum);
// Insert a FakeDef so the live range of MinusOnes is not overestimated.
Context.insert<InstFakeDef>(MinusOnes);
}
template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, RegNumT RegNum) {
Variable *Dest = makeVectorOfZeros(Ty, RegNum);
Variable *MinusOne = makeVectorOfMinusOnes(Ty);
_psub(Dest, MinusOne);
template <typename TraitsType>
Variable *TargetX86Base<TraitsType>::makeVectorOfHighOrderBits(Type Ty,
- int32_t RegNum) {
+ RegNumT RegNum) {
assert(Ty == IceType_v4i32 || Ty == IceType_v4f32 || Ty == IceType_v8i16 ||
Ty == IceType_v16i8);
if (Ty == IceType_v4f32 || Ty == IceType_v4i32 || Ty == IceType_v8i16) {
// TODO: above, to represent vector constants in memory.
template <typename TraitsType>
Variable *TargetX86Base<TraitsType>::makeVectorOfFabsMask(Type Ty,
- int32_t RegNum) {
+ RegNumT RegNum) {
Variable *Reg = makeVectorOfMinusOnes(Ty, RegNum);
_psrl(Reg, Ctx->getConstantInt8(1));
return Reg;
uint32_t Offset) {
// Ensure that Loc is a stack slot.
assert(Slot->mustNotHaveReg());
- assert(Slot->getRegNum() == Variable::NoRegister);
+ assert(Slot->getRegNum() == RegNumT::NoRegister);
// Compute the location of Loc in memory.
// TODO(wala,stichnot): lea should not
// be required. The address of the stack slot is known at compile time
/// is a convenient way to prevent ah/bh/ch/dh from being an (invalid) argument
/// to the pinsrb instruction.
template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, RegNumT RegNum) {
Type Ty = Src->getType();
assert(isScalarIntegerType(Ty));
assert(Ty != IceType_i1);
/// Helper for legalize() to emit the right code to lower an operand to a
/// register of the appropriate type.
template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, RegNumT RegNum) {
Type Ty = Src->getType();
Variable *Reg = makeReg(Ty, RegNum);
if (isVectorType(Ty)) {
template <typename TraitsType>
Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
- int32_t RegNum) {
+ RegNumT RegNum) {
const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi();
const Type Ty = From->getType();
// Assert that a physical register is allowed. To date, all calls to
// If we're asking for a specific physical register, make sure we're not
// allowing any other operand kinds. (This could be future work, e.g. allow
// the shl shift amount to be either an immediate or in ecx.)
- assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg);
+ assert(RegNum == RegNumT::NoRegister || Allowed == Legal_Reg);
// Substitute with an available infinite-weight variable if possible. Only do
// this when we are not asking for a specific register, and when the
// substitution is not locked to a specific register, and when the types
// match, in order to capture the vast majority of opportunities and avoid
// corner cases in the lowering.
- if (RegNum == Variable::NoRegister) {
+ if (RegNum == RegNumT::NoRegister) {
if (Variable *Subst = getContext().availabilityGet(From)) {
// At this point we know there is a potential substitution available.
if (Subst->mustHaveReg() && !Subst->hasReg()) {
// register in x86-64.
if (Traits::Is64Bit) {
if (llvm::isa<ConstantInteger64>(Const)) {
- if (RegNum != Variable::NoRegister) {
+ if (RegNum != RegNumT::NoRegister) {
assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
}
return copyToReg(Const, RegNum);
_lea(NewVar, Mem);
From = NewVar;
} else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
- (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+ (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
From = copyToReg(From, RegNum);
}
return From;
/// Provide a trivial wrapper to legalize() for this common usage.
template <typename TraitsType>
Variable *TargetX86Base<TraitsType>::legalizeToReg(Operand *From,
- int32_t RegNum) {
+ RegNumT RegNum) {
return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
}
/// Legalize undef values to concrete values.
template <typename TraitsType>
Operand *TargetX86Base<TraitsType>::legalizeUndef(Operand *From,
- int32_t RegNum) {
+ RegNumT RegNum) {
Type Ty = From->getType();
if (llvm::isa<ConstantUndef>(From)) {
// Lower undefs to zero. Another option is to lower undefs to an
}
template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::makeReg(Type Type, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::makeReg(Type Type, RegNumT RegNum) {
// There aren't any 64-bit integer registers for x86-32.
assert(Traits::Is64Bit || Type != IceType_i64);
Variable *Reg = Func->makeVariable(Type);
- if (RegNum == Variable::NoRegister)
+ if (RegNum == RegNumT::NoRegister)
Reg->setMustHaveReg();
else
Reg->setRegNum(RegNum);
template <typename TraitsType>
void TargetX86Base<TraitsType>::makeRandomRegisterPermutation(
- llvm::SmallVectorImpl<int32_t> &Permutation,
+ llvm::SmallVectorImpl<RegNumT> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation,
ExcludeRegisters, Salt);
template <typename TraitsType>
Operand *
TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate,
- int32_t RegNum) {
+ RegNumT RegNum) {
assert(llvm::isa<ConstantInteger32>(Immediate) ||
llvm::isa<ConstantRelocatable>(Immediate));
if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
template <typename TraitsType>
typename TargetX86Base<TraitsType>::X86OperandMem *
TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
- int32_t RegNum) {
+ RegNumT RegNum) {
assert(MemOperand);
if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
RandomizationPoolingPaused == true) {
// phi lowering, we should not ask for new physical registers in
// general. However, if we do meet Memory Operand during phi lowering,
// we should not blind or pool the immediates for now.
- if (RegNum != Variable::NoRegister)
+ if (RegNum != RegNumT::NoRegister)
return MemOperand;
Variable *RegTemp = makeReg(IceType_i32);
IceString Label;