Skip to content

Commit

Permalink
[EVM] Do stackification of instructions in the EVMStackify pass to ha…
Browse files Browse the repository at this point in the history
…ve valid MIR

This change moves the place where normal instructions are replaced with their
'stack' counterparts from the EVMMCInstLower to the EVMStackify pass. This
ensures we have a valid MIR after each pass.
This change also contains some updates in how labels are represented and
resolved in the BE.
  • Loading branch information
PavelKopyl committed Oct 9, 2024
1 parent 876ffb6 commit 3cc01e9
Show file tree
Hide file tree
Showing 20 changed files with 271 additions and 122 deletions.
1 change: 0 additions & 1 deletion llvm/lib/Target/EVM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ add_llvm_target(EVMCodeGen
EVMStackify.cpp
EVMSubtarget.cpp
EVMTargetMachine.cpp
EVMTargetObjectFile.cpp
EVMTargetTransformInfo.cpp

LINK_COMPONENTS
Expand Down
31 changes: 30 additions & 1 deletion llvm/lib/Target/EVM/EVMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,36 @@ class EVMAsmPrinter : public AsmPrinter {

StringRef getPassName() const override { return "EVM Assembly "; }

void SetupMachineFunction(MachineFunction &MF) override;

void emitInstruction(const MachineInstr *MI) override;

void emitFunctionEntryLabel() override;

/// Return true if the basic block has exactly one predecessor and the control
/// transfer mechanism between the predecessor and this block is a
/// fall-through.
bool isBlockOnlyReachableByFallthrough(
const MachineBasicBlock *MBB) const override;
};
} // end of anonymous namespace

void EVMAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
// Unbundle <push_label, jump> bundles.
for (MachineBasicBlock &MBB : MF) {
MachineBasicBlock::instr_iterator I = MBB.instr_begin(),
E = MBB.instr_end();
for (; I != E; ++I) {
if (I->isBundledWithPred()) {
assert(I->isConditionalBranch() || I->isUnconditionalBranch());
I->unbundleFromPred();
}
}
}

AsmPrinter::SetupMachineFunction(MF);
}

void EVMAsmPrinter::emitFunctionEntryLabel() {
AsmPrinter::emitFunctionEntryLabel();

Expand All @@ -70,12 +94,17 @@ void EVMAsmPrinter::emitFunctionEntryLabel() {
void EVMAsmPrinter::emitInstruction(const MachineInstr *MI) {
EVMMCInstLower MCInstLowering(OutContext, *this, VRegMapping,
MF->getRegInfo());

MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);
EmitToStreamer(*OutStreamer, TmpInst);
}

bool EVMAsmPrinter::isBlockOnlyReachableByFallthrough(
const MachineBasicBlock *MBB) const {
// For simplicity, always emit BB labels.
return false;
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeEVMAsmPrinter() {
const RegisterAsmPrinter<EVMAsmPrinter> X(getTheEVMTarget());
}
2 changes: 1 addition & 1 deletion llvm/lib/Target/EVM/EVMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ SDValue EVMTargetLowering::LowerFormalArguments(
fail(DL, DAG, "VarArg is not supported yet");

MachineFunction &MF = DAG.getMachineFunction();
auto *MFI = MF.getInfo<EVMFunctionInfo>();
auto *MFI = MF.getInfo<EVMMachineFunctionInfo>();

// Set up the incoming ARGUMENTS value, which serves to represent the liveness
// of the incoming values before they're represented by virtual registers.
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/EVM/EVMInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "EVMInstrInfo.h"
#include "EVMMachineFunctionInfo.h"
#include "MCTargetDesc/EVMMCTargetDesc.h"
using namespace llvm;

Expand Down Expand Up @@ -65,6 +66,12 @@ bool EVMInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
FBB = nullptr;
Cond.clear();

const auto *MFI = MBB.getParent()->getInfo<EVMMachineFunctionInfo>();
if (MFI->getIsStackified()) {
LLVM_DEBUG(dbgs() << "Can't analyze terminators in stackified code");
return true;
}

// Iterate backwards and analyze all terminators.
MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend();
while (I != E) {
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Target/EVM/EVMInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ foreach I = {1-16} in {

defm PUSH0 : I<(outs), (ins), [], "PUSH0", "", 0x5F, 2>;

def PUSH8_LABEL : NI<(outs), (ins jmptarget:$dst), [], false, "", 0, 0> {
def PUSH_LABEL : NI<(outs), (ins jmptarget:$dst), [], false, "", 0, 0> {
let isCodeGenOnly = 1;
}

Expand Down Expand Up @@ -1122,7 +1122,7 @@ def PUSH32_S : NI<(outs), (ins i256imm:$imm), [], true, "PUSH32 $imm",
}

// Pseudo instructions for linkage
let isCodeGenOnly = 1 in
defm DATA
: I<(outs GPR:$dst), (ins jmptarget:$reloc), [], "",
"", 0, 0>;
let isCodeGenOnly = 1, BaseName = "DATA" in {
def DATA : NI<(outs GPR:$dst), (ins jmptarget:$reloc), [], false, "", 0, 0>;
def DATA_S : NI<(outs), (ins jmptarget:$reloc), [], true, "", 0, 0>;
}
38 changes: 14 additions & 24 deletions llvm/lib/Target/EVM/EVMMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,23 @@ using namespace llvm;

extern cl::opt<bool> EVMKeepRegisters;

static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI) {
// Remove all uses of stackified registers to bring the instruction format
// into its final stack form used throughout MC, and transition opcodes to
// their _S variant.
// Stackify instruction that were not stackified before.
// Only two instructions need to be stackified here: PUSH_LABEL and DATA_S,
static void stackifyInstruction(const MachineInstr *MI, MCInst &OutMI) {
if (MI->isDebugInstr() || MI->isLabel() || MI->isInlineAsm())
return;

// Transform 'register' instruction to 'stack' one.
unsigned RegOpcode = OutMI.getOpcode();
if (RegOpcode == EVM::PUSH8_LABEL) {
// Replace PUSH8_LABEL with PUSH8_S opcode.
OutMI.setOpcode(EVM::PUSH8_S);
} else {
unsigned StackOpcode = EVM::getStackOpcode(RegOpcode);
OutMI.setOpcode(StackOpcode);
}
// Check there are no register operands.
assert(std::all_of(OutMI.begin(), OutMI.end(),
[](const MCOperand &MO) { return !MO.isReg(); }));

// Remove register operands.
for (auto I = OutMI.getNumOperands(); I; --I) {
auto &MO = OutMI.getOperand(I - 1);
if (MO.isReg()) {
OutMI.erase(&MO);
}
}

if (RegOpcode == EVM::DATA)
// Set up final opcodes for the following codegen-only instructions.
unsigned Opcode = OutMI.getOpcode();
if (Opcode == EVM::PUSH_LABEL || Opcode == EVM::DATA_S)
OutMI.setOpcode(EVM::PUSH4_S);

// Check that all the instructions are in the 'stack' form.
assert(EVM::getRegisterOpcode(OutMI.getOpcode()));
}

MCSymbol *
Expand Down Expand Up @@ -136,7 +126,7 @@ void EVMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) {
case MachineOperand::MO_MCSymbol: {
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VariantKind::VK_None;
unsigned Opc = MI->getOpcode();
if (Opc == EVM::DATA)
if (Opc == EVM::DATA_S)
Kind = MCSymbolRefExpr::VariantKind::VK_EVM_DATA;

MCOp = MCOperand::createExpr(
Expand All @@ -156,7 +146,7 @@ void EVMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) {
OutMI.addOperand(MCOp);
}
if (!EVMKeepRegisters)
removeRegisterOperands(MI, OutMI);
stackifyInstruction(MI, OutMI);
else if (Desc.variadicOpsAreDefs())
OutMI.insert(OutMI.begin(), MCOperand::createImm(MI->getNumExplicitDefs()));
}
Expand Down
27 changes: 21 additions & 6 deletions llvm/lib/Target/EVM/EVMMachineFunctionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,26 @@
#include "EVMMachineFunctionInfo.h"
using namespace llvm;

EVMFunctionInfo::~EVMFunctionInfo() = default; // anchor.
EVMMachineFunctionInfo::~EVMMachineFunctionInfo() = default;

MachineFunctionInfo *
EVMFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *>
&Src2DstMBB) const {
return DestMF.cloneInfo<EVMFunctionInfo>(*this);
MachineFunctionInfo *EVMMachineFunctionInfo::clone(
BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
const {
return DestMF.cloneInfo<EVMMachineFunctionInfo>(*this);
}

yaml::EVMMachineFunctionInfo::~EVMMachineFunctionInfo() = default;

yaml::EVMMachineFunctionInfo::EVMMachineFunctionInfo(
const llvm::EVMMachineFunctionInfo &MFI)
: IsStackified(MFI.getIsStackified()) {}

void yaml::EVMMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
MappingTraits<EVMMachineFunctionInfo>::mapping(YamlIO, *this);
}

void EVMMachineFunctionInfo::initializeBaseYamlFields(
const yaml::EVMMachineFunctionInfo &YamlMFI) {
IsStackified = YamlMFI.IsStackified;
}
40 changes: 35 additions & 5 deletions llvm/lib/Target/EVM/EVMMachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,33 @@
#include "MCTargetDesc/EVMMCTargetDesc.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCSymbolWasm.h"

namespace llvm {

class EVMMachineFunctionInfo;

namespace yaml {

struct EVMMachineFunctionInfo final : public yaml::MachineFunctionInfo {
bool IsStackified = false;

EVMMachineFunctionInfo() = default;
explicit EVMMachineFunctionInfo(const llvm::EVMMachineFunctionInfo &MFI);
~EVMMachineFunctionInfo() override;

void mappingImpl(yaml::IO &YamlIO) override;
};

template <> struct MappingTraits<EVMMachineFunctionInfo> {
static void mapping(IO &YamlIO, EVMMachineFunctionInfo &MFI) {
YamlIO.mapOptional("isStackified", MFI.IsStackified, false);
}
};
} // end namespace yaml

/// This class is derived from MachineFunctionInfo and contains private
/// EVM-specific information for each MachineFunction.
class EVMFunctionInfo final : public MachineFunctionInfo {
class EVMMachineFunctionInfo final : public MachineFunctionInfo {
/// A mapping from CodeGen vreg index to a boolean value indicating whether
/// the given register is considered to be "stackified", meaning it has been
/// determined or made to meet the stack requirements:
Expand All @@ -34,16 +54,21 @@ class EVMFunctionInfo final : public MachineFunctionInfo {
/// Number of parameters. Their type doesn't matter as it always is i256.
unsigned NumberOfParameters = 0;

/// If the MF's instructions are in 'stack' form.
bool IsStackified = false;

public:
explicit EVMFunctionInfo(MachineFunction &MF) {}
EVMFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {}
~EVMFunctionInfo() override;
explicit EVMMachineFunctionInfo(MachineFunction &MF) {}
EVMMachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {}
~EVMMachineFunctionInfo() override;

MachineFunctionInfo *
clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
const override;

void initializeBaseYamlFields(const yaml::EVMMachineFunctionInfo &YamlMFI);

void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) {
assert(MRI.getUniqueVRegDef(VReg));
auto I = Register::virtReg2Index(VReg);
Expand Down Expand Up @@ -72,7 +97,12 @@ class EVMFunctionInfo final : public MachineFunctionInfo {
unsigned getNumParams() const {
return NumberOfParameters;
}

void setIsStackified(bool Val = true) { IsStackified = Val; }

bool getIsStackified() const { return IsStackified; }
};

} // end namespace llvm

#endif // LLVM_LIB_TARGET_EVM_EVMMACHINEFUNCTIONINFO_H
2 changes: 1 addition & 1 deletion llvm/lib/Target/EVM/EVMRegColoring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bool EVMRegColoring::runOnMachineFunction(MachineFunction &MF) {
LiveIntervals *Liveness = &getAnalysis<LiveIntervals>();
const MachineBlockFrequencyInfo *MBFI =
&getAnalysis<MachineBlockFrequencyInfo>();
EVMFunctionInfo &MFI = *MF.getInfo<EVMFunctionInfo>();
EVMMachineFunctionInfo &MFI = *MF.getInfo<EVMMachineFunctionInfo>();

// Gather all register intervals into a list and sort them.
unsigned NumVRegs = MRI->getNumVirtRegs();
Expand Down
11 changes: 6 additions & 5 deletions llvm/lib/Target/EVM/EVMSingleUseExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ static bool shouldRematerialize(const MachineInstr &Def,
// TODO: Compute memory dependencies in a way that uses AliasAnalysis to be
// more precise.
static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use,
const MachineInstr *Insert, const EVMFunctionInfo &MFI,
const MachineInstr *Insert,
const EVMMachineFunctionInfo &MFI,
const MachineRegisterInfo &MRI) {
const MachineInstr *DefI = Def->getParent();
const MachineInstr *UseI = Use->getParent();
Expand Down Expand Up @@ -390,7 +391,7 @@ static void shrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
MachineInstr *Def, MachineBasicBlock &MBB,
MachineInstr *Insert, LiveIntervals &LIS,
EVMFunctionInfo &MFI,
EVMMachineFunctionInfo &MFI,
MachineRegisterInfo &MRI) {
LLVM_DEBUG(dbgs() << "Move for single use: "; Def->dump());

Expand Down Expand Up @@ -430,8 +431,8 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
static MachineInstr *rematerializeCheapDef(
unsigned Reg, MachineOperand &Op, MachineInstr &Def, MachineBasicBlock &MBB,
MachineBasicBlock::instr_iterator Insert, LiveIntervals &LIS,
EVMFunctionInfo &MFI, MachineRegisterInfo &MRI, const EVMInstrInfo *TII,
const EVMRegisterInfo *TRI) {
EVMMachineFunctionInfo &MFI, MachineRegisterInfo &MRI,
const EVMInstrInfo *TII, const EVMRegisterInfo *TRI) {
LLVM_DEBUG(dbgs() << "Rematerializing cheap def: "; Def.dump());
LLVM_DEBUG(dbgs() << " - for use in "; Op.getParent()->dump());

Expand Down Expand Up @@ -593,7 +594,7 @@ bool EVMSingleUseExpression::runOnMachineFunction(MachineFunction &MF) {

bool Changed = false;
MachineRegisterInfo &MRI = MF.getRegInfo();
EVMFunctionInfo &MFI = *MF.getInfo<EVMFunctionInfo>();
EVMMachineFunctionInfo &MFI = *MF.getInfo<EVMMachineFunctionInfo>();
const auto *TII = MF.getSubtarget<EVMSubtarget>().getInstrInfo();
const auto *TRI = MF.getSubtarget<EVMSubtarget>().getRegisterInfo();
auto &MDT = getAnalysis<MachineDominatorTree>();
Expand Down
Loading

0 comments on commit 3cc01e9

Please sign in to comment.