[llvm-exegesis] Refactor how forbidden registers are computed.

Summary:
Right now latency generation can incorrectly select the scratch register
as a dependency-carrying register.
 - Move the logic for preventing register selection from Uops
   implementation to common SnippetGenerator class.
 - Aliasing detection now takes a set of forbidden registers just like
   random register assignment does.

Reviewers: gchatelet

Subscribers: tschuett, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D68084

llvm-svn: 373048
diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
index 8b110f8..1c225bb 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
@@ -61,7 +61,8 @@
   std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) {
     randomGenerator().seed(0); // Initialize seed.
     const Instruction &Instr = State.getIC().getInstr(Opcode);
-    auto CodeTemplateOrError = Generator.generateCodeTemplates(Instr);
+    auto CodeTemplateOrError = Generator.generateCodeTemplates(
+        Instr, State.getRATC().emptyRegisters());
     EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.
     return std::move(CodeTemplateOrError.get());
   }
@@ -148,6 +149,26 @@
       << "Op0 is either set to Op1 or to Op2";
 }
 
+TEST_F(LatencySnippetGeneratorTest,
+       ImplicitSelfDependencyThroughExplicitRegsForbidAll) {
+  // - VXORPSrr
+  // - Op0 Explicit Def RegClass(VR128)
+  // - Op1 Explicit Use RegClass(VR128)
+  // - Op2 Explicit Use RegClass(VR128)
+  // - Var0 [Op0]
+  // - Var1 [Op1]
+  // - Var2 [Op2]
+  // - hasAliasingRegisters
+  const unsigned Opcode = llvm::X86::VXORPSrr;
+  randomGenerator().seed(0); // Initialize seed.
+  const Instruction &Instr = State.getIC().getInstr(Opcode);
+  auto AllRegisters = State.getRATC().emptyRegisters();
+  AllRegisters.flip();
+  auto Error = Generator.generateCodeTemplates(Instr, AllRegisters).takeError();
+  EXPECT_TRUE((bool)Error);
+  llvm::consumeError(std::move(Error));
+}
+
 TEST_F(LatencySnippetGeneratorTest, DependencyThroughOtherOpcode) {
   // - CMP64rr
   // - Op0 Explicit Use RegClass(GR64)
@@ -323,7 +344,31 @@
   EXPECT_EQ(IT.VariableValues[5].getReg(), 0u);
 }
 
-TEST_F(UopsSnippetGeneratorTest, MemoryUse_Movsb) {
+class FakeSnippetGenerator : public SnippetGenerator {
+public:
+  FakeSnippetGenerator(const LLVMState &State) : SnippetGenerator(State) {}
+
+  Instruction createInstruction(unsigned Opcode) {
+    return State.getIC().getInstr(Opcode);
+  }
+
+private:
+  llvm::Expected<std::vector<CodeTemplate>>
+  generateCodeTemplates(const Instruction &, const BitVector &) const override {
+    return llvm::make_error<llvm::StringError>("not implemented",
+                                               llvm::inconvertibleErrorCode());
+  }
+};
+
+using FakeSnippetGeneratorTest = SnippetGeneratorTest<FakeSnippetGenerator>;
+
+testing::Matcher<const RegisterValue &> IsRegisterValue(unsigned Reg,
+                                                        llvm::APInt Value) {
+  return testing::AllOf(testing::Field(&RegisterValue::Register, Reg),
+                        testing::Field(&RegisterValue::Value, Value));
+}
+
+TEST_F(FakeSnippetGeneratorTest, MemoryUse_Movsb) {
   // MOVSB writes to scratch memory register.
   // - MOVSB
   // - Op0 Explicit Use Memory RegClass(GR8)
@@ -342,35 +387,11 @@
   // - hasAliasingRegisters
   const unsigned Opcode = llvm::X86::MOVSB;
   const Instruction &Instr = State.getIC().getInstr(Opcode);
-  auto Error = Generator.generateCodeTemplates(Instr).takeError();
+  auto Error = Generator.generateConfigurations(Instr).takeError();
   EXPECT_TRUE((bool)Error);
   llvm::consumeError(std::move(Error));
 }
 
-class FakeSnippetGenerator : public SnippetGenerator {
-public:
-  FakeSnippetGenerator(const LLVMState &State) : SnippetGenerator(State) {}
-
-  Instruction createInstruction(unsigned Opcode) {
-    return State.getIC().getInstr(Opcode);
-  }
-
-private:
-  llvm::Expected<std::vector<CodeTemplate>>
-  generateCodeTemplates(const Instruction &Instr) const override {
-    return llvm::make_error<llvm::StringError>("not implemented",
-                                               llvm::inconvertibleErrorCode());
-  }
-};
-
-using FakeSnippetGeneratorTest = SnippetGeneratorTest<FakeSnippetGenerator>;
-
-testing::Matcher<const RegisterValue &> IsRegisterValue(unsigned Reg,
-                                                        llvm::APInt Value) {
-  return testing::AllOf(testing::Field(&RegisterValue::Register, Reg),
-                        testing::Field(&RegisterValue::Value, Value));
-}
-
 TEST_F(FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd16ri) {
   // ADD16ri:
   // explicit def 0       : reg RegClass=GR16