Commit 11c9a325 by Andrew Scull

Weight variables for register allocation by their number of uses.

Count the number of instructions that use a variable following the heuristic that more uses implies higher register priority. This is currently very simple but is precursor work for weighting variables by loop nest depth. BUG= R=jvoung@chromium.org Review URL: https://codereview.chromium.org/1312433004.
parent 25529f7b
...@@ -765,7 +765,7 @@ void Cfg::dump(const IceString &Message) { ...@@ -765,7 +765,7 @@ void Cfg::dump(const IceString &Message) {
Str << getVMetadata()->isMultiBlock(Var); Str << getVMetadata()->isMultiBlock(Var);
else else
Str << "?"; Str << "?";
Str << " weight=" << Var->getWeight() << " "; Str << " weight=" << Var->getWeight(this) << " ";
Var->dump(this); Var->dump(this);
Str << " LIVE=" << Var->getLiveRange() << "\n"; Str << " LIVE=" << Var->getLiveRange() << "\n";
} }
......
...@@ -700,15 +700,15 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, ...@@ -700,15 +700,15 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
Variable *Var = Liveness->getVariable(i, this); Variable *Var = Liveness->getVariable(i, this);
if (LB > LE) { if (LB > LE) {
Var->addLiveRange(FirstInstNum, LE, 1); Var->addLiveRange(FirstInstNum, LE);
Var->addLiveRange(LB, LastInstNum + 1, 1); Var->addLiveRange(LB, LastInstNum + 1);
// Assert that Var is a global variable by checking that its // Assert that Var is a global variable by checking that its
// liveness index is less than the number of globals. This // liveness index is less than the number of globals. This
// ensures that the LiveInAndOut[] access is valid. // ensures that the LiveInAndOut[] access is valid.
assert(i < Liveness->getNumGlobalVars()); assert(i < Liveness->getNumGlobalVars());
LiveInAndOut[i] = false; LiveInAndOut[i] = false;
} else { } else {
Var->addLiveRange(LB, LE, 1); Var->addLiveRange(LB, LE);
} }
if (i == i1) if (i == i1)
++IBB; ++IBB;
...@@ -720,7 +720,7 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, ...@@ -720,7 +720,7 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
i = LiveInAndOut.find_next(i)) { i = LiveInAndOut.find_next(i)) {
Variable *Var = Liveness->getVariable(i, this); Variable *Var = Liveness->getVariable(i, this);
if (Liveness->getRangeMask(Var->getIndex())) if (Liveness->getRangeMask(Var->getIndex()))
Var->addLiveRange(FirstInstNum, LastInstNum + 1, 1); Var->addLiveRange(FirstInstNum, LastInstNum + 1);
} }
} }
......
...@@ -102,7 +102,7 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode, ...@@ -102,7 +102,7 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode,
Variable *Var = *I; Variable *Var = *I;
SizeT VarIndex = Var->getIndex(); SizeT VarIndex = Var->getIndex();
if (Var->getIgnoreLiveness() || if (Var->getIgnoreLiveness() ||
(!IsFullInit && !Var->hasReg() && !Var->getWeight().isInf())) (!IsFullInit && !Var->hasReg() && !Var->mustHaveReg()))
RangeMask[VarIndex] = false; RangeMask[VarIndex] = false;
} }
......
...@@ -145,9 +145,21 @@ Variable *Variable::asType(Type Ty) { ...@@ -145,9 +145,21 @@ Variable *Variable::asType(Type Ty) {
return V; return V;
} }
RegWeight Variable::getWeight(const Cfg *Func) const {
VariablesMetadata *VMetadata = Func->getVMetadata();
return RegWeight(mustHaveReg()
? RegWeight::Inf
: mustNotHaveReg() ? RegWeight::Zero
: VMetadata->getUseWeight(this));
}
void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr, void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
CfgNode *Node, bool IsImplicit) { CfgNode *Node, bool IsImplicit) {
(void)TrackingKind; (void)TrackingKind;
// TODO(ascull): get the loop nest depth from CfgNode
UseWeight += 1;
if (MultiBlock == MBS_MultiBlock) if (MultiBlock == MBS_MultiBlock)
return; return;
// TODO(stichnot): If the use occurs as a source operand in the // TODO(stichnot): If the use occurs as a source operand in the
...@@ -383,6 +395,13 @@ CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { ...@@ -383,6 +395,13 @@ CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
return Metadata[VarNum].getNode(); return Metadata[VarNum].getNode();
} }
uint32_t VariablesMetadata::getUseWeight(const Variable *Var) const {
if (!isTracked(Var))
return 1; // conservative answer
SizeT VarNum = Var->getIndex();
return Metadata[VarNum].getUseWeight();
}
const InstDefList VariablesMetadata::NoDefinitions; const InstDefList VariablesMetadata::NoDefinitions;
// ======================== dump routines ======================== // // ======================== dump routines ======================== //
...@@ -466,7 +485,6 @@ void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); } ...@@ -466,7 +485,6 @@ void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
void LiveRange::dump(Ostream &Str) const { void LiveRange::dump(Ostream &Str) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Str << "(weight=" << Weight << ") ";
bool First = true; bool First = true;
for (const RangeElementType &I : Range) { for (const RangeElementType &I : Range) {
if (!First) if (!First)
......
...@@ -332,8 +332,6 @@ public: ...@@ -332,8 +332,6 @@ public:
void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
void setWeight(uint32_t Val) { Weight = Val; } void setWeight(uint32_t Val) { Weight = Val; }
uint32_t getWeight() const { return Weight; } uint32_t getWeight() const { return Weight; }
bool isInf() const { return Weight == Inf; }
bool isZero() const { return Weight == Zero; }
private: private:
uint32_t Weight = 0; uint32_t Weight = 0;
...@@ -346,9 +344,7 @@ bool operator==(const RegWeight &A, const RegWeight &B); ...@@ -346,9 +344,7 @@ bool operator==(const RegWeight &A, const RegWeight &B);
/// LiveRange is a set of instruction number intervals representing /// LiveRange is a set of instruction number intervals representing
/// a variable's live range. Generally there is one interval per basic /// a variable's live range. Generally there is one interval per basic
/// block where the variable is live, but adjacent intervals get /// block where the variable is live, but adjacent intervals get
/// coalesced into a single interval. LiveRange also includes a /// coalesced into a single interval.
/// weight, in case e.g. we want a live range to have higher weight
/// inside a loop.
class LiveRange { class LiveRange {
public: public:
LiveRange() = default; LiveRange() = default;
...@@ -364,7 +360,6 @@ public: ...@@ -364,7 +360,6 @@ public:
void reset() { void reset() {
Range.clear(); Range.clear();
Weight.setWeight(0);
untrim(); untrim();
} }
void addSegment(InstNumberT Start, InstNumberT End); void addSegment(InstNumberT Start, InstNumberT End);
...@@ -384,9 +379,6 @@ public: ...@@ -384,9 +379,6 @@ public:
void untrim() { TrimmedBegin = Range.begin(); } void untrim() { TrimmedBegin = Range.begin(); }
void trim(InstNumberT Lower); void trim(InstNumberT Lower);
RegWeight getWeight() const { return Weight; }
void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
void dump(Ostream &Str) const; void dump(Ostream &Str) const;
private: private:
...@@ -395,7 +387,6 @@ private: ...@@ -395,7 +387,6 @@ private:
typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>> typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>
RangeType; RangeType;
RangeType Range; RangeType Range;
RegWeight Weight = RegWeight(0);
/// TrimmedBegin is an optimization for the overlaps() computation. /// TrimmedBegin is an optimization for the overlaps() computation.
/// Since the linear-scan algorithm always calls it as overlaps(Cur) /// Since the linear-scan algorithm always calls it as overlaps(Cur)
/// and Cur advances monotonically according to live range start, we /// and Cur advances monotonically according to live range start, we
...@@ -417,6 +408,12 @@ class Variable : public Operand { ...@@ -417,6 +408,12 @@ class Variable : public Operand {
Variable(const Variable &) = delete; Variable(const Variable &) = delete;
Variable &operator=(const Variable &) = delete; Variable &operator=(const Variable &) = delete;
enum RegRequirement {
RR_MayHaveRegister,
RR_MustHaveRegister,
RR_MustNotHaveRegister,
};
public: public:
static Variable *create(Cfg *Func, Type Ty, SizeT Index) { static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index);
...@@ -454,25 +451,22 @@ public: ...@@ -454,25 +451,22 @@ public:
int32_t getRegNumTmp() const { return RegNumTmp; } int32_t getRegNumTmp() const { return RegNumTmp; }
void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
RegWeight getWeight() const { return Weight; } RegWeight getWeight(const Cfg *Func) const;
void setWeight(uint32_t NewWeight) { Weight = RegWeight(NewWeight); }
void setWeightInfinite() { setWeight(RegWeight::Inf); } void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
bool mustNotHaveReg() const {
return RegRequirement == RR_MustNotHaveRegister;
}
LiveRange &getLiveRange() { return Live; } LiveRange &getLiveRange() { return Live; }
const LiveRange &getLiveRange() const { return Live; } const LiveRange &getLiveRange() const { return Live; }
void setLiveRange(const LiveRange &Range) { Live = Range; } void setLiveRange(const LiveRange &Range) { Live = Range; }
void resetLiveRange() { Live.reset(); } void resetLiveRange() { Live.reset(); }
void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { void addLiveRange(InstNumberT Start, InstNumberT End) {
assert(!getIgnoreLiveness()); assert(!getIgnoreLiveness());
assert(WeightDelta != RegWeight::Inf);
Live.addSegment(Start, End); Live.addSegment(Start, End);
if (Weight.isInf())
Live.setWeight(RegWeight(RegWeight::Inf));
else
Live.addWeight(WeightDelta * Weight.getWeight());
}
void setLiveRangeInfiniteWeight() {
Live.setWeight(RegWeight(RegWeight::Inf));
} }
void trimLiveRange(InstNumberT Start) { Live.trim(Start); } void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
void untrimLiveRange() { Live.untrim(); } void untrimLiveRange() { Live.untrim(); }
...@@ -500,7 +494,7 @@ public: ...@@ -500,7 +494,7 @@ public:
/// Used primarily for syntactic correctness of textual assembly /// Used primarily for syntactic correctness of textual assembly
/// emission. Note that only basic information is copied, in /// emission. Note that only basic information is copied, in
/// particular not IsArgument, IsImplicitArgument, IgnoreLiveness, /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
/// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. /// RegNumTmp, Live, LoVar, HiVar, VarsReal.
Variable *asType(Type Ty); Variable *asType(Type Ty);
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
...@@ -540,7 +534,7 @@ protected: ...@@ -540,7 +534,7 @@ protected:
int32_t RegNum = NoRegister; int32_t RegNum = NoRegister;
/// RegNumTmp is the tentative assignment during register allocation. /// RegNumTmp is the tentative assignment during register allocation.
int32_t RegNumTmp = NoRegister; int32_t RegNumTmp = NoRegister;
RegWeight Weight = RegWeight(1); // Register allocation priority RegRequirement RegRequirement = RR_MayHaveRegister;
LiveRange Live; LiveRange Live;
// LoVar and HiVar are needed for lowering from 64 to 32 bits. When // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
// lowering from I64 to I32 on a 32-bit architecture, we split the // lowering from I64 to I32 on a 32-bit architecture, we split the
...@@ -585,6 +579,7 @@ public: ...@@ -585,6 +579,7 @@ public:
const Inst *getSingleDefinition() const; const Inst *getSingleDefinition() const;
const InstDefList &getLatterDefinitions() const { return Definitions; } const InstDefList &getLatterDefinitions() const { return Definitions; }
CfgNode *getNode() const { return SingleUseNode; } CfgNode *getNode() const { return SingleUseNode; }
uint32_t getUseWeight() const { return UseWeight; }
void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node, void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
bool IsImplicit); bool IsImplicit);
void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node); void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
...@@ -599,10 +594,11 @@ private: ...@@ -599,10 +594,11 @@ private:
InstDefList Definitions; /// Only used if Kind==VMK_All InstDefList Definitions; /// Only used if Kind==VMK_All
const Inst *FirstOrSingleDefinition = const Inst *FirstOrSingleDefinition =
nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
uint32_t UseWeight = 0;
}; };
/// VariablesMetadata analyzes and summarizes the metadata for the /// VariablesMetadata analyzes and summarizes the metadata for the complete set
/// complete set of Variables. /// of Variables.
class VariablesMetadata { class VariablesMetadata {
VariablesMetadata() = delete; VariablesMetadata() = delete;
VariablesMetadata(const VariablesMetadata &) = delete; VariablesMetadata(const VariablesMetadata &) = delete;
...@@ -616,29 +612,27 @@ public: ...@@ -616,29 +612,27 @@ public:
/// Add a single node. This is called by init(), and can be called /// Add a single node. This is called by init(), and can be called
/// incrementally from elsewhere, e.g. after edge-splitting. /// incrementally from elsewhere, e.g. after edge-splitting.
void addNode(CfgNode *Node); void addNode(CfgNode *Node);
/// Returns whether the given Variable is tracked in this object. It /// Returns whether the given Variable is tracked in this object. It should
/// should only return false if changes were made to the CFG after /// only return false if changes were made to the CFG after running init(), in
/// running init(), in which case the state is stale and the results /// which case the state is stale and the results shouldn't be trusted (but it
/// shouldn't be trusted (but it may be OK e.g. for dumping). /// may be OK e.g. for dumping).
bool isTracked(const Variable *Var) const { bool isTracked(const Variable *Var) const {
return Var->getIndex() < Metadata.size(); return Var->getIndex() < Metadata.size();
} }
/// Returns whether the given Variable has multiple definitions. /// Returns whether the given Variable has multiple definitions.
bool isMultiDef(const Variable *Var) const; bool isMultiDef(const Variable *Var) const;
/// Returns the first definition instruction of the given Variable. /// Returns the first definition instruction of the given Variable. This is
/// This is only valid for variables whose definitions are all within /// only valid for variables whose definitions are all within the same block,
/// the same block, e.g. T after the lowered sequence "T=B; T+=C; /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
/// A=T", for which getFirstDefinition(T) would return the "T=B" /// getFirstDefinition(T) would return the "T=B" instruction. For variables
/// instruction. For variables with definitions span multiple /// with definitions span multiple blocks, nullptr is returned.
/// blocks, nullptr is returned.
const Inst *getFirstDefinition(const Variable *Var) const; const Inst *getFirstDefinition(const Variable *Var) const;
/// Returns the definition instruction of the given Variable, when /// Returns the definition instruction of the given Variable, when
/// the variable has exactly one definition. Otherwise, nullptr is /// the variable has exactly one definition. Otherwise, nullptr is
/// returned. /// returned.
const Inst *getSingleDefinition(const Variable *Var) const; const Inst *getSingleDefinition(const Variable *Var) const;
/// Returns the list of all definition instructions of the given /// Returns the list of all definition instructions of the given Variable.
/// Variable.
const InstDefList &getLatterDefinitions(const Variable *Var) const; const InstDefList &getLatterDefinitions(const Variable *Var) const;
/// Returns whether the given Variable is live across multiple /// Returns whether the given Variable is live across multiple
...@@ -653,6 +647,10 @@ public: ...@@ -653,6 +647,10 @@ public:
/// isMultiBlock() returns false. Otherwise, nullptr is returned. /// isMultiBlock() returns false. Otherwise, nullptr is returned.
CfgNode *getLocalUseNode(const Variable *Var) const; CfgNode *getLocalUseNode(const Variable *Var) const;
/// Returns the total use weight computed as the sum of uses multiplied by a
/// loop nest depth factor for each use.
uint32_t getUseWeight(const Variable *Var) const;
private: private:
const Cfg *Func; const Cfg *Func;
MetadataKind Kind; MetadataKind Kind;
......
...@@ -99,7 +99,7 @@ void LinearScan::initForGlobal() { ...@@ -99,7 +99,7 @@ void LinearScan::initForGlobal() {
for (Variable *Var : Vars) { for (Variable *Var : Vars) {
// Explicitly don't consider zero-weight variables, which are meant to be // Explicitly don't consider zero-weight variables, which are meant to be
// spill slots. // spill slots.
if (Var->getWeight().isZero()) if (Var->mustNotHaveReg())
continue; continue;
// Don't bother if the variable has a null live range, which means it was // Don't bother if the variable has a null live range, which means it was
// never referenced. // never referenced.
...@@ -109,7 +109,7 @@ void LinearScan::initForGlobal() { ...@@ -109,7 +109,7 @@ void LinearScan::initForGlobal() {
Unhandled.push_back(Var); Unhandled.push_back(Var);
if (Var->hasReg()) { if (Var->hasReg()) {
Var->setRegNumTmp(Var->getRegNum()); Var->setRegNumTmp(Var->getRegNum());
Var->setLiveRangeInfiniteWeight(); Var->setMustHaveReg();
UnhandledPrecolored.push_back(Var); UnhandledPrecolored.push_back(Var);
} }
} }
...@@ -173,7 +173,7 @@ void LinearScan::initForInfOnly() { ...@@ -173,7 +173,7 @@ void LinearScan::initForInfOnly() {
continue; continue;
if (const Variable *Var = Inst.getDest()) { if (const Variable *Var = Inst.getDest()) {
if (!Var->getIgnoreLiveness() && if (!Var->getIgnoreLiveness() &&
(Var->hasReg() || Var->getWeight().isInf())) { (Var->hasReg() || Var->mustHaveReg())) {
if (LRBegin[Var->getIndex()] == Inst::NumberSentinel) { if (LRBegin[Var->getIndex()] == Inst::NumberSentinel) {
LRBegin[Var->getIndex()] = Inst.getNumber(); LRBegin[Var->getIndex()] = Inst.getNumber();
++NumVars; ++NumVars;
...@@ -187,7 +187,7 @@ void LinearScan::initForInfOnly() { ...@@ -187,7 +187,7 @@ void LinearScan::initForInfOnly() {
const Variable *Var = Src->getVar(J); const Variable *Var = Src->getVar(J);
if (Var->getIgnoreLiveness()) if (Var->getIgnoreLiveness())
continue; continue;
if (Var->hasReg() || Var->getWeight().isInf()) if (Var->hasReg() || Var->mustHaveReg())
LREnd[Var->getIndex()] = Inst.getNumber(); LREnd[Var->getIndex()] = Inst.getNumber();
} }
} }
...@@ -202,12 +202,11 @@ void LinearScan::initForInfOnly() { ...@@ -202,12 +202,11 @@ void LinearScan::initForInfOnly() {
assert(LREnd[i] != Inst::NumberSentinel); assert(LREnd[i] != Inst::NumberSentinel);
Unhandled.push_back(Var); Unhandled.push_back(Var);
Var->resetLiveRange(); Var->resetLiveRange();
constexpr uint32_t WeightDelta = 1; Var->addLiveRange(LRBegin[i], LREnd[i]);
Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta);
Var->untrimLiveRange(); Var->untrimLiveRange();
if (Var->hasReg()) { if (Var->hasReg()) {
Var->setRegNumTmp(Var->getRegNum()); Var->setRegNumTmp(Var->getRegNum());
Var->setLiveRangeInfiniteWeight(); Var->setMustHaveReg();
UnhandledPrecolored.push_back(Var); UnhandledPrecolored.push_back(Var);
} }
--NumVars; --NumVars;
...@@ -519,14 +518,14 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -519,14 +518,14 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
assert(Item->rangeOverlaps(Iter.Cur)); assert(Item->rangeOverlaps(Iter.Cur));
int32_t RegNum = Item->getRegNumTmp(); int32_t RegNum = Item->getRegNumTmp();
assert(Item->hasRegTmp()); assert(Item->hasRegTmp());
Iter.Weights[RegNum].addWeight(Item->getLiveRange().getWeight()); Iter.Weights[RegNum].addWeight(Item->getWeight(Func));
} }
// Same as above, but check Inactive ranges instead of Active. // Same as above, but check Inactive ranges instead of Active.
for (const Variable *Item : Inactive) { for (const Variable *Item : Inactive) {
int32_t RegNum = Item->getRegNumTmp(); int32_t RegNum = Item->getRegNumTmp();
assert(Item->hasRegTmp()); assert(Item->hasRegTmp());
if (Item->rangeOverlaps(Iter.Cur)) if (Item->rangeOverlaps(Iter.Cur))
Iter.Weights[RegNum].addWeight(Item->getLiveRange().getWeight()); Iter.Weights[RegNum].addWeight(Item->getWeight(Func));
} }
// All the weights are now calculated. Find the register with smallest // All the weights are now calculated. Find the register with smallest
...@@ -539,11 +538,11 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -539,11 +538,11 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
MinWeightIndex = i; MinWeightIndex = i;
} }
if (Iter.Cur->getLiveRange().getWeight() <= Iter.Weights[MinWeightIndex]) { if (Iter.Cur->getWeight(Func) <= Iter.Weights[MinWeightIndex]) {
// Cur doesn't have priority over any other live ranges, so don't allocate // Cur doesn't have priority over any other live ranges, so don't allocate
// any register to it, and move it to the Handled state. // any register to it, and move it to the Handled state.
Handled.push_back(Iter.Cur); Handled.push_back(Iter.Cur);
if (Iter.Cur->getLiveRange().getWeight().isInf()) { if (Iter.Cur->mustHaveReg()) {
if (Kind == RAK_Phi) if (Kind == RAK_Phi)
addSpillFill(Iter); addSpillFill(Iter);
else else
......
...@@ -410,7 +410,7 @@ void TargetARM32::emitVariable(const Variable *Var) const { ...@@ -410,7 +410,7 @@ void TargetARM32::emitVariable(const Variable *Var) const {
Str << getRegName(Var->getRegNum(), Var->getType()); Str << getRegName(Var->getRegNum(), Var->getType());
return; return;
} }
if (Var->getWeight().isInf()) { if (Var->mustHaveReg()) {
llvm::report_fatal_error( llvm::report_fatal_error(
"Infinite-weight Variable has no register assigned"); "Infinite-weight Variable has no register assigned");
} }
...@@ -907,7 +907,7 @@ StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, ...@@ -907,7 +907,7 @@ StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var,
else else
_add(ScratchReg, OrigBaseReg, OffsetVal); _add(ScratchReg, OrigBaseReg, OffsetVal);
StackVariable *NewVar = Func->makeVariable<StackVariable>(stackSlotType()); StackVariable *NewVar = Func->makeVariable<StackVariable>(stackSlotType());
NewVar->setWeight(RegWeight::Zero); NewVar->setMustNotHaveReg();
NewVar->setBaseRegNum(ScratchReg->getRegNum()); NewVar->setBaseRegNum(ScratchReg->getRegNum());
constexpr int32_t NewOffset = 0; constexpr int32_t NewOffset = 0;
NewVar->setStackOffset(NewOffset); NewVar->setStackOffset(NewOffset);
...@@ -984,7 +984,7 @@ void TargetARM32::legalizeStackSlots() { ...@@ -984,7 +984,7 @@ void TargetARM32::legalizeStackSlots() {
if (isLegalVariableStackOffset(OffsetDiff)) { if (isLegalVariableStackOffset(OffsetDiff)) {
StackVariable *NewDest = StackVariable *NewDest =
Func->makeVariable<StackVariable>(stackSlotType()); Func->makeVariable<StackVariable>(stackSlotType());
NewDest->setWeight(RegWeight::Zero); NewDest->setMustNotHaveReg();
NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum()); NewDest->setBaseRegNum(NewBaseReg->getBaseRegNum());
NewDest->setStackOffset(OffsetDiff); NewDest->setStackOffset(OffsetDiff);
Variable *NewDestVar = NewDest; Variable *NewDestVar = NewDest;
...@@ -1014,7 +1014,7 @@ void TargetARM32::legalizeStackSlots() { ...@@ -1014,7 +1014,7 @@ void TargetARM32::legalizeStackSlots() {
if (isLegalVariableStackOffset(OffsetDiff)) { if (isLegalVariableStackOffset(OffsetDiff)) {
StackVariable *NewVar = StackVariable *NewVar =
Func->makeVariable<StackVariable>(stackSlotType()); Func->makeVariable<StackVariable>(stackSlotType());
NewVar->setWeight(RegWeight::Zero); NewVar->setMustNotHaveReg();
NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum()); NewVar->setBaseRegNum(NewBaseReg->getBaseRegNum());
NewVar->setStackOffset(OffsetDiff); NewVar->setStackOffset(OffsetDiff);
_mov(Dest, NewVar); _mov(Dest, NewVar);
...@@ -2834,7 +2834,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, ...@@ -2834,7 +2834,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
// Check if the variable is guaranteed a physical register. This // Check if the variable is guaranteed a physical register. This
// can happen either when the variable is pre-colored or when it is // can happen either when the variable is pre-colored or when it is
// assigned infinite weight. // assigned infinite weight.
bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg());
// We need a new physical register for the operand if: // We need a new physical register for the operand if:
// Mem is not allowed and Var isn't guaranteed a physical // Mem is not allowed and Var isn't guaranteed a physical
// register, or // register, or
...@@ -2899,7 +2899,7 @@ Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { ...@@ -2899,7 +2899,7 @@ Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) {
assert(Type != IceType_i64); assert(Type != IceType_i64);
Variable *Reg = Func->makeVariable(Type); Variable *Reg = Func->makeVariable(Type);
if (RegNum == Variable::NoRegister) if (RegNum == Variable::NoRegister)
Reg->setWeightInfinite(); Reg->setMustHaveReg();
else else
Reg->setRegNum(RegNum); Reg->setRegNum(RegNum);
return Reg; return Reg;
......
...@@ -429,7 +429,7 @@ void TargetX8632::addProlog(CfgNode *Node) { ...@@ -429,7 +429,7 @@ void TargetX8632::addProlog(CfgNode *Node) {
[&VariablesLinkedToSpillSlots](Variable *Var) { [&VariablesLinkedToSpillSlots](Variable *Var) {
if (auto *SpillVar = if (auto *SpillVar =
llvm::dyn_cast<typename Traits::SpillVariable>(Var)) { llvm::dyn_cast<typename Traits::SpillVariable>(Var)) {
assert(Var->getWeight().isZero()); assert(Var->mustNotHaveReg());
if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) {
VariablesLinkedToSpillSlots.push_back(Var); VariablesLinkedToSpillSlots.push_back(Var);
return true; return true;
......
...@@ -449,7 +449,7 @@ void TargetX8664::addProlog(CfgNode *Node) { ...@@ -449,7 +449,7 @@ void TargetX8664::addProlog(CfgNode *Node) {
[&VariablesLinkedToSpillSlots](Variable *Var) { [&VariablesLinkedToSpillSlots](Variable *Var) {
if (auto *SpillVar = if (auto *SpillVar =
llvm::dyn_cast<typename Traits::SpillVariable>(Var)) { llvm::dyn_cast<typename Traits::SpillVariable>(Var)) {
assert(Var->getWeight().isZero()); assert(Var->mustNotHaveReg());
if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) {
VariablesLinkedToSpillSlots.push_back(Var); VariablesLinkedToSpillSlots.push_back(Var);
return true; return true;
......
...@@ -585,7 +585,7 @@ template <class Machine> void TargetX86Base<Machine>::findRMW() { ...@@ -585,7 +585,7 @@ template <class Machine> void TargetX86Base<Machine>::findRMW() {
Str << "\n"; Str << "\n";
} }
Variable *Beacon = Func->makeVariable(IceType_i32); Variable *Beacon = Func->makeVariable(IceType_i32);
Beacon->setWeight(0); Beacon->setMustNotHaveReg();
Store->setRmwBeacon(Beacon); Store->setRmwBeacon(Beacon);
InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon); InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon);
Node->getInsts().insert(I3, BeaconDef); Node->getInsts().insert(I3, BeaconDef);
...@@ -763,7 +763,7 @@ void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { ...@@ -763,7 +763,7 @@ void TargetX86Base<Machine>::emitVariable(const Variable *Var) const {
Str << "%" << getRegName(Var->getRegNum(), Var->getType()); Str << "%" << getRegName(Var->getRegNum(), Var->getType());
return; return;
} }
if (Var->getWeight().isInf()) { if (Var->mustHaveReg()) {
llvm_unreachable("Infinite-weight Variable has no register assigned"); llvm_unreachable("Infinite-weight Variable has no register assigned");
} }
int32_t Offset = Var->getStackOffset(); int32_t Offset = Var->getStackOffset();
...@@ -784,7 +784,7 @@ typename TargetX86Base<Machine>::Traits::Address ...@@ -784,7 +784,7 @@ typename TargetX86Base<Machine>::Traits::Address
TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
if (Var->hasReg()) if (Var->hasReg())
llvm_unreachable("Stack Variable has a register assigned"); llvm_unreachable("Stack Variable has a register assigned");
if (Var->getWeight().isInf()) { if (Var->mustHaveReg()) {
llvm_unreachable("Infinite-weight Variable has no register assigned"); llvm_unreachable("Infinite-weight Variable has no register assigned");
} }
int32_t Offset = Var->getStackOffset(); int32_t Offset = Var->getStackOffset();
...@@ -2054,7 +2054,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2054,7 +2054,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
T_1 = makeReg(IceType_i32); T_1 = makeReg(IceType_i32);
} }
// cvt() requires its integer argument to be a GPR. // cvt() requires its integer argument to be a GPR.
T_1->setWeightInfinite(); T_1->setMustHaveReg();
Variable *T_2 = makeReg(Dest->getType()); Variable *T_2 = makeReg(Dest->getType());
_cvt(T_1, Src0RM, Traits::Insts::Cvt::Tss2si); _cvt(T_1, Src0RM, Traits::Insts::Cvt::Tss2si);
_mov(T_2, T_1); // T_1 and T_2 may have different integer types _mov(T_2, T_1); // T_1 and T_2 may have different integer types
...@@ -2105,7 +2105,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2105,7 +2105,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
assert(Dest->getType() != IceType_i32); assert(Dest->getType() != IceType_i32);
T_1 = makeReg(IceType_i32); T_1 = makeReg(IceType_i32);
} }
T_1->setWeightInfinite(); T_1->setMustHaveReg();
Variable *T_2 = makeReg(Dest->getType()); Variable *T_2 = makeReg(Dest->getType());
_cvt(T_1, Src0RM, Traits::Insts::Cvt::Tss2si); _cvt(T_1, Src0RM, Traits::Insts::Cvt::Tss2si);
_mov(T_2, T_1); // T_1 and T_2 may have different integer types _mov(T_2, T_1); // T_1 and T_2 may have different integer types
...@@ -2147,7 +2147,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2147,7 +2147,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
assert(Src0RM->getType() != IceType_i64); assert(Src0RM->getType() != IceType_i64);
T_1 = makeReg(IceType_i32); T_1 = makeReg(IceType_i32);
} }
T_1->setWeightInfinite(); T_1->setMustHaveReg();
Variable *T_2 = makeReg(Dest->getType()); Variable *T_2 = makeReg(Dest->getType());
if (Src0RM->getType() == T_1->getType()) if (Src0RM->getType() == T_1->getType())
_mov(T_1, Src0RM); _mov(T_1, Src0RM);
...@@ -2196,7 +2196,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2196,7 +2196,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
assert(Traits::Is64Bit || Src0RM->getType() != IceType_i32); assert(Traits::Is64Bit || Src0RM->getType() != IceType_i32);
T_1 = makeReg(IceType_i32); T_1 = makeReg(IceType_i32);
} }
T_1->setWeightInfinite(); T_1->setMustHaveReg();
Variable *T_2 = makeReg(Dest->getType()); Variable *T_2 = makeReg(Dest->getType());
if (Src0RM->getType() == T_1->getType()) if (Src0RM->getType() == T_1->getType())
_mov(T_1, Src0RM); _mov(T_1, Src0RM);
...@@ -2248,7 +2248,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2248,7 +2248,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
Func->makeVariable<typename Traits::SpillVariable>(SrcType); Func->makeVariable<typename Traits::SpillVariable>(SrcType);
SpillVar->setLinkedTo(Dest); SpillVar->setLinkedTo(Dest);
Variable *Spill = SpillVar; Variable *Spill = SpillVar;
Spill->setWeight(RegWeight::Zero); Spill->setMustNotHaveReg();
_mov(T, Src0RM); _mov(T, Src0RM);
_mov(Spill, T); _mov(Spill, T);
_mov(Dest, Spill); _mov(Dest, Spill);
...@@ -2276,7 +2276,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2276,7 +2276,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
Func->makeVariable<typename Traits::SpillVariable>(IceType_f64); Func->makeVariable<typename Traits::SpillVariable>(IceType_f64);
SpillVar->setLinkedTo(Src0Var); SpillVar->setLinkedTo(Src0Var);
Variable *Spill = SpillVar; Variable *Spill = SpillVar;
Spill->setWeight(RegWeight::Zero); Spill->setMustNotHaveReg();
_movq(Spill, Src0RM); _movq(Spill, Src0RM);
SpillLo = Traits::VariableSplit::create(Func, Spill, SpillLo = Traits::VariableSplit::create(Func, Spill,
Traits::VariableSplit::Low); Traits::VariableSplit::Low);
...@@ -2305,7 +2305,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2305,7 +2305,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
Variable *T = makeReg(IceType_f64); Variable *T = makeReg(IceType_f64);
// Movd requires its fp argument (in this case, the bitcast destination) // Movd requires its fp argument (in this case, the bitcast destination)
// to be an xmm register. // to be an xmm register.
T->setWeightInfinite(); T->setMustHaveReg();
_movd(T, Src0RM); _movd(T, Src0RM);
_mov(Dest, T); _mov(Dest, T);
} else { } else {
...@@ -2327,7 +2327,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) { ...@@ -2327,7 +2327,7 @@ void TargetX86Base<Machine>::lowerCast(const InstCast *Inst) {
Func->makeVariable<typename Traits::SpillVariable>(IceType_f64); Func->makeVariable<typename Traits::SpillVariable>(IceType_f64);
SpillVar->setLinkedTo(Dest); SpillVar->setLinkedTo(Dest);
Variable *Spill = SpillVar; Variable *Spill = SpillVar;
Spill->setWeight(RegWeight::Zero); Spill->setMustNotHaveReg();
Variable *T_Lo = nullptr, *T_Hi = nullptr; Variable *T_Lo = nullptr, *T_Hi = nullptr;
typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create( typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create(
...@@ -2429,7 +2429,7 @@ void TargetX86Base<Machine>::lowerExtractElement( ...@@ -2429,7 +2429,7 @@ void TargetX86Base<Machine>::lowerExtractElement(
// TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when
// support for legalizing to mem is implemented. // support for legalizing to mem is implemented.
Variable *Slot = Func->makeVariable(Ty); Variable *Slot = Func->makeVariable(Ty);
Slot->setWeight(RegWeight::Zero); Slot->setMustNotHaveReg();
_movp(Slot, legalizeToReg(SourceVectNotLegalized)); _movp(Slot, legalizeToReg(SourceVectNotLegalized));
// Compute the location of the element in memory. // Compute the location of the element in memory.
...@@ -2838,7 +2838,7 @@ void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) { ...@@ -2838,7 +2838,7 @@ void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) {
// TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when
// support for legalizing to mem is implemented. // support for legalizing to mem is implemented.
Variable *Slot = Func->makeVariable(Ty); Variable *Slot = Func->makeVariable(Ty);
Slot->setWeight(RegWeight::Zero); Slot->setMustNotHaveReg();
_movp(Slot, legalizeToReg(SourceVectNotLegalized)); _movp(Slot, legalizeToReg(SourceVectNotLegalized));
// Compute the location of the position to insert in memory. // Compute the location of the position to insert in memory.
...@@ -4848,7 +4848,7 @@ typename TargetX86Base<Machine>::Traits::X86OperandMem * ...@@ -4848,7 +4848,7 @@ typename TargetX86Base<Machine>::Traits::X86OperandMem *
TargetX86Base<Machine>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, TargetX86Base<Machine>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
uint32_t Offset) { uint32_t Offset) {
// Ensure that Loc is a stack slot. // Ensure that Loc is a stack slot.
assert(Slot->getWeight().isZero()); assert(Slot->mustNotHaveReg());
assert(Slot->getRegNum() == Variable::NoRegister); assert(Slot->getRegNum() == Variable::NoRegister);
// Compute the location of Loc in memory. // Compute the location of Loc in memory.
// TODO(wala,stichnot): lea should not be required. The address of // TODO(wala,stichnot): lea should not be required. The address of
...@@ -4932,7 +4932,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, ...@@ -4932,7 +4932,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed,
if (Traits::Is64Bit) { if (Traits::Is64Bit) {
if (llvm::isa<ConstantInteger64>(Const)) { if (llvm::isa<ConstantInteger64>(Const)) {
Variable *V = copyToReg(Const, RegNum); Variable *V = copyToReg(Const, RegNum);
V->setWeightInfinite(); V->setMustHaveReg();
return V; return V;
} }
} }
...@@ -4973,7 +4973,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, ...@@ -4973,7 +4973,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed,
// Check if the variable is guaranteed a physical register. This // Check if the variable is guaranteed a physical register. This
// can happen either when the variable is pre-colored or when it is // can happen either when the variable is pre-colored or when it is
// assigned infinite weight. // assigned infinite weight.
bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg());
// We need a new physical register for the operand if: // We need a new physical register for the operand if:
// Mem is not allowed and Var isn't guaranteed a physical // Mem is not allowed and Var isn't guaranteed a physical
// register, or // register, or
...@@ -5077,7 +5077,7 @@ Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { ...@@ -5077,7 +5077,7 @@ Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) {
assert(Traits::Is64Bit || Type != IceType_i64); assert(Traits::Is64Bit || Type != IceType_i64);
Variable *Reg = Func->makeVariable(Type); Variable *Reg = Func->makeVariable(Type);
if (RegNum == Variable::NoRegister) if (RegNum == Variable::NoRegister)
Reg->setWeightInfinite(); Reg->setMustHaveReg();
else else
Reg->setRegNum(RegNum); Reg->setRegNum(RegNum);
return Reg; return Reg;
......
...@@ -169,13 +169,13 @@ next2: ...@@ -169,13 +169,13 @@ next2:
br i1 %cmp, label %next, label %next2 br i1 %cmp, label %next, label %next2
} }
; CHECK-LABEL: test_local_forward_then_back ; CHECK-LABEL: test_local_forward_then_back
; CHECK: 14: {{.*}} mov DWORD PTR ; CHECK: {{.*}} mov DWORD PTR
; CHECK-NEXT: 16: {{.*}} mfence ; CHECK-NEXT: {{.*}} mfence
; CHECK-NEXT: 19: {{.*}} mov DWORD PTR {{.*}},0x1 ; CHECK-NEXT: 16: {{.*}} mov {{.*}},0x1
; CHECK-NEXT: 20: {{.*}} cmp ; CHECK-NEXT: {{.*}} cmp
; CHECK-NEXT: 23: {{.*}} jb 33 ; CHECK-NEXT: {{.*}} jb
; CHECK: 37: {{.*}} jne 14 ; CHECK: {{.*}} jne
; CHECK: 39: {{.*}} jmp 19 ; CHECK: {{.*}} jmp 16
; Test that backward local branches also work and are small. ; Test that backward local branches also work and are small.
......
...@@ -33,14 +33,14 @@ entry: ...@@ -33,14 +33,14 @@ entry:
%res = select <8 x i1> %cond, <8 x i16> %res_acc1_3, <8 x i16> %res_acc2_4 %res = select <8 x i1> %cond, <8 x i16> %res_acc1_3, <8 x i16> %res_acc2_4
ret <8 x i16> %res ret <8 x i16> %res
; CHECK-LABEL: test_mul_v8i16_more_regs ; CHECK-LABEL: test_mul_v8i16_more_regs
; CHECK-DAG: 66 0f d5 c2 pmullw xmm0,xmm2 ; CHECK-DAG: pmullw xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f d5 c3 pmullw xmm0,xmm3 ; CHECK-DAG: pmullw xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f d5 c4 pmullw xmm0,xmm4 ; CHECK-DAG: pmullw xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f d5 c5 pmullw xmm0,xmm5 ; CHECK-DAG: pmullw xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f d5 c6 pmullw xmm0,xmm6 ; CHECK-DAG: pmullw xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f d5 c7 pmullw xmm0,xmm7 ; CHECK-DAG: pmullw xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f d5 44 24 70 pmullw xmm0,XMMWORD PTR [esp ; CHECK-DAG: pmullw xmm0,XMMWORD PTR [esp
; CHECK-DAG: 66 0f d5 8c 24 80 00 00 00 pmullw xmm1,XMMWORD PTR [esp ; CHECK-DAG: pmullw xmm1,XMMWORD PTR [esp
} }
define <4 x i32> @test_mul_v4i32(<4 x i32> %arg0, <4 x i32> %arg1) { define <4 x i32> @test_mul_v4i32(<4 x i32> %arg0, <4 x i32> %arg1) {
...@@ -70,14 +70,14 @@ entry: ...@@ -70,14 +70,14 @@ entry:
%res = select <4 x i1> %cond, <4 x i32> %res_acc1_3, <4 x i32> %res_acc2_4 %res = select <4 x i1> %cond, <4 x i32> %res_acc1_3, <4 x i32> %res_acc2_4
ret <4 x i32> %res ret <4 x i32> %res
; CHECK-LABEL: test_mul_v4i32_more_regs ; CHECK-LABEL: test_mul_v4i32_more_regs
; CHECK-DAG: 66 0f 38 40 c2 pmulld xmm0,xmm2 ; CHECK-DAG: pmulld xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f 38 40 c3 pmulld xmm0,xmm3 ; CHECK-DAG: pmulld xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f 38 40 c4 pmulld xmm0,xmm4 ; CHECK-DAG: pmulld xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f 38 40 c5 pmulld xmm0,xmm5 ; CHECK-DAG: pmulld xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f 38 40 c6 pmulld xmm0,xmm6 ; CHECK-DAG: pmulld xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f 38 40 c7 pmulld xmm0,xmm7 ; CHECK-DAG: pmulld xmm0,{{xmm[0-7]|xmmword ptr\[esp}}
; CHECK-DAG: 66 0f 38 40 44 24 70 pmulld xmm0,XMMWORD PTR [esp ; CHECK-DAG: pmulld xmm0,XMMWORD PTR [esp
; CHECK-DAG: 66 0f 38 40 8c 24 80 00 00 00 pmulld xmm1,XMMWORD PTR [esp ; CHECK-DAG: pmulld xmm1,XMMWORD PTR [esp
} }
; Test movq, which is used by atomic stores. ; Test movq, which is used by atomic stores.
...@@ -192,7 +192,7 @@ entry: ...@@ -192,7 +192,7 @@ entry:
; CHECK-LABEL: test_pinsrb ; CHECK-LABEL: test_pinsrb
; CHECK-DAG: 66 0f 3a 20 c{{.*}} 01 pinsrb xmm0,e{{.*}} ; CHECK-DAG: 66 0f 3a 20 c{{.*}} 01 pinsrb xmm0,e{{.*}}
; CHECK-DAG: 66 0f 3a 20 c{{.*}} 07 pinsrb xmm0,e{{.*}} ; CHECK-DAG: 66 0f 3a 20 c{{.*}} 07 pinsrb xmm0,e{{.*}}
; CHECK-DAG: 66 0f 3a 20 {{.*}} 0f pinsrb xmm0,BYTE PTR {{.*}} ; CHECK-DAG: 66 0f 3a 20 c{{.*}} 0f pinsrb xmm0,e{{.*}}
define <8 x i16> @test_pinsrw(<8 x i16> %vec, i32 %elt1_w, i32 %elt2_w, i32 %elt3_w, i32 %elt4_w) { define <8 x i16> @test_pinsrw(<8 x i16> %vec, i32 %elt1_w, i32 %elt2_w, i32 %elt3_w, i32 %elt4_w) {
entry: entry:
......
...@@ -128,6 +128,5 @@ done: ...@@ -128,6 +128,5 @@ done:
} }
; O2-LABEL: test_atomic_cmpxchg_no_opt2 ; O2-LABEL: test_atomic_cmpxchg_no_opt2
; O2: lock cmpxchg DWORD PTR [e{{[^a].}}],e{{[^a]}} ; O2: lock cmpxchg DWORD PTR [e{{[^a].}}],e{{[^a]}}
; O2: mov {{.*}}
; O2: cmp ; O2: cmp
; O2: sete ; O2: sete
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment