llvm.org GIT mirror llvm / 7c5ba99
[llvm-exegesis] Teach llvm-exegesis to handle instructions with multiple tied variables. Reviewers: gchatelet Subscribers: tschuett, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58285 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354862 91177308-0d34-0410-b5e6-96231b3b80d8 Clement Courbet 1 year, 9 months ago
2 changed file(s) with 53 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
0 # RUN: llvm-exegesis -mode=uops -opcode-name=XCHG64rr | FileCheck %s
1
2 CHECK: mode: uops
3 CHECK-NEXT: key:
4 CHECK-NEXT: instructions:
5 CHECK-NEXT: XCHG64rr
120120 }
121121 assert(I * MemStep < BenchmarkRunner::ScratchSpace::kSize &&
122122 "not enough scratch space");
123 }
124
125 static std::vector generateSnippetUsingStaticRenaming(
126 const LLVMState &State, const InstructionTemplate &IT,
127 const ArrayRef TiedVariables,
128 const BitVector *ScratchSpaceAliasedRegs) {
129 std::vector Instructions;
130 // Assign registers to variables in a round-robin manner. This is simple but
131 // ensures that the most register-constrained variable does not get starved.
132 std::vector PossibleRegsForVar;
133 for (const Variable *Var : TiedVariables) {
134 assert(Var);
135 const Operand &Op = IT.Instr.getPrimaryOperand(*Var);
136 assert(Op.isReg());
137 BitVector PossibleRegs = State.getRATC().emptyRegisters();
138 if (ScratchSpaceAliasedRegs) {
139 PossibleRegs |= *ScratchSpaceAliasedRegs;
140 }
141 PossibleRegs.flip();
142 PossibleRegs &= Op.getRegisterAliasing().sourceBits();
143 PossibleRegsForVar.push_back(std::move(PossibleRegs));
144 }
145 SmallVector Iterators(TiedVariables.size(), 0);
146 while (true) {
147 InstructionTemplate TmpIT = IT;
148 // Find a possible register for each variable in turn, marking the
149 // register as taken.
150 for (size_t VarId = 0; VarId < TiedVariables.size(); ++VarId) {
151 const int NextPossibleReg =
152 PossibleRegsForVar[VarId].find_next(Iterators[VarId]);
153 if (NextPossibleReg <= 0) {
154 return Instructions;
155 }
156 TmpIT.getValueFor(*TiedVariables[VarId]) =
157 llvm::MCOperand::createReg(NextPossibleReg);
158 // Bump iterator.
159 Iterators[VarId] = NextPossibleReg;
160 // Prevent other variables from using the register.
161 for (BitVector &OtherPossibleRegs : PossibleRegsForVar) {
162 OtherPossibleRegs.reset(NextPossibleReg);
163 }
164 }
165 Instructions.push_back(std::move(TmpIT));
166 }
123167 }
124168
125169 llvm::Expected>
161205 }
162206 const auto TiedVariables = getVariablesWithTiedOperands(Instr);
163207 if (!TiedVariables.empty()) {
164 if (TiedVariables.size() > 1)
165 return llvm::make_error(
166 "Infeasible : don't know how to handle several tied variables",
167 llvm::inconvertibleErrorCode());
168 const Variable *Var = TiedVariables.front();
169 assert(Var);
170 const Operand &Op = Instr.getPrimaryOperand(*Var);
171 assert(Op.isReg());
172 CT.Info = "instruction has tied variables using static renaming.";
173 for (const llvm::MCPhysReg Reg :
174 Op.getRegisterAliasing().sourceBits().set_bits()) {
175 if (ScratchSpaceAliasedRegs && ScratchSpaceAliasedRegs->test(Reg))
176 continue; // Do not use the scratch memory address register.
177 InstructionTemplate TmpIT = IT;
178 TmpIT.getValueFor(*Var) = llvm::MCOperand::createReg(Reg);
179 CT.Instructions.push_back(std::move(TmpIT));
180 }
208 CT.Info = "instruction has tied variables, using static renaming.";
209 CT.Instructions = generateSnippetUsingStaticRenaming(
210 State, IT, TiedVariables, ScratchSpaceAliasedRegs);
181211 instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions);
182212 return getSingleton(std::move(CT));
183213 }