From 6b77481d598d89c0717ee4259de46a43e97342a0 Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Tue, 21 Jan 2020 11:58:51 +0100 Subject: [PATCH] [llvm-exegesis] Fix support for LEA64_32r. Summary: Add unit test to show the issue: We must select an *aliasing* output register, not the exact register. Reviewers: gchatelet Subscribers: tschuett, mstojanovic, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D73095 --- .../llvm-exegesis/X86/latency-LEA64_32r.s | 16 +++++++ tools/llvm-exegesis/lib/X86/Target.cpp | 46 ++++++++++--------- 2 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 test/tools/llvm-exegesis/X86/latency-LEA64_32r.s diff --git a/test/tools/llvm-exegesis/X86/latency-LEA64_32r.s b/test/tools/llvm-exegesis/X86/latency-LEA64_32r.s new file mode 100644 index 00000000000..40b6db9afe8 --- /dev/null +++ b/test/tools/llvm-exegesis/X86/latency-LEA64_32r.s @@ -0,0 +1,16 @@ +# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64_32r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s +# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64_32r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s + +CHECK: --- +CHECK-NEXT: mode: latency +CHECK-NEXT: key: +CHECK-NEXT: instructions: +CHECK-NEXT: LEA64_32r +CHECK-NEXT: config: '0(%[[REG1:[A-Z0-9]+]], %[[REG1]], 1)' + +CHECK: --- +CHECK-NEXT: mode: latency +CHECK-NEXT: key: +CHECK-NEXT: instructions: +CHECK-NEXT: LEA64_32r +CHECK-NEXT: config: '42(%[[REG2:[A-Z0-9]+]], %[[REG2]], 1)' diff --git a/tools/llvm-exegesis/lib/X86/Target.cpp b/tools/llvm-exegesis/lib/X86/Target.cpp index 47b14f2e7c1..c739eae651e 100644 --- a/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/tools/llvm-exegesis/lib/X86/Target.cpp @@ -188,7 +188,8 @@ static void setMemOp(InstructionTemplate &IT, int OpIdx, static Expected> generateLEATemplatesCommon( const Instruction &Instr, const BitVector &ForbiddenRegisters, const LLVMState &State, const SnippetGenerator::Options &Opts, - std::function GetDestReg) { + std::function + RestrictDestRegs) { assert(Instr.Operands.size() == 6 && "invalid LEA"); assert(X86II::getMemoryOperandNo(Instr.Description.TSFlags) == 1 && "invalid LEA"); @@ -222,8 +223,15 @@ static Expected> generateLEATemplatesCommon( // SegmentReg must be 0 for LEA. setMemOp(IT, 5, MCOperand::createReg(0)); - // Output reg is selected by the caller. - setMemOp(IT, 0, MCOperand::createReg(GetDestReg(BaseReg, IndexReg))); + // Output reg candidates are selected by the caller. + auto PossibleDestRegsNow = PossibleDestRegs; + RestrictDestRegs(BaseReg, IndexReg, PossibleDestRegsNow); + assert(PossibleDestRegsNow.set_bits().begin() != + PossibleDestRegsNow.set_bits().end() && + "no remaining registers"); + setMemOp( + IT, 0, + MCOperand::createReg(*PossibleDestRegsNow.set_bits().begin())); CodeTemplate CT; CT.Instructions.push_back(std::move(IT)); @@ -261,12 +269,15 @@ X86SerialSnippetGenerator::generateCodeTemplates( // LEA gets special attention. const auto Opcode = Instr.Description.getOpcode(); if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r) { - return generateLEATemplatesCommon(Instr, ForbiddenRegisters, State, Opts, - [](unsigned BaseReg, unsigned IndexReg) { - // We just select the same base and - // output register. - return BaseReg; - }); + return generateLEATemplatesCommon( + Instr, ForbiddenRegisters, State, Opts, + [this](unsigned BaseReg, unsigned IndexReg, + BitVector &CandidateDestRegs) { + // We just select a destination register that aliases the base + // register. + CandidateDestRegs &= + State.getRATC().getRegister(BaseReg).aliasedBits(); + }); } switch (getX86FPFlags(Instr)) { @@ -312,22 +323,15 @@ X86ParallelSnippetGenerator::generateCodeTemplates( // LEA gets special attention. const auto Opcode = Instr.Description.getOpcode(); if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r) { - // Any destination register that is not used for adddressing is fine. - auto PossibleDestRegs = - Instr.Operands[0].getRegisterAliasing().sourceBits(); - remove(PossibleDestRegs, ForbiddenRegisters); return generateLEATemplatesCommon( Instr, ForbiddenRegisters, State, Opts, - [this, &PossibleDestRegs](unsigned BaseReg, unsigned IndexReg) { - auto PossibleDestRegsNow = PossibleDestRegs; - remove(PossibleDestRegsNow, + [this](unsigned BaseReg, unsigned IndexReg, + BitVector &CandidateDestRegs) { + // Any destination register that is not used for addressing is fine. + remove(CandidateDestRegs, State.getRATC().getRegister(BaseReg).aliasedBits()); - remove(PossibleDestRegsNow, + remove(CandidateDestRegs, State.getRATC().getRegister(IndexReg).aliasedBits()); - assert(PossibleDestRegsNow.set_bits().begin() != - PossibleDestRegsNow.set_bits().end() && - "no remaining registers"); - return *PossibleDestRegsNow.set_bits().begin(); }); }