[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