diff --git a/llvm/lib/Target/EVM/EVMAssembly.cpp b/llvm/lib/Target/EVM/EVMAssembly.cpp index ef60698acfcf..21a7020e284c 100644 --- a/llvm/lib/Target/EVM/EVMAssembly.cpp +++ b/llvm/lib/Target/EVM/EVMAssembly.cpp @@ -106,10 +106,10 @@ void EVMAssembly::appendConstant(const APInt &Val) { CurMIIt = std::next(CurMIIt); } -void EVMAssembly::appendSymbol(MCSymbol *Symbol) { +void EVMAssembly::appendSymbol(MCSymbol *Symbol, unsigned Opcode) { // This is codegen-only instruction, that will be converted into PUSH4. CurMIIt = - BuildMI(*CurMBB, CurMIIt, DebugLoc(), TII->get(EVM::DATA)).addSym(Symbol); + BuildMI(*CurMBB, CurMIIt, DebugLoc(), TII->get(Opcode)).addSym(Symbol); StackHeight += 1; AssemblyInstrs.insert(&*CurMIIt); LLVM_DEBUG(dumpInst(&*CurMIIt)); diff --git a/llvm/lib/Target/EVM/EVMAssembly.h b/llvm/lib/Target/EVM/EVMAssembly.h index fa2d30d5a9cb..8f40acfebe9e 100644 --- a/llvm/lib/Target/EVM/EVMAssembly.h +++ b/llvm/lib/Target/EVM/EVMAssembly.h @@ -62,7 +62,7 @@ class EVMAssembly { void appendConstant(const APInt &Val); - void appendSymbol(MCSymbol *Symbol); + void appendSymbol(MCSymbol *Symbol, unsigned Opcode); void appendConstant(uint64_t Val); diff --git a/llvm/lib/Target/EVM/EVMControlFlowGraph.h b/llvm/lib/Target/EVM/EVMControlFlowGraph.h index 2f76f93455d4..86b7e2720560 100644 --- a/llvm/lib/Target/EVM/EVMControlFlowGraph.h +++ b/llvm/lib/Target/EVM/EVMControlFlowGraph.h @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/Register.h" #include "llvm/MC/MCSymbol.h" @@ -103,11 +104,17 @@ struct LiteralSlot { /// A slot containing a MCSymbol. struct SymbolSlot { MCSymbol *Symbol; + const MachineInstr *MI = nullptr; static constexpr bool canBeFreelyGenerated = true; - bool operator==(SymbolSlot const &Rhs) const { return Symbol == Rhs.Symbol; } + bool operator==(SymbolSlot const &Rhs) const { + return Symbol == Rhs.Symbol && MI->getOpcode() == Rhs.MI->getOpcode(); + } - bool operator<(SymbolSlot const &Rhs) const { return Symbol < Rhs.Symbol; } + bool operator<(SymbolSlot const &Rhs) const { + return std::make_pair(Symbol, MI->getOpcode()) < + std::make_pair(Rhs.Symbol, Rhs.MI->getOpcode()); + } }; /// A slot containing the index-th return value of a previous call. diff --git a/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp b/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp index 4aaa75841920..cb072b24de5c 100644 --- a/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp +++ b/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp @@ -188,11 +188,10 @@ void ControlFlowGraphBuilder::collectInstrOperands(const MachineInstr &MI, Stack *Output) const { if (Input) { for (const auto &MO : reverse(MI.explicit_uses())) { - if (!MO.isReg()) { - if (MO.isMCSymbol()) - Input->push_back(SymbolSlot{MO.getMCSymbol()}); + // All the non-register operands are handled in instruction specific + // handlers. + if (!MO.isReg()) continue; - } const Register Reg = MO.getReg(); // SP is not used anyhow. @@ -234,7 +233,8 @@ void ControlFlowGraphBuilder::handleMachineInstr(MachineInstr &MI) { // Branch instructions are handled separately. return; case EVM::COPY_I256: - case EVM::DATA: + case EVM::DATASIZE: + case EVM::DATAOFFSET: // The copy/data instructions just represent an assignment. This case is // handled below. break; @@ -275,10 +275,11 @@ void ControlFlowGraphBuilder::handleMachineInstr(MachineInstr &MI) { Output.push_back(VariableSlot{DefReg}); Variables.push_back(VariableSlot{DefReg}); } break; - case EVM::DATA: { + case EVM::DATASIZE: + case EVM::DATAOFFSET: { const Register DefReg = MI.getOperand(0).getReg(); MCSymbol *Sym = MI.getOperand(1).getMCSymbol(); - Input.push_back(SymbolSlot{Sym}); + Input.push_back(SymbolSlot{Sym, &MI}); Output.push_back(VariableSlot{DefReg}); Variables.push_back(VariableSlot{DefReg}); } break; diff --git a/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp b/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp index 1b168bb1ab7a..3025675257f2 100644 --- a/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp +++ b/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp @@ -221,7 +221,8 @@ void EVMOptimizedCodeTransform::createStackLayout(Stack TargetStack) { Assembly.appendConstant(Literal.Value); }, [&](SymbolSlot const &Symbol) { - Assembly.appendSymbol(Symbol.Symbol); + Assembly.appendSymbol(Symbol.Symbol, + Symbol.MI->getOpcode()); }, [&](FunctionReturnLabelSlot const &) { llvm_unreachable("Cannot produce function return label"); diff --git a/llvm/lib/Target/EVM/EVMStackDebug.cpp b/llvm/lib/Target/EVM/EVMStackDebug.cpp index 773ae26af37b..edffdadacf60 100644 --- a/llvm/lib/Target/EVM/EVMStackDebug.cpp +++ b/llvm/lib/Target/EVM/EVMStackDebug.cpp @@ -20,10 +20,10 @@ using namespace llvm; -static StringRef getInstName(const MachineInstr *MI) { +static std::string getInstName(const MachineInstr *MI) { const MachineFunction *MF = MI->getParent()->getParent(); const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); - return TII->getName(MI->getOpcode()); + return TII->getName(MI->getOpcode()).str(); } const Function *llvm::getCalledFunction(const MachineInstr &MI) { @@ -66,7 +66,8 @@ std::string llvm::stackSlotToString(const StackSlot &Slot) { return std::string(S); }, [](const SymbolSlot &Symbol) -> std::string { - return std::string(Symbol.Symbol->getName()); + return getInstName(Symbol.MI) + ":" + + std::string(Symbol.Symbol->getName()); }, [](const TemporarySlot &Tmp) -> std::string { SmallString<128> S; @@ -195,7 +196,7 @@ void StackLayoutPrinter::operator()(CFG::FunctionInfo const &Info) { for (const StackSlot &ParamSlot : Info.Parameters) { if (const auto *Slot = std::get_if(&ParamSlot)) OS << printReg(Slot->VirtualReg, nullptr, 0, nullptr) << ' '; - else if (const auto *Slot = std::get_if(&ParamSlot)) + else if (std::holds_alternative(&ParamSlot)) OS << "[unused param] "; else llvm_unreachable("Unexpected stack slot"); diff --git a/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp b/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp index 9b2f1dd0625e..0ef1a508da2c 100644 --- a/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp +++ b/llvm/lib/Target/EVM/EVMStackLayoutGenerator.cpp @@ -248,8 +248,7 @@ Stack StackLayoutGenerator::propagateStackThroughOperation( Stack ExitStack, const CFG::Operation &Operation, bool AggressiveStackCompression) { // Enable aggressive stack compression for recursive calls. - if (auto const *functionCall = - std::get_if(&Operation.Operation)) + if (std::holds_alternative(&Operation.Operation)) // TODO: compress stack for recursive functions. AggressiveStackCompression = false; diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/evm-basic.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/evm-basic.ll.expected index 4b6359646f18..4a4f1e007b5d 100644 --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/evm-basic.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/evm-basic.ll.expected @@ -5,17 +5,12 @@ define i256 @swap_second_no_junk(i256 %a1, i256 %a2, i256 %a3, i256 %a4) nounwin ; CHECK-LABEL: swap_second_no_junk: ; CHECK: ; %bb.0: ; CHECK-NEXT: JUMPDEST -; CHECK-NEXT: DUP2 -; CHECK-NEXT: DUP6 -; CHECK-NEXT: SUB -; CHECK-NEXT: SWAP5 -; CHECK-NEXT: POP -; CHECK-NEXT: DUP1 -; CHECK-NEXT: SWAP4 -; CHECK-NEXT: POP -; CHECK-NEXT: POP +; CHECK-NEXT: SWAP3 +; CHECK-NEXT: SWAP2 ; CHECK-NEXT: POP ; CHECK-NEXT: POP +; CHECK-NEXT: SUB +; CHECK-NEXT: SWAP1 ; CHECK-NEXT: JUMP %x1 = sub i256 %a4, %a1 ret i256 %x1