Index: tools/llvm-exegesis/lib/CodeTemplate.cpp =================================================================== --- tools/llvm-exegesis/lib/CodeTemplate.cpp +++ tools/llvm-exegesis/lib/CodeTemplate.cpp @@ -42,14 +42,12 @@ } llvm::MCOperand &InstructionTemplate::getValueFor(const Operand &Op) { - assert(Op.VariableIndex >= 0); - return getValueFor(Instr.Variables[Op.VariableIndex]); + return getValueFor(Instr.Variables[Op.getVariableIndex()]); } const llvm::MCOperand & InstructionTemplate::getValueFor(const Operand &Op) const { - assert(Op.VariableIndex >= 0); - return getValueFor(Instr.Variables[Op.VariableIndex]); + return getValueFor(Instr.Variables[Op.getVariableIndex()]); } bool InstructionTemplate::hasImmediateVariables() const { @@ -57,8 +55,7 @@ assert(!Var.TiedOperands.empty()); const unsigned OpIndex = Var.TiedOperands[0]; const Operand &Op = Instr.Operands[OpIndex]; - assert(Op.Info); - return Op.Info->OperandType == llvm::MCOI::OPERAND_IMMEDIATE; + return Op.isImm(); }); } @@ -66,7 +63,7 @@ llvm::MCInst Result; Result.setOpcode(Instr.Description->Opcode); for (const auto &Op : Instr.Operands) - if (Op.IsExplicit) + if (Op.isExplicit()) Result.addOperand(getValueFor(Op)); return Result; } Index: tools/llvm-exegesis/lib/MCInstrDescView.h =================================================================== --- tools/llvm-exegesis/lib/MCInstrDescView.h +++ tools/llvm-exegesis/lib/MCInstrDescView.h @@ -56,15 +56,31 @@ // - VariableIndex: the index of the Variable holding the value for this Operand // or -1 if this operand is implicit. struct Operand { - unsigned Index = 0; - bool IsDef = false; - bool IsMem = false; - bool IsExplicit = false; - const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op. - const llvm::MCOperandInfo *Info = nullptr; // Set for Explicit Op. - int TiedToIndex = -1; // Set for Reg&Explicit Op. - const llvm::MCPhysReg *ImplicitReg = nullptr; // Set for Implicit Op. - int VariableIndex = -1; // Set for Explicit Op. + bool getIndex() const { return Index_; } + bool isExplicit() const { return Info_; } + bool isImplicit() const { return !Info_; } + bool isImplicitReg() const { return ImplicitReg_; } + bool isDef() const { return IsDef_; } + bool isUse() const { return !IsDef_; } + bool isReg() const { return Tracker_; } + bool isTied() const { return TiedToIndex_ >= 0; } + bool isVariable() const { return VariableIndex_ >= 0; } + bool isMemory() const; + bool isImm() const; + int getTiedToIndex() const; + int getVariableIndex() const; + unsigned getImplicitReg() const; + const RegisterAliasingTracker &getRegisterAliasing() const; + const llvm::MCOperandInfo &getExplicitOperandInfo() const; + + // Please use the accessors above and not the following fields. + unsigned Index_ = 0; + bool IsDef_ = false; + const RegisterAliasingTracker *Tracker_ = nullptr; // Set for Register Op. + const llvm::MCOperandInfo *Info_ = nullptr; // Set for Explicit Op. + int TiedToIndex_ = -1; // Set for Reg&Explicit Op. + const llvm::MCPhysReg *ImplicitReg_ = nullptr; // Set for Implicit Op. + int VariableIndex_ = -1; // Set for Explicit Op. }; // A view over an MCInstrDesc offering a convenient interface to compute Index: tools/llvm-exegesis/lib/MCInstrDescView.cpp =================================================================== --- tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -17,6 +17,41 @@ namespace exegesis { +bool Operand::isMemory() const { + return isExplicit() && + getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY; +} + +bool Operand::isImm() const { + return isExplicit() && + getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE; +} + +int Operand::getTiedToIndex() const { + assert(isTied()); + return TiedToIndex_; +} + +int Operand::getVariableIndex() const { + assert(isVariable()); + return VariableIndex_; +} + +unsigned Operand::getImplicitReg() const { + assert(ImplicitReg_); + return *ImplicitReg_; +} + +const RegisterAliasingTracker &Operand::getRegisterAliasing() const { + assert(Tracker_); + return *Tracker_; +} + +const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const { + assert(Info_); + return *Info_; +} + Instruction::Instruction(const llvm::MCInstrDesc &MCInstrDesc, const RegisterAliasingTrackerCache &RATC) : Description(&MCInstrDesc) { @@ -24,69 +59,66 @@ for (; OpIndex < MCInstrDesc.getNumOperands(); ++OpIndex) { const auto &OpInfo = MCInstrDesc.opInfo_begin()[OpIndex]; Operand Operand; - Operand.Index = OpIndex; - Operand.IsDef = (OpIndex < MCInstrDesc.getNumDefs()); - Operand.IsMem = OpInfo.OperandType == llvm::MCOI::OPERAND_MEMORY; - Operand.IsExplicit = true; + Operand.Index_ = OpIndex; + Operand.IsDef_ = (OpIndex < MCInstrDesc.getNumDefs()); // TODO(gchatelet): Handle isLookupPtrRegClass. if (OpInfo.RegClass >= 0) - Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass); - Operand.TiedToIndex = + Operand.Tracker_ = &RATC.getRegisterClass(OpInfo.RegClass); + Operand.TiedToIndex_ = MCInstrDesc.getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO); - Operand.Info = &OpInfo; + Operand.Info_ = &OpInfo; Operands.push_back(Operand); } for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitDefs(); MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) { Operand Operand; - Operand.Index = OpIndex; - Operand.IsDef = true; - Operand.IsExplicit = false; - Operand.Tracker = &RATC.getRegister(*MCPhysReg); - Operand.ImplicitReg = MCPhysReg; + Operand.Index_ = OpIndex; + Operand.IsDef_ = true; + Operand.Tracker_ = &RATC.getRegister(*MCPhysReg); + Operand.ImplicitReg_ = MCPhysReg; Operands.push_back(Operand); } for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitUses(); MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) { Operand Operand; - Operand.Index = OpIndex; - Operand.IsDef = false; - Operand.IsExplicit = false; - Operand.Tracker = &RATC.getRegister(*MCPhysReg); - Operand.ImplicitReg = MCPhysReg; + Operand.Index_ = OpIndex; + Operand.IsDef_ = false; + Operand.Tracker_ = &RATC.getRegister(*MCPhysReg); + Operand.ImplicitReg_ = MCPhysReg; Operands.push_back(Operand); } // Assigning Variables to non tied explicit operands. Variables.reserve(Operands.size()); // Variables.size() <= Operands.size() for (auto &Op : Operands) - if (Op.IsExplicit && Op.TiedToIndex < 0) { + if (Op.isExplicit() && !Op.isTied()) { const size_t VariableIndex = Variables.size(); - Op.VariableIndex = VariableIndex; + Op.VariableIndex_ = VariableIndex; Variables.emplace_back(); Variables.back().Index = VariableIndex; } // Assigning Variables to tied operands. for (auto &Op : Operands) - if (Op.TiedToIndex >= 0) - Op.VariableIndex = Operands[Op.TiedToIndex].VariableIndex; + if (Op.isTied()) + Op.VariableIndex_ = Operands[Op.getTiedToIndex()].getVariableIndex(); // Assigning Operands to Variables. for (auto &Op : Operands) - if (Op.VariableIndex >= 0) - Variables[Op.VariableIndex].TiedOperands.push_back(Op.Index); + if (Op.isVariable()) + Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex()); // Processing Aliasing. DefRegisters = RATC.emptyRegisters(); UseRegisters = RATC.emptyRegisters(); for (const auto &Op : Operands) { - if (Op.Tracker) { - auto &Registers = Op.IsDef ? DefRegisters : UseRegisters; - Registers |= Op.Tracker->aliasedBits(); + if (Op.isReg()) { + auto &Registers = Op.isDef() ? DefRegisters : UseRegisters; + Registers |= Op.getRegisterAliasing().aliasedBits(); } } } bool Instruction::hasMemoryOperands() const { - return std::any_of(Operands.begin(), Operands.end(), - [](const Operand &Op) { return Op.IsMem; }); + return std::any_of(Operands.begin(), Operands.end(), [](const Operand &Op) { + return Op.isReg() && Op.isExplicit() && Op.isMemory(); + }); } bool RegisterOperandAssignment:: @@ -103,8 +135,8 @@ const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef Operands, llvm::SmallVectorImpl &OperandValues) { for (const auto &Op : Operands) { - if (Op.Tracker && Op.IsDef == SelectDef) { - const int SourceReg = Op.Tracker->getOrigin(Reg); + if (Op.isReg() && Op.isDef() == SelectDef) { + const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg); if (SourceReg >= 0) OperandValues.emplace_back(&Op, SourceReg); } @@ -113,7 +145,7 @@ bool AliasingRegisterOperands::hasImplicitAliasing() const { const auto HasImplicit = [](const RegisterOperandAssignment &ROV) { - return !ROV.Op->IsExplicit; + return ROV.Op->isImplicit(); }; return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit); } Index: tools/llvm-exegesis/lib/SnippetGenerator.cpp =================================================================== --- tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -70,17 +70,17 @@ // Returns the register that this Operand sets or uses, or 0 if this is not // a register. const auto GetOpReg = [&IT](const Operand &Op) -> unsigned { - if (Op.IsMem) + if (Op.isMemory()) return 0; - if (Op.ImplicitReg) - return *Op.ImplicitReg; - if (Op.IsExplicit && IT.getValueFor(Op).isReg()) + if (Op.isImplicitReg()) + return Op.getImplicitReg(); + if (Op.isExplicit() && IT.getValueFor(Op).isReg()) return IT.getValueFor(Op).getReg(); return 0; }; // Collect used registers that have never been def'ed. for (const Operand &Op : IT.Instr.Operands) { - if (!Op.IsDef) { + if (Op.isUse()) { const unsigned Reg = GetOpReg(Op); if (Reg > 0 && !DefinedRegs.test(Reg)) { RIV.push_back(RegisterValue{Reg, llvm::APInt()}); @@ -90,7 +90,7 @@ } // Mark defs as having been def'ed. for (const Operand &Op : IT.Instr.Operands) { - if (Op.IsDef) { + if (Op.isDef()) { const unsigned Reg = GetOpReg(Op); if (Reg > 0) DefinedRegs.set(Reg); @@ -151,16 +151,14 @@ const llvm::BitVector &ForbiddenRegs) { assert(!Var.TiedOperands.empty()); const Operand &Op = Instr.Operands[Var.TiedOperands.front()]; - assert(Op.Info != nullptr); - const auto &OpInfo = *Op.Info; - switch (OpInfo.OperandType) { + switch (Op.getExplicitOperandInfo().OperandType) { case llvm::MCOI::OperandType::OPERAND_IMMEDIATE: // FIXME: explore immediate values too. AssignedValue = llvm::MCOperand::createImm(1); break; case llvm::MCOI::OperandType::OPERAND_REGISTER: { - assert(Op.Tracker); - auto AllowedRegs = Op.Tracker->sourceBits(); + assert(Op.isReg()); + auto AllowedRegs = Op.getRegisterAliasing().sourceBits(); assert(AllowedRegs.size() == ForbiddenRegs.size()); for (auto I : ForbiddenRegs.set_bits()) AllowedRegs.reset(I); @@ -175,7 +173,7 @@ static void setRegisterOperandValue(const RegisterOperandAssignment &ROV, InstructionTemplate &IB) { assert(ROV.Op); - if (ROV.Op->IsExplicit) { + if (ROV.Op->isExplicit()) { auto &AssignedValue = IB.getValueFor(*ROV.Op); if (AssignedValue.isValid()) { assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); @@ -183,8 +181,8 @@ } AssignedValue = llvm::MCOperand::createReg(ROV.Reg); } else { - assert(ROV.Op->ImplicitReg != nullptr); - assert(ROV.Reg == *ROV.Op->ImplicitReg); + assert(ROV.Op->isImplicitReg()); + assert(ROV.Reg == ROV.Op->getImplicitReg()); } } Index: tools/llvm-exegesis/lib/Uops.cpp =================================================================== --- tools/llvm-exegesis/lib/Uops.cpp +++ tools/llvm-exegesis/lib/Uops.cpp @@ -99,9 +99,9 @@ bool HasDef = false; for (const unsigned OpIndex : Var.TiedOperands) { const Operand &Op = Instr.Operands[OpIndex]; - if (Op.IsDef) + if (Op.isDef()) HasDef = true; - else + if (Op.isUse()) HasUse = true; } return HasUse && HasDef; @@ -170,8 +170,8 @@ // If the instruction implicitly writes to ScratchSpacePointerInReg , abort. // FIXME: We could make a copy of the scratch register. for (const auto &Op : Instr.Operands) { - if (Op.IsDef && Op.ImplicitReg && - ScratchSpaceAliasedRegs->test(*Op.ImplicitReg)) + if (Op.isDef() && Op.isImplicitReg() && + ScratchSpaceAliasedRegs->test(Op.getImplicitReg())) return llvm::make_error( "Infeasible : memory instruction uses scratch memory register"); } @@ -201,9 +201,10 @@ assert(Var); assert(!Var->TiedOperands.empty()); const Operand &Op = Instr.Operands[Var->TiedOperands.front()]; - assert(Op.Tracker); + assert(Op.isReg()); CT.Info = "instruction has tied variables using static renaming."; - for (const llvm::MCPhysReg Reg : Op.Tracker->sourceBits().set_bits()) { + for (const llvm::MCPhysReg Reg : + Op.getRegisterAliasing().sourceBits().set_bits()) { if (ScratchSpaceAliasedRegs && ScratchSpaceAliasedRegs->test(Reg)) continue; // Do not use the scratch memory address register. InstructionTemplate TmpIT = IT; @@ -216,8 +217,8 @@ // No tied variables, we pick random values for defs. llvm::BitVector Defs(State.getRegInfo().getNumRegs()); for (const auto &Op : Instr.Operands) { - if (Op.Tracker && Op.IsExplicit && Op.IsDef && !Op.IsMem) { - auto PossibleRegisters = Op.Tracker->sourceBits(); + if (Op.isReg() && Op.isExplicit() && Op.isDef() && !Op.isMemory()) { + auto PossibleRegisters = Op.getRegisterAliasing().sourceBits(); remove(PossibleRegisters, RATC.reservedRegisters()); // Do not use the scratch memory address register. if (ScratchSpaceAliasedRegs) @@ -231,8 +232,8 @@ // And pick random use values that are not reserved and don't alias with defs. const auto DefAliases = getAliasedBits(State.getRegInfo(), Defs); for (const auto &Op : Instr.Operands) { - if (Op.Tracker && Op.IsExplicit && !Op.IsDef && !Op.IsMem) { - auto PossibleRegisters = Op.Tracker->sourceBits(); + if (Op.isReg() && Op.isExplicit() && Op.isUse() && !Op.isMemory()) { + auto PossibleRegisters = Op.getRegisterAliasing().sourceBits(); remove(PossibleRegisters, RATC.reservedRegisters()); // Do not use the scratch memory address register. if (ScratchSpaceAliasedRegs) Index: tools/llvm-exegesis/lib/X86/Target.cpp =================================================================== --- tools/llvm-exegesis/lib/X86/Target.cpp +++ tools/llvm-exegesis/lib/X86/Target.cpp @@ -262,25 +262,25 @@ // value for input and output. for (size_t I = 0, E = IT.Instr.Operands.size(); I < E; ++I) { const Operand *Op = &IT.Instr.Operands[I]; - if (Op->IsExplicit && Op->IsMem) { + if (Op->isExplicit() && Op->isMemory()) { // Case 1: 5-op memory. assert((I + 5 <= E) && "x86 memory references are always 5 ops"); IT.getValueFor(*Op) = llvm::MCOperand::createReg(Reg); // BaseReg Op = &IT.Instr.Operands[++I]; - assert(Op->IsMem); - assert(Op->IsExplicit); + assert(Op->isMemory()); + assert(Op->isExplicit()); IT.getValueFor(*Op) = llvm::MCOperand::createImm(1); // ScaleAmt Op = &IT.Instr.Operands[++I]; - assert(Op->IsMem); - assert(Op->IsExplicit); + assert(Op->isMemory()); + assert(Op->isExplicit()); IT.getValueFor(*Op) = llvm::MCOperand::createReg(0); // IndexReg Op = &IT.Instr.Operands[++I]; - assert(Op->IsMem); - assert(Op->IsExplicit); + assert(Op->isMemory()); + assert(Op->isExplicit()); IT.getValueFor(*Op) = llvm::MCOperand::createImm(Offset); // Disp Op = &IT.Instr.Operands[++I]; - assert(Op->IsMem); - assert(Op->IsExplicit); + assert(Op->isMemory()); + assert(Op->isExplicit()); IT.getValueFor(*Op) = llvm::MCOperand::createReg(0); // Segment // Case2: segment:index addressing. We assume that ES is 0. }