llvm.org GIT mirror llvm / b3382d2
[llvm-exegesis] Fix serialization/deserialization of special NoRegister register (PR41448) Summary: A *lot* of instructions have this special register. It seems this never really worked, but i finally noticed it only because it happened to break for `CMOV16rm` instruction. We serialized that register as "" (empty string), which is naturally 'ignored' during deserialization, so we re-create a `MCInst` with too few operands. And when we then happened to try to resolve variant sched class for this mis-serialized instruction, and the variant predicate tried to read an operand that was out of bounds since we got less operands, we crashed. Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=41448 | PR41448 ]]. Reviewers: craig.topper, courbet Reviewed By: courbet Subscribers: tschuett, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60517 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358153 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Lebedev 1 year, 7 months ago
2 changed file(s) with 31 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
0 # RUN: llvm-exegesis -mode=uops -opcode-name=CMOV16rm -benchmarks-file=%t.CMOV16rm-uops.yaml
1 # RUN: FileCheck -check-prefixes=CHECK-YAML -input-file=%t.CMOV16rm-uops.yaml %s
2 # RUN: llvm-exegesis -mcpu=bdver2 -mode=analysis -benchmarks-file=%t.CMOV16rm-uops.yaml -analysis-clusters-output-file=- -analysis-clustering-epsilon=0.1 -analysis-inconsistency-epsilon=0.1 -analysis-numpoints=1 -analysis-clustering=naive | FileCheck -check-prefixes=CHECK-CLUSTERS %s
3
4 # https://bugs.llvm.org/show_bug.cgi?id=41448
5 # 1. Verify that we correctly serialize RegNo 0 as %noreg, not as an empty string!
6 # 2. Verify that deserialization works. Since CMOV16rm has a variant sched class, just printing clusters is sufficient
7
8 CHECK-YAML: ---
9 CHECK-YAML-NEXT: mode: uops
10 CHECK-YAML-NEXT: key:
11 CHECK-YAML-NEXT: instructions:
12 CHECK-YAML-NEXT: - 'CMOV16rm {{[A-Z0-9]+}} {{[A-Z0-9]+}} {{[A-Z0-9]+}} i_0x1 %noreg i_0x0 %noreg i_0x{{[0-9a-f]}}'
13 CHECK-YAML-LAST: ...
14
15 # CHECK-CLUSTERS: {{^}}cluster_id,opcode_name,config,sched_class,
16 # CHECK-CLUSTERS-NEXT: {{^}}0,
2020 static constexpr const char kIntegerPrefix[] = "i_0x";
2121 static constexpr const char kDoublePrefix[] = "f_";
2222 static constexpr const char kInvalidOperand[] = "INVALID";
23 static constexpr llvm::StringLiteral kNoRegister("%noreg");
2324
2425 namespace llvm {
2526
4647 llvm::StringMap
4748 generateRegNameToRegNoMapping(const llvm::MCRegisterInfo &RegInfo) {
4849 llvm::StringMap Map(RegInfo.getNumRegs());
49 for (unsigned I = 0, E = RegInfo.getNumRegs(); I < E; ++I)
50 // Special-case RegNo 0, which would otherwise be spelled as ''.
51 Map[kNoRegister] = 0;
52 for (unsigned I = 1, E = RegInfo.getNumRegs(); I < E; ++I)
5053 Map[RegInfo.getName(I)] = I;
5154 assert(Map.size() == RegInfo.getNumRegs() && "Size prediction failed");
5255 return Map;
8285 llvm::raw_string_ostream &getErrorStream() { return ErrorStream; }
8386
8487 llvm::StringRef getRegName(unsigned RegNo) {
88 // Special case: RegNo 0 is NoRegister. We have to deal with it explicitly.
89 if (RegNo == 0)
90 return kNoRegister;
8591 const llvm::StringRef RegName = State->getRegInfo().getName(RegNo);
8692 if (RegName.empty())
8793 ErrorStream << "No register with enum value '" << RegNo << "'\n";
8894 return RegName;
8995 }
9096
91 unsigned getRegNo(llvm::StringRef RegName) {
97 llvm::Optional getRegNo(llvm::StringRef RegName) {
9298 auto Iter = RegNameToRegNo.find(RegName);
9399 if (Iter != RegNameToRegNo.end())
94100 return Iter->second;
95101 ErrorStream << "No register with name '" << RegName << "'\n";
96 return 0;
102 return llvm::None;
97103 }
98104
99105 private:
141147 return llvm::MCOperand::createImm(IntValue);
142148 if (tryDeserializeFPOperand(String, DoubleValue))
143149 return llvm::MCOperand::createFPImm(DoubleValue);
144 if (unsigned RegNo = getRegNo(String))
145 return llvm::MCOperand::createReg(RegNo);
150 if (auto RegNo = getRegNo(String))
151 return llvm::MCOperand::createReg(*RegNo);
146152 if (String != kInvalidOperand)
147153 ErrorStream << "Unknown Operand: '" << String << "'\n";
148154 return {};
257263 String.split(Pieces, "=0x", /* MaxSplit */ -1,
258264 /* KeepEmpty */ false);
259265 YamlContext &Context = getTypedContext(Ctx);
260 if (Pieces.size() == 2) {
261 RV.Register = Context.getRegNo(Pieces[0]);
266 llvm::Optional RegNo;
267 if (Pieces.size() == 2 && (RegNo = Context.getRegNo(Pieces[0]))) {
268 RV.Register = *RegNo;
262269 const unsigned BitsNeeded = llvm::APInt::getBitsNeeded(Pieces[1], kRadix);
263270 RV.Value = llvm::APInt(BitsNeeded, Pieces[1], kRadix);
264271 } else {