brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.8 KiB · 3e0b1f4 Raw
547 lines · cpp
1//===-- SnippetGeneratorTest.cpp --------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "../Common/AssemblerUtils.h"10#include "LlvmState.h"11#include "MCInstrDescView.h"12#include "ParallelSnippetGenerator.h"13#include "RegisterAliasing.h"14#include "SerialSnippetGenerator.h"15#include "TestBase.h"16#include "X86InstrInfo.h"17#include "llvm/ADT/SetOperations.h"18 19namespace llvm {20namespace exegesis {21namespace {22 23using testing::AnyOf;24using testing::ElementsAre;25using testing::Gt;26using testing::HasSubstr;27using testing::IsEmpty;28using testing::Not;29using testing::SizeIs;30 31MATCHER(IsInvalid, "") { return !arg.isValid(); }32MATCHER(IsReg, "") { return arg.isReg(); }33 34template <typename SnippetGeneratorT>35class X86SnippetGeneratorTest : public X86TestBase {36protected:37  X86SnippetGeneratorTest() : Generator(State, SnippetGenerator::Options()),38	                      InstrInfo(State.getInstrInfo()) {}39 40  std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) {41    randomGenerator().seed(0); // Initialize seed.42    const Instruction &Instr = State.getIC().getInstr(Opcode);43    auto CodeTemplateOrError = Generator.generateCodeTemplates(44        &Instr, State.getRATC().emptyRegisters());45    EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.46    return std::move(CodeTemplateOrError.get());47  }48 49  SnippetGeneratorT Generator;50  const MCInstrInfo &InstrInfo;51};52 53using X86SerialSnippetGeneratorTest = X86SnippetGeneratorTest<SerialSnippetGenerator>;54 55using X86ParallelSnippetGeneratorTest =56    X86SnippetGeneratorTest<ParallelSnippetGenerator>;57 58TEST_F(X86SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughImplicitReg) {59  // - ADC16i1660  // - Op0 Explicit Use Immediate61  // - Op1 Implicit Def Reg(AX)62  // - Op2 Implicit Def Reg(EFLAGS)63  // - Op3 Implicit Use Reg(AX)64  // - Op4 Implicit Use Reg(EFLAGS)65  // - Var0 [Op0]66  // - hasAliasingImplicitRegisters (execution is always serial)67  // - hasAliasingRegisters68  const unsigned Opcode = X86::ADC16i16;69  EXPECT_THAT(InstrInfo.get(Opcode).implicit_defs()[0], X86::AX);70  EXPECT_THAT(InstrInfo.get(Opcode).implicit_defs()[1], X86::EFLAGS);71  EXPECT_THAT(InstrInfo.get(Opcode).implicit_uses()[0], X86::AX);72  EXPECT_THAT(InstrInfo.get(Opcode).implicit_uses()[1], X86::EFLAGS);73  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);74  ASSERT_THAT(CodeTemplates, SizeIs(1));75  const auto &CT = CodeTemplates[0];76  EXPECT_THAT(CT.Execution, ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS);77  ASSERT_THAT(CT.Instructions, SizeIs(1));78  const InstructionTemplate &IT = CT.Instructions[0];79  EXPECT_THAT(IT.getOpcode(), Opcode);80  ASSERT_THAT(IT.getVariableValues(), SizeIs(1)); // Imm.81  EXPECT_THAT(IT.getVariableValues()[0], IsInvalid()) << "Immediate is not set";82}83 84TEST_F(X86SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughTiedRegs) {85  // - ADD16ri86  // - Op0 Explicit Def RegClass(GR16)87  // - Op1 Explicit Use RegClass(GR16) TiedToOp088  // - Op2 Explicit Use Immediate89  // - Op3 Implicit Def Reg(EFLAGS)90  // - Var0 [Op0,Op1]91  // - Var1 [Op2]92  // - hasTiedRegisters (execution is always serial)93  // - hasAliasingRegisters94  const unsigned Opcode = X86::ADD16ri;95  EXPECT_THAT(InstrInfo.get(Opcode).implicit_defs()[0], X86::EFLAGS);96  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);97  ASSERT_THAT(CodeTemplates, SizeIs(1));98  const auto &CT = CodeTemplates[0];99  EXPECT_THAT(CT.Execution, ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS);100  ASSERT_THAT(CT.Instructions, SizeIs(1));101  const InstructionTemplate &IT = CT.Instructions[0];102  EXPECT_THAT(IT.getOpcode(), Opcode);103  ASSERT_THAT(IT.getVariableValues(), SizeIs(2));104  EXPECT_THAT(IT.getVariableValues()[0], IsInvalid()) << "Operand 1 is not set";105  EXPECT_THAT(IT.getVariableValues()[1], IsInvalid()) << "Operand 2 is not set";106}107 108TEST_F(X86SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughExplicitRegs) {109  // - VXORPSrr110  // - Op0 Explicit Def RegClass(VR128)111  // - Op1 Explicit Use RegClass(VR128)112  // - Op2 Explicit Use RegClass(VR128)113  // - Var0 [Op0]114  // - Var1 [Op1]115  // - Var2 [Op2]116  // - hasAliasingRegisters117  const unsigned Opcode = X86::VXORPSrr;118  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);119  ASSERT_THAT(CodeTemplates, SizeIs(1));120  const auto &CT = CodeTemplates[0];121  EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS);122  ASSERT_THAT(CT.Instructions, SizeIs(1));123  const InstructionTemplate &IT = CT.Instructions[0];124  EXPECT_THAT(IT.getOpcode(), Opcode);125  ASSERT_THAT(IT.getVariableValues(), SizeIs(3));126  EXPECT_THAT(IT.getVariableValues(),127              AnyOf(ElementsAre(IsReg(), IsInvalid(), IsReg()),128                    ElementsAre(IsReg(), IsReg(), IsInvalid())))129      << "Op0 is either set to Op1 or to Op2";130}131 132TEST_F(X86SerialSnippetGeneratorTest,133       ImplicitSelfDependencyThroughExplicitRegsForbidAll) {134  // - VXORPSrr135  // - Op0 Explicit Def RegClass(VR128)136  // - Op1 Explicit Use RegClass(VR128)137  // - Op2 Explicit Use RegClass(VR128)138  // - Var0 [Op0]139  // - Var1 [Op1]140  // - Var2 [Op2]141  // - hasAliasingRegisters142  const unsigned Opcode = X86::VXORPSrr;143  randomGenerator().seed(0); // Initialize seed.144  const Instruction &Instr = State.getIC().getInstr(Opcode);145  auto AllRegisters = State.getRATC().emptyRegisters();146  AllRegisters.flip();147  auto Error =148      Generator.generateCodeTemplates(&Instr, AllRegisters).takeError();149  EXPECT_TRUE((bool)Error);150  consumeError(std::move(Error));151}152 153TEST_F(X86SerialSnippetGeneratorTest,154       ImplicitSelfDependencyThroughExplicitRegsForbidAlmostAll) {155  // - VXORPSrr156  // - Op0 Explicit Def RegClass(VR128)157  // - Op1 Explicit Use RegClass(VR128)158  // - Op2 Explicit Use RegClass(VR128)159  // - Var0 [Op0]160  // - Var1 [Op1]161  // - Var2 [Op2]162  // - hasAliasingRegisters163  const unsigned Opcode = X86::VXORPSrr;164  randomGenerator().seed(0); // Initialize seed.165  const Instruction &Instr = State.getIC().getInstr(Opcode);166  auto ForbiddenRegisters = State.getRATC().emptyRegisters();167  ForbiddenRegisters.flip();168  ForbiddenRegisters.reset(X86::XMM0);169  auto Error = Generator.generateCodeTemplates(&Instr, ForbiddenRegisters);170  EXPECT_FALSE((bool)Error.takeError());171  auto CodeTemplates = std::move(Error.get());172  ASSERT_THAT(CodeTemplates, SizeIs(Gt(0U))) << "Templates are available";173  for (const auto &CT : CodeTemplates) {174    EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS);175    ASSERT_THAT(CT.Instructions, SizeIs(1));176    const InstructionTemplate &IT = CT.Instructions[0];177    EXPECT_THAT(IT.getOpcode(), Opcode);178    ASSERT_THAT(IT.getVariableValues(), SizeIs(3));179    for (const auto &Var : IT.getVariableValues()) {180      if (Var.isReg()) {181        EXPECT_FALSE(ForbiddenRegisters[Var.getReg().id()]);182      }183    }184  }185}186 187TEST_F(X86SerialSnippetGeneratorTest, DependencyThroughOtherOpcode) {188  // - CMP64rr189  // - Op0 Explicit Use RegClass(GR64)190  // - Op1 Explicit Use RegClass(GR64)191  // - Op2 Implicit Def Reg(EFLAGS)192  // - Var0 [Op0]193  // - Var1 [Op1]194  const unsigned Opcode = X86::CMP64rr;195  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);196  ASSERT_THAT(CodeTemplates, SizeIs(Gt(1U))) << "Many templates are available";197  for (const auto &CT : CodeTemplates) {198    EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR);199    ASSERT_THAT(CT.Instructions, SizeIs(2));200    const InstructionTemplate &IT = CT.Instructions[0];201    EXPECT_THAT(IT.getOpcode(), Opcode);202    ASSERT_THAT(IT.getVariableValues(), SizeIs(2));203    EXPECT_THAT(IT.getVariableValues(),204                AnyOf(ElementsAre(IsReg(), IsInvalid()),205                      ElementsAre(IsInvalid(), IsReg())));206    EXPECT_THAT(CT.Instructions[1].getOpcode(), Not(Opcode));207    // TODO: check that the two instructions alias each other.208  }209}210 211TEST_F(X86SerialSnippetGeneratorTest, LAHF) {212  // - LAHF213  // - Op0 Implicit Def Reg(AH)214  // - Op1 Implicit Use Reg(EFLAGS)215  const unsigned Opcode = X86::LAHF;216  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);217  ASSERT_THAT(CodeTemplates, SizeIs(Gt(1U))) << "Many templates are available";218  for (const auto &CT : CodeTemplates) {219    EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR);220    ASSERT_THAT(CT.Instructions, SizeIs(2));221    const InstructionTemplate &IT = CT.Instructions[0];222    EXPECT_THAT(IT.getOpcode(), Opcode);223    ASSERT_THAT(IT.getVariableValues(), SizeIs(0));224  }225}226 227TEST_F(X86SerialSnippetGeneratorTest, VCVTUSI642SDZrrb_Int) {228  // - VCVTUSI642SDZrrb_Int229  // - Op0 Explicit Def RegClass(VR128X)230  // - Op1 Explicit Use RegClass(VR128X)231  // - Op2 Explicit Use STATIC_ROUNDING232  // - Op2 Explicit Use RegClass(GR64)233  // - Op4 Implicit Use Reg(MXSCR)234  const unsigned Opcode = X86::VCVTUSI642SDZrrb_Int;235  const Instruction &Instr = State.getIC().getInstr(Opcode);236  std::vector<BenchmarkCode> Configs;237  auto Error = Generator.generateConfigurations(238      &Instr, Configs, State.getRATC().emptyRegisters());239  ASSERT_FALSE(Error);240  ASSERT_THAT(Configs, SizeIs(1));241  const BenchmarkCode &BC = Configs[0];242  ASSERT_THAT(BC.Key.Instructions, SizeIs(1));243  ASSERT_TRUE(BC.Key.Instructions[0].getOperand(3).isImm());244}245 246TEST_F(X86ParallelSnippetGeneratorTest, SerialInstruction) {247  // - CDQ248  // - Op0 Implicit Def Reg(EAX)249  // - Op1 Implicit Def Reg(EDX)250  // - Op2 Implicit Use Reg(EAX)251  // - hasAliasingImplicitRegisters (execution is always serial)252  // - hasAliasingRegisters253  const unsigned Opcode = X86::CDQ;254  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);255  ASSERT_THAT(CodeTemplates, SizeIs(1));256  const auto &CT = CodeTemplates[0];257  EXPECT_THAT(CT.Info, HasSubstr("serial"));258  EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);259  ASSERT_THAT(CT.Instructions, SizeIs(1));260  const InstructionTemplate &IT = CT.Instructions[0];261  EXPECT_THAT(IT.getOpcode(), Opcode);262  ASSERT_THAT(IT.getVariableValues(), SizeIs(0));263}264 265TEST_F(X86ParallelSnippetGeneratorTest, ReadAfterWrite_CMOV32rr) {266  // CMOV32rr has tied variables, we enumerate the possible values to execute267  // as many in parallel as possible.268 269  // - CMOV32rr270  // - Op0 Explicit Def RegClass(GR32)271  // - Op1 Explicit Use RegClass(GR32) TiedToOp0272  // - Op2 Explicit Use RegClass(GR32)273  // - Op3 Explicit Use Immediate274  // - Op3 Implicit Use Reg(EFLAGS)275  // - Var0 [Op0,Op1]276  // - Var1 [Op2]277  // - hasTiedRegisters (execution is always serial)278  // - hasAliasingRegisters279  const unsigned Opcode = X86::CMOV32rr;280  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);281  ASSERT_THAT(CodeTemplates, SizeIs(2));282  for (const auto &CT : CodeTemplates) {283    EXPECT_THAT(CT.Info, HasSubstr("avoiding Read-After-Write issue"));284    EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);285    ASSERT_GT(CT.Instructions.size(), 1U);286    std::set<MCRegister> AllDefRegisters;287    std::set<MCRegister> AllUseRegisters;288    for (const auto &IT : CT.Instructions) {289      ASSERT_THAT(IT.getVariableValues(), SizeIs(3));290      AllDefRegisters.insert(IT.getVariableValues()[0].getReg());291      AllUseRegisters.insert(IT.getVariableValues()[1].getReg());292    }293    EXPECT_THAT(AllDefRegisters, SizeIs(CT.Instructions.size()))294        << "Each instruction writes to a different register";295    EXPECT_THAT(AllUseRegisters, Not(IsEmpty()))296        << "In total, some other registers are used";297    auto AllDefAndUseRegs = AllUseRegisters;298    llvm::set_intersect(AllDefAndUseRegs, AllDefRegisters); // A := A ^ B299    EXPECT_THAT(AllDefAndUseRegs, IsEmpty())300        << "No instruction uses any register defined by any of the "301           "instructions";302  }303}304 305TEST_F(X86ParallelSnippetGeneratorTest, ReadAfterWrite_VFMADD132PDr) {306  // VFMADD132PDr has tied variables, we enumerate the possible values307  // to execute as many in parallel as possible.308 309  // - VFMADD132PDr310  // - Op0 Explicit Def RegClass(XMM)311  // - Op1 Explicit Use RegClass(XMM) TiedToOp0312  // - Op2 Explicit Use RegClass(XMM)313  // - Op3 Explicit Use RegClass(XMM)314  // - Var0 [Op0,Op1]315  // - Var1 [Op2]316  // - Var2 [Op3]317  // - hasTiedRegisters (execution is always serial)318  // - hasAliasingRegisters319  const unsigned Opcode = X86::VFMADD132PDr;320  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);321  ASSERT_THAT(CodeTemplates, SizeIs(3));322  for (const auto &CT : CodeTemplates) {323    EXPECT_THAT(CT.Info, HasSubstr("avoiding Read-After-Write issue"));324    EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);325    ASSERT_GT(CT.Instructions.size(), 1U);326    std::set<MCRegister> AllDefRegisters;327    std::set<MCRegister> AllUseRegisters;328    for (const auto &IT : CT.Instructions) {329      ASSERT_THAT(IT.getVariableValues(), SizeIs(3));330      AllDefRegisters.insert(IT.getVariableValues()[0].getReg());331      AllUseRegisters.insert(IT.getVariableValues()[1].getReg());332      AllUseRegisters.insert(IT.getVariableValues()[2].getReg());333    }334    EXPECT_THAT(AllDefRegisters, SizeIs(CT.Instructions.size()))335        << "Each instruction writes to a different register";336    EXPECT_THAT(AllUseRegisters, Not(IsEmpty()))337        << "In total, some other registers are used";338    auto AllDefAndUseRegs = AllUseRegisters;339    llvm::set_intersect(AllDefAndUseRegs, AllDefRegisters); // A := A ^ B340    EXPECT_THAT(AllDefAndUseRegs, IsEmpty())341        << "No instruction uses any register defined by any of the "342           "instructions";343  }344}345 346TEST_F(X86ParallelSnippetGeneratorTest, NoTiedVariables) {347  // CMOV_GR32 has no tied variables, we make sure def and use are different348  // from each other.349 350  // - CMOV_GR32351  // - Op0 Explicit Def RegClass(GR32)352  // - Op1 Explicit Use RegClass(GR32)353  // - Op2 Explicit Use RegClass(GR32)354  // - Op3 Explicit Use Immediate355  // - Op4 Implicit Use Reg(EFLAGS)356  // - Var0 [Op0]357  // - Var1 [Op1]358  // - Var2 [Op2]359  // - Var3 [Op3]360  // - hasAliasingRegisters361  const unsigned Opcode = X86::CMOV_GR32;362  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);363  ASSERT_THAT(CodeTemplates, SizeIs(2));364  for (const auto &CT : CodeTemplates) {365    EXPECT_THAT(CT.Info, HasSubstr("no tied variables"));366    EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);367    ASSERT_THAT(CT.Instructions, SizeIs(1));368    const InstructionTemplate &IT = CT.Instructions[0];369    EXPECT_THAT(IT.getOpcode(), Opcode);370    ASSERT_THAT(IT.getVariableValues(), SizeIs(4));371    EXPECT_THAT(IT.getVariableValues()[0].getReg(),372                Not(IT.getVariableValues()[1].getReg()))373        << "Def is different from first Use";374    EXPECT_THAT(IT.getVariableValues()[0].getReg(),375                Not(IT.getVariableValues()[2].getReg()))376        << "Def is different from second Use";377    EXPECT_THAT(IT.getVariableValues()[3], IsInvalid());378  }379}380 381TEST_F(X86ParallelSnippetGeneratorTest, MemoryUse) {382  // Mov32rm reads from memory.383  // - MOV32rm384  // - Op0 Explicit Def RegClass(GR32)385  // - Op1 Explicit Use Memory RegClass(GR8)386  // - Op2 Explicit Use Memory387  // - Op3 Explicit Use Memory RegClass(GRH8)388  // - Op4 Explicit Use Memory389  // - Op5 Explicit Use Memory RegClass(SEGMENT_REG)390  // - Var0 [Op0]391  // - Var1 [Op1]392  // - Var2 [Op2]393  // - Var3 [Op3]394  // - Var4 [Op4]395  // - Var5 [Op5]396  // - hasMemoryOperands397  // - hasAliasingRegisters398  const unsigned Opcode = X86::MOV32rm;399  const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);400  ASSERT_THAT(CodeTemplates, SizeIs(1));401  for (const auto &CT : CodeTemplates) {402    EXPECT_THAT(CT.Info, HasSubstr("no tied variables"));403    EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);404    ASSERT_THAT(CT.Instructions,405                SizeIs(ParallelSnippetGenerator::kMinNumDifferentAddresses));406    const InstructionTemplate &IT = CT.Instructions[0];407    EXPECT_THAT(IT.getOpcode(), Opcode);408    ASSERT_THAT(IT.getVariableValues(), SizeIs(6));409    EXPECT_EQ(IT.getVariableValues()[2].getImm(), 1);410    EXPECT_FALSE(IT.getVariableValues()[3].getReg().isValid());411    EXPECT_EQ(IT.getVariableValues()[4].getImm(), 0);412    EXPECT_FALSE(IT.getVariableValues()[5].getReg().isValid());413  }414}415 416TEST_F(X86ParallelSnippetGeneratorTest, MOV16ms) {417  const unsigned Opcode = X86::MOV16ms;418  const Instruction &Instr = State.getIC().getInstr(Opcode);419  std::vector<BenchmarkCode> Benchmarks;420  auto Err = Generator.generateConfigurations(&Instr, Benchmarks,421                                              State.getRATC().emptyRegisters());422  EXPECT_TRUE((bool)Err);423  EXPECT_THAT(toString(std::move(Err)),424              testing::HasSubstr("no available registers"));425}426 427TEST_F(X86ParallelSnippetGeneratorTest,428       AvoidSerializingThroughImplicitRegisters) {429  // MULX32rr implicitly uses EDX. We should not select that register to avoid430  // serialization.431  const unsigned Opcode = X86::MULX32rr;432  randomGenerator().seed(0); // Initialize seed.433  const Instruction &Instr = State.getIC().getInstr(Opcode);434  // Forbid all registers but RDX/EDX/DX/DH/DL. The only option would be to435  // choose that register, but that would serialize the instruction, so we436  // should be returning an error.437  auto AllRegisters = State.getRATC().emptyRegisters();438  AllRegisters.flip();439  AllRegisters.reset(X86::RDX);440  AllRegisters.reset(X86::EDX);441  AllRegisters.reset(X86::DX);442  AllRegisters.reset(X86::DH);443  AllRegisters.reset(X86::DL);444  auto Err = Generator.generateCodeTemplates(&Instr, AllRegisters);445  EXPECT_FALSE((bool)Err);446  EXPECT_THAT(toString(Err.takeError()),447              testing::HasSubstr("Failed to produce any snippet"));448}449 450class X86FakeSnippetGenerator : public SnippetGenerator {451public:452  X86FakeSnippetGenerator(const LLVMState &State, const Options &Opts)453      : SnippetGenerator(State, Opts) {}454 455  const Instruction &getInstr(unsigned Opcode) {456    return State.getIC().getInstr(Opcode);457  }458 459  InstructionTemplate getInstructionTemplate(unsigned Opcode) {460    return {&getInstr(Opcode)};461  }462 463private:464  Expected<std::vector<CodeTemplate>>465  generateCodeTemplates(InstructionTemplate, const BitVector &) const override {466    return make_error<StringError>("not implemented", inconvertibleErrorCode());467  }468};469 470using X86FakeSnippetGeneratorTest = X86SnippetGeneratorTest<X86FakeSnippetGenerator>;471 472testing::Matcher<const RegisterValue &> IsRegisterValue(unsigned Reg,473                                                        APInt Value) {474  return testing::AllOf(testing::Field(&RegisterValue::Register, Reg),475                        testing::Field(&RegisterValue::Value, Value));476}477 478TEST_F(X86FakeSnippetGeneratorTest, MemoryUse_Movsb) {479  // MOVSB writes to scratch memory register.480  // - MOVSB481  // - Op0 Explicit Use Memory RegClass(GR8)482  // - Op1 Explicit Use Memory RegClass(GR8)483  // - Op2 Explicit Use Memory RegClass(SEGMENT_REG)484  // - Op3 Implicit Def Reg(EDI)485  // - Op4 Implicit Def Reg(ESI)486  // - Op5 Implicit Use Reg(EDI)487  // - Op6 Implicit Use Reg(ESI)488  // - Op7 Implicit Use Reg(DF)489  // - Var0 [Op0]490  // - Var1 [Op1]491  // - Var2 [Op2]492  // - hasMemoryOperands493  // - hasAliasingImplicitRegisters (execution is always serial)494  // - hasAliasingRegisters495  const unsigned Opcode = X86::MOVSB;496  const Instruction &Instr = State.getIC().getInstr(Opcode);497  std::vector<BenchmarkCode> Benchmarks;498  auto Error = Generator.generateConfigurations(499      &Instr, Benchmarks, State.getRATC().emptyRegisters());500  EXPECT_TRUE((bool)Error);501  consumeError(std::move(Error));502}503 504TEST_F(X86FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd16ri) {505  // ADD16ri:506  // explicit def 0       : reg RegClass=GR16507  // explicit use 1       : reg RegClass=GR16 | TIED_TO:0508  // explicit use 2       : imm509  // implicit def         : EFLAGS510  InstructionTemplate IT = Generator.getInstructionTemplate(X86::ADD16ri);511  IT.getValueFor(IT.getInstr().Variables[0]) = MCOperand::createReg(X86::AX);512  std::vector<InstructionTemplate> Snippet;513  Snippet.push_back(std::move(IT));514  const auto RIV = Generator.computeRegisterInitialValues(Snippet);515  EXPECT_THAT(RIV, ElementsAre(IsRegisterValue(X86::AX, APInt())));516}517 518TEST_F(X86FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd64rr) {519  // ADD64rr:520  //  mov64ri rax, 42521  //  add64rr rax, rax, rbx522  // -> only rbx needs defining.523  std::vector<InstructionTemplate> Snippet;524  {525    InstructionTemplate Mov = Generator.getInstructionTemplate(X86::MOV64ri);526    Mov.getValueFor(Mov.getInstr().Variables[0]) =527        MCOperand::createReg(X86::RAX);528    Mov.getValueFor(Mov.getInstr().Variables[1]) = MCOperand::createImm(42);529    Snippet.push_back(std::move(Mov));530  }531  {532    InstructionTemplate Add = Generator.getInstructionTemplate(X86::ADD64rr);533    Add.getValueFor(Add.getInstr().Variables[0]) =534        MCOperand::createReg(X86::RAX);535    Add.getValueFor(Add.getInstr().Variables[1]) =536        MCOperand::createReg(X86::RBX);537    Snippet.push_back(std::move(Add));538  }539 540  const auto RIV = Generator.computeRegisterInitialValues(Snippet);541  EXPECT_THAT(RIV, ElementsAre(IsRegisterValue(X86::RBX, APInt())));542}543 544} // namespace545} // namespace exegesis546} // namespace llvm547