[llvm] 04fd204 - [llvm-exegesis] Allow the randomizer to fail nicely...

Clement Courbet via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 23 02:09:04 PST 2020


Author: Clement Courbet
Date: 2020-01-23T11:08:44+01:00
New Revision: 04fd20415612f02c4b09da526f19d24e6fe18e7e

URL: https://github.com/llvm/llvm-project/commit/04fd20415612f02c4b09da526f19d24e6fe18e7e
DIFF: https://github.com/llvm/llvm-project/commit/04fd20415612f02c4b09da526f19d24e6fe18e7e.diff

LOG: [llvm-exegesis] Allow the randomizer to fail nicely...

Summary:
... instead of crashing.
On typical exmaple is when there are no available registers.

Reviewers: gchatelet

Subscribers: tschuett, mstojanovic, llvm-commits

Tags: #llvm

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

Added: 
    

Modified: 
    llvm/tools/llvm-exegesis/lib/RegisterAliasing.cpp
    llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
    llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
    llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
    llvm/tools/llvm-exegesis/lib/Target.cpp
    llvm/tools/llvm-exegesis/lib/Target.h
    llvm/tools/llvm-exegesis/lib/X86/Target.cpp
    llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/tools/llvm-exegesis/lib/RegisterAliasing.cpp b/llvm/tools/llvm-exegesis/lib/RegisterAliasing.cpp
index 1db195240155..ee612fb0dd6a 100644
--- a/llvm/tools/llvm-exegesis/lib/RegisterAliasing.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RegisterAliasing.cpp
@@ -79,5 +79,14 @@ RegisterAliasingTrackerCache::getRegisterClass(unsigned RegClassIndex) const {
   return *Found;
 }
 
+std::string debugString(const MCRegisterInfo &RegInfo, const BitVector &Regs) {
+  std::string Result;
+  for (const unsigned Reg : Regs.set_bits()) {
+    Result.append(RegInfo.getName(Reg));
+    Result.push_back(' ');
+  }
+  return Result;
+}
+
 } // namespace exegesis
 } // namespace llvm

diff  --git a/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h b/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
index f269c89a3f93..b2980854ba2d 100644
--- a/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
+++ b/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
@@ -110,6 +110,9 @@ inline void remove(BitVector &A, const BitVector &B) {
     A.reset(I);
 }
 
+// Returns a debug string for the list of registers.
+std::string debugString(const MCRegisterInfo &RegInfo, const BitVector &Regs);
+
 } // namespace exegesis
 } // namespace llvm
 

diff  --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
index d1f168fe43bf..af3709486ec2 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
@@ -72,7 +72,8 @@ Expected<std::vector<BenchmarkCode>> SnippetGenerator::generateConfigurations(
         BenchmarkCode BC;
         BC.Info = CT.Info;
         for (InstructionTemplate &IT : CT.Instructions) {
-          randomizeUnsetVariables(State.getExegesisTarget(), ForbiddenRegs, IT);
+          if (auto error = randomizeUnsetVariables(State, ForbiddenRegs, IT))
+            return std::move(error);
           BC.Key.Instructions.push_back(IT.build());
         }
         if (CT.ScratchSpacePointerInReg)
@@ -215,15 +216,53 @@ void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
   setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB);
 }
 
-void randomizeUnsetVariables(const ExegesisTarget &Target,
-                             const BitVector &ForbiddenRegs,
-                             InstructionTemplate &IT) {
+static Error randomizeMCOperand(const LLVMState &State,
+                                const Instruction &Instr, const Variable &Var,
+                                MCOperand &AssignedValue,
+                                const BitVector &ForbiddenRegs) {
+  const Operand &Op = Instr.getPrimaryOperand(Var);
+  if (Op.getExplicitOperandInfo().OperandType >=
+      MCOI::OperandType::OPERAND_FIRST_TARGET)
+    return State.getExegesisTarget().randomizeTargetMCOperand(
+        Instr, Var, AssignedValue, ForbiddenRegs);
+  switch (Op.getExplicitOperandInfo().OperandType) {
+  case MCOI::OperandType::OPERAND_IMMEDIATE:
+    // FIXME: explore immediate values too.
+    AssignedValue = MCOperand::createImm(1);
+    break;
+  case MCOI::OperandType::OPERAND_REGISTER: {
+    assert(Op.isReg());
+    auto AllowedRegs = Op.getRegisterAliasing().sourceBits();
+    assert(AllowedRegs.size() == ForbiddenRegs.size());
+    for (auto I : ForbiddenRegs.set_bits())
+      AllowedRegs.reset(I);
+    if (!AllowedRegs.any())
+      return make_error<Failure>(
+          Twine("no available registers:\ncandidates:\n")
+              .concat(debugString(State.getRegInfo(),
+                                  Op.getRegisterAliasing().sourceBits()))
+              .concat("\nforbidden:\n")
+              .concat(debugString(State.getRegInfo(), ForbiddenRegs)));
+    AssignedValue = MCOperand::createReg(randomBit(AllowedRegs));
+    break;
+  }
+  default:
+    break;
+  }
+  return Error::success();
+}
+
+Error randomizeUnsetVariables(const LLVMState &State,
+                              const BitVector &ForbiddenRegs,
+                              InstructionTemplate &IT) {
   for (const Variable &Var : IT.getInstr().Variables) {
     MCOperand &AssignedValue = IT.getValueFor(Var);
     if (!AssignedValue.isValid())
-      Target.randomizeMCOperand(IT.getInstr(), Var, AssignedValue,
-                                ForbiddenRegs);
+      if (auto Err = randomizeMCOperand(State, IT.getInstr(), Var,
+                                        AssignedValue, ForbiddenRegs))
+        return Err;
   }
+  return Error::success();
 }
 
 } // namespace exegesis

diff  --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
index 70f81f942be4..7e7f6e487e18 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
+++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
@@ -97,9 +97,9 @@ void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
 
 // Assigns a Random Value to all Variables in IT that are still Invalid.
 // Do not use any of the registers in `ForbiddenRegs`.
-void randomizeUnsetVariables(const ExegesisTarget &Target,
-                             const BitVector &ForbiddenRegs,
-                             InstructionTemplate &IT);
+Error randomizeUnsetVariables(const LLVMState &State,
+                              const BitVector &ForbiddenRegs,
+                              InstructionTemplate &IT);
 
 } // namespace exegesis
 } // namespace llvm

diff  --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 40021e2931cb..701ff14be209 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -99,30 +99,6 @@ ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const {
   return std::make_unique<UopsBenchmarkRunner>(State);
 }
 
-void ExegesisTarget::randomizeMCOperand(const Instruction &Instr,
-                                        const Variable &Var,
-                                        MCOperand &AssignedValue,
-                                        const BitVector &ForbiddenRegs) const {
-  const Operand &Op = Instr.getPrimaryOperand(Var);
-  switch (Op.getExplicitOperandInfo().OperandType) {
-  case MCOI::OperandType::OPERAND_IMMEDIATE:
-    // FIXME: explore immediate values too.
-    AssignedValue = MCOperand::createImm(1);
-    break;
-  case MCOI::OperandType::OPERAND_REGISTER: {
-    assert(Op.isReg());
-    auto AllowedRegs = Op.getRegisterAliasing().sourceBits();
-    assert(AllowedRegs.size() == ForbiddenRegs.size());
-    for (auto I : ForbiddenRegs.set_bits())
-      AllowedRegs.reset(I);
-    AssignedValue = MCOperand::createReg(randomBit(AllowedRegs));
-    break;
-  }
-  default:
-    break;
-  }
-}
-
 static_assert(std::is_pod<PfmCountersInfo>::value,
               "We shouldn't have dynamic initialization here");
 const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,

diff  --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index bd4300904105..d9bddc56e824 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -18,6 +18,7 @@
 
 #include "BenchmarkResult.h"
 #include "BenchmarkRunner.h"
+#include "Error.h"
 #include "LlvmState.h"
 #include "SnippetGenerator.h"
 #include "llvm/ADT/Triple.h"
@@ -108,12 +109,15 @@ class ExegesisTarget {
   virtual unsigned getMaxMemoryAccessSize() const { return 0; }
 
   // Assigns a random operand of the right type to variable Var.
-  // The default implementation only handles generic operand types.
-  // The target is responsible for handling any operand
-  // starting from OPERAND_FIRST_TARGET.
-  virtual void randomizeMCOperand(const Instruction &Instr, const Variable &Var,
-                                  MCOperand &AssignedValue,
-                                  const BitVector &ForbiddenRegs) const;
+  // The target is responsible for handling any operand starting from
+  // OPERAND_FIRST_TARGET.
+  virtual Error randomizeTargetMCOperand(const Instruction &Instr,
+                                         const Variable &Var,
+                                         MCOperand &AssignedValue,
+                                         const BitVector &ForbiddenRegs) const {
+    return make_error<Failure>(
+        "targets with target-specific operands should implement this");
+  }
 
   // Returns true if this instruction is supported as a back-to-back
   // instructions.

diff  --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index cea8af0cf69c..a76e590cfa2c 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -566,9 +566,9 @@ class ExegesisX86Target : public ExegesisTarget {
 
   unsigned getMaxMemoryAccessSize() const override { return 64; }
 
-  void randomizeMCOperand(const Instruction &Instr, const Variable &Var,
-                          MCOperand &AssignedValue,
-                          const BitVector &ForbiddenRegs) const override;
+  Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
+                                 MCOperand &AssignedValue,
+                                 const BitVector &ForbiddenRegs) const override;
 
   void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
                           unsigned Offset) const override;
@@ -644,24 +644,25 @@ unsigned ExegesisX86Target::getLoopCounterRegister(const Triple &TT) const {
   return kLoopCounterReg;
 }
 
-void ExegesisX86Target::randomizeMCOperand(
+Error ExegesisX86Target::randomizeTargetMCOperand(
     const Instruction &Instr, const Variable &Var, MCOperand &AssignedValue,
     const BitVector &ForbiddenRegs) const {
-  ExegesisTarget::randomizeMCOperand(Instr, Var, AssignedValue, ForbiddenRegs);
-
   const Operand &Op = Instr.getPrimaryOperand(Var);
   switch (Op.getExplicitOperandInfo().OperandType) {
   case X86::OperandType::OPERAND_ROUNDING_CONTROL:
     AssignedValue =
         MCOperand::createImm(randomIndex(X86::STATIC_ROUNDING::NO_EXC));
-    break;
+    return Error::success();
   case X86::OperandType::OPERAND_COND_CODE:
     AssignedValue =
         MCOperand::createImm(randomIndex(X86::CondCode::LAST_VALID_COND));
-    break;
+    return Error::success();
   default:
     break;
   }
+  return make_error<Failure>(
+      Twine("unimplemented operand type ")
+          .concat(Twine(Op.getExplicitOperandInfo().OperandType)));
 }
 
 void ExegesisX86Target::fillMemoryOperands(InstructionTemplate &IT,

diff  --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
index 808ea34e7437..a833e1e22793 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
@@ -354,6 +354,17 @@ TEST_F(ParallelSnippetGeneratorTest, MemoryUse) {
   EXPECT_EQ(IT.getVariableValues()[5].getReg(), 0u);
 }
 
+TEST_F(ParallelSnippetGeneratorTest, MOV16ms) {
+  const unsigned Opcode = X86::MOV16ms;
+  const Instruction &Instr = State.getIC().getInstr(Opcode);
+  auto Err =
+      Generator.generateConfigurations(Instr, State.getRATC().emptyRegisters())
+          .takeError();
+  EXPECT_TRUE((bool)Err);
+  EXPECT_THAT(toString(std::move(Err)),
+              testing::HasSubstr("no available registers"));
+}
+
 class FakeSnippetGenerator : public SnippetGenerator {
 public:
   FakeSnippetGenerator(const LLVMState &State, const Options &Opts)


        


More information about the llvm-commits mailing list