CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
145 lines
5.2 KiB
C++
145 lines
5.2 KiB
C++
//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
// The PowerPC ExegesisTarget.
|
|
//===----------------------------------------------------------------------===//
|
|
#include "../Target.h"
|
|
#include "PPC.h"
|
|
#include "PPCRegisterInfo.h"
|
|
|
|
#define GET_AVAILABLE_OPCODE_CHECKER
|
|
#include "PPCGenInstrInfo.inc"
|
|
|
|
namespace llvm {
|
|
namespace exegesis {
|
|
|
|
// Helper to fill a memory operand with a value.
|
|
static void setMemOp(InstructionTemplate &IT, int OpIdx,
|
|
const MCOperand &OpVal) {
|
|
const auto Op = IT.getInstr().Operands[OpIdx];
|
|
assert(Op.isExplicit() && "invalid memory pattern");
|
|
IT.getValueFor(Op) = OpVal;
|
|
}
|
|
|
|
#include "PPCGenExegesis.inc"
|
|
|
|
namespace {
|
|
class ExegesisPowerPCTarget : public ExegesisTarget {
|
|
public:
|
|
ExegesisPowerPCTarget()
|
|
: ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}
|
|
|
|
private:
|
|
std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, MCRegister Reg,
|
|
const APInt &Value) const override;
|
|
bool matchesArch(Triple::ArchType Arch) const override {
|
|
return Arch == Triple::ppc64le;
|
|
}
|
|
MCRegister getScratchMemoryRegister(const Triple &) const override;
|
|
void fillMemoryOperands(InstructionTemplate &IT, MCRegister Reg,
|
|
unsigned Offset) const override;
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
|
|
switch (RegBitWidth) {
|
|
case 32:
|
|
return PPC::LI;
|
|
case 64:
|
|
return PPC::LI8;
|
|
}
|
|
llvm_unreachable("Invalid Value Width");
|
|
}
|
|
|
|
// Generates instruction to load an immediate value into a register.
|
|
static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth,
|
|
const APInt &Value) {
|
|
if (Value.getBitWidth() > RegBitWidth)
|
|
llvm_unreachable("Value must fit in the Register");
|
|
// We don't really care the value in reg, ignore the 16 bit
|
|
// restriction for now.
|
|
// TODO: make sure we get the exact value in reg if needed.
|
|
return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
|
|
.addReg(Reg)
|
|
.addImm(Value.getZExtValue());
|
|
}
|
|
|
|
MCRegister
|
|
ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {
|
|
// R13 is reserved as Thread Pointer, we won't use threading in benchmark, so
|
|
// use it as scratch memory register
|
|
return TT.isArch64Bit() ? PPC::X13 : PPC::R13;
|
|
}
|
|
|
|
void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
|
|
MCRegister Reg,
|
|
unsigned Offset) const {
|
|
int MemOpIdx = 0;
|
|
if (IT.getInstr().hasTiedRegisters())
|
|
MemOpIdx = 1;
|
|
int DispOpIdx = MemOpIdx + 1;
|
|
const auto DispOp = IT.getInstr().Operands[DispOpIdx];
|
|
if (DispOp.isReg())
|
|
// We don't really care about the real address in snippets,
|
|
// So hardcode X1 for X-form Memory Operations for simplicity.
|
|
// TODO: materialize the offset into a reggister
|
|
setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));
|
|
else
|
|
setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp
|
|
setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg
|
|
}
|
|
|
|
std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
|
|
MCRegister Reg,
|
|
const APInt &Value) const {
|
|
// X11 is optional use in function linkage, should be the least used one
|
|
// Use it as scratch reg to load immediate.
|
|
unsigned ScratchImmReg = PPC::X11;
|
|
|
|
if (PPC::GPRCRegClass.contains(Reg))
|
|
return {loadImmediate(Reg, 32, Value)};
|
|
if (PPC::G8RCRegClass.contains(Reg))
|
|
return {loadImmediate(Reg, 64, Value)};
|
|
if (PPC::F4RCRegClass.contains(Reg))
|
|
return {loadImmediate(ScratchImmReg, 64, Value),
|
|
MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
|
|
// We don't care the real value in reg, so set 64 bits or duplicate 64 bits
|
|
// for simplicity.
|
|
// TODO: update these if we need a accurate 128 values in registers.
|
|
if (PPC::VRRCRegClass.contains(Reg))
|
|
return {loadImmediate(ScratchImmReg, 64, Value),
|
|
MCInstBuilder(PPC::MTVRD).addReg(Reg).addReg(ScratchImmReg)};
|
|
if (PPC::VSRCRegClass.contains(Reg))
|
|
return {loadImmediate(ScratchImmReg, 64, Value),
|
|
MCInstBuilder(PPC::MTVSRDD)
|
|
.addReg(Reg)
|
|
.addReg(ScratchImmReg)
|
|
.addReg(ScratchImmReg)};
|
|
if (PPC::VFRCRegClass.contains(Reg))
|
|
return {loadImmediate(ScratchImmReg, 64, Value),
|
|
MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
|
|
// SPE not supported yet
|
|
if (PPC::SPERCRegClass.contains(Reg)) {
|
|
errs() << "Unsupported SPE Reg:" << Reg << "\n";
|
|
return {};
|
|
}
|
|
errs() << "setRegTo is not implemented, results will be unreliable:" << Reg
|
|
<< "\n";
|
|
return {};
|
|
}
|
|
|
|
static ExegesisTarget *getTheExegesisPowerPCTarget() {
|
|
static ExegesisPowerPCTarget Target;
|
|
return &Target;
|
|
}
|
|
|
|
void InitializePowerPCExegesisTarget() {
|
|
ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());
|
|
}
|
|
|
|
} // namespace exegesis
|
|
} // namespace llvm
|