From ab5456fa2bd52a2bde24620127af48918e1c2b85 Mon Sep 17 00:00:00 2001 From: Pavel Kopyl Date: Sat, 26 Oct 2024 00:11:19 +0200 Subject: [PATCH] [EVM] Handle unused function parameters --- llvm/lib/Target/EVM/EVMControlFlowGraph.h | 2 +- .../Target/EVM/EVMControlFlowGraphBuilder.cpp | 18 ++++++- .../Target/EVM/EVMOptimizedCodeTransform.cpp | 2 + llvm/lib/Target/EVM/EVMStackDebug.cpp | 10 +++- llvm/lib/Target/EVM/EVMTargetMachine.cpp | 9 ++-- .../CodeGen/EVM/unused_function_arguments.ll | 52 +++++++++++++++++++ 6 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 llvm/test/CodeGen/EVM/unused_function_arguments.ll diff --git a/llvm/lib/Target/EVM/EVMControlFlowGraph.h b/llvm/lib/Target/EVM/EVMControlFlowGraph.h index b31a8418fdfd..86bfb57eff5b 100644 --- a/llvm/lib/Target/EVM/EVMControlFlowGraph.h +++ b/llvm/lib/Target/EVM/EVMControlFlowGraph.h @@ -246,7 +246,7 @@ struct CFG { struct FunctionInfo { MachineFunction *MF = nullptr; BasicBlock *Entry = nullptr; - std::vector Parameters; + std::vector Parameters; std::vector Exits; bool CanContinue = true; }; diff --git a/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp b/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp index d28765979a35..f84628db7af5 100644 --- a/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp +++ b/llvm/lib/Target/EVM/EVMControlFlowGraphBuilder.cpp @@ -15,6 +15,7 @@ #include "EVMControlFlowGraphBuilder.h" #include "EVMHelperUtilities.h" +#include "EVMMachineFunctionInfo.h" #include "EVMStackDebug.h" #include "EVMSubtarget.h" #include "MCTargetDesc/EVMMCTargetDesc.h" @@ -123,6 +124,18 @@ std::unique_ptr ControlFlowGraphBuilder::build(MachineFunction &MF, if (F.hasFnAttribute(Attribute::NoReturn)) Result->FuncInfo.CanContinue = false; + // Handle function parameters + auto *MFI = MF.getInfo(); + Result->FuncInfo.Parameters = + std::vector(MFI->getNumParams(), JunkSlot{}); + for (const MachineInstr &MI : MF.front()) { + if (MI.getOpcode() == EVM::ARGUMENT) { + int64_t ArgIdx = MI.getOperand(1).getImm(); + Result->FuncInfo.Parameters[ArgIdx] = + VariableSlot{MI.getOperand(0).getReg()}; + } + } + for (MachineBasicBlock &MBB : MF) Builder.handleBasicBlock(MBB); @@ -201,8 +214,7 @@ void ControlFlowGraphBuilder::handleMachineInstr(MachineInstr &MI) { llvm_unreachable("Unexpected stack memory instruction"); return; case EVM::ARGUMENT: - Cfg.FuncInfo.Parameters.emplace_back( - VariableSlot{MI.getOperand(0).getReg()}); + // Is handled above. return; case EVM::FCALL: handleFunctionCall(MI); @@ -314,6 +326,8 @@ void ControlFlowGraphBuilder::handleReturn(const MachineInstr &MI) { collectInstrOperands(MI, Input, Output); // We need to reverse input operands to restore original ordering, // as it is in the instruction. + // Calling convention: return values are passed in stack such that the + // last one specified in the RET instruction is passed on the stack TOP. std::reverse(Input.begin(), Input.end()); CurrentBlock->Exit = CFG::BasicBlock::FunctionReturn{std::move(Input), &Cfg.FuncInfo}; diff --git a/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp b/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp index 1101076616f1..0e38d53f96f0 100644 --- a/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp +++ b/llvm/lib/Target/EVM/EVMOptimizedCodeTransform.cpp @@ -420,6 +420,8 @@ void EVMOptimizedCodeTransform::operator()() { if (FuncInfo->CanContinue) CurrentStack.emplace_back(FunctionReturnLabelSlot{FuncInfo->MF}); + // Calling convention: input arguments are passed in stack such that the + // first one specified in the function declaration is passed on the stack TOP. for (auto const &Param : reverse(FuncInfo->Parameters)) CurrentStack.emplace_back(Param); diff --git a/llvm/lib/Target/EVM/EVMStackDebug.cpp b/llvm/lib/Target/EVM/EVMStackDebug.cpp index 9c79afc0ec4a..ee78ef00a03f 100644 --- a/llvm/lib/Target/EVM/EVMStackDebug.cpp +++ b/llvm/lib/Target/EVM/EVMStackDebug.cpp @@ -192,8 +192,14 @@ void StackLayoutPrinter::operator()(CFG::BasicBlock const &Block, void StackLayoutPrinter::operator()(CFG::FunctionInfo const &Info) { OS << "Function: " << Info.MF->getName() << "("; - for (const auto &Param : Info.Parameters) - OS << printReg(Param.VirtualReg, nullptr, 0, nullptr); + 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)) + OS << "[unused param] "; + else + llvm_unreachable("Unexpected stack slot"); + } OS << ");\n"; OS << "FunctionEntry " << " -> Block" << getBlockId(*Info.Entry) << ";\n"; (*this)(*Info.Entry, false); diff --git a/llvm/lib/Target/EVM/EVMTargetMachine.cpp b/llvm/lib/Target/EVM/EVMTargetMachine.cpp index 306f4d4db1cb..ccbe26b43389 100644 --- a/llvm/lib/Target/EVM/EVMTargetMachine.cpp +++ b/llvm/lib/Target/EVM/EVMTargetMachine.cpp @@ -203,12 +203,13 @@ void EVMPassConfig::addPreEmitPass() { addPass(&MachineBlockPlacementID); addPass(createEVMOptimizeLiveIntervals()); addPass(createEVMSingleUseExpression()); - // Run the register coloring pass to reduce the total number of registers. - addPass(createEVMRegColoring()); - if (EVMUseLocalStakify) + if (EVMUseLocalStakify) { + // Run the register coloring pass to reduce the total number of registers. + addPass(createEVMRegColoring()); addPass(createEVMStackify()); - else + } else { addPass(createEVMStackifyEF()); + } } } diff --git a/llvm/test/CodeGen/EVM/unused_function_arguments.ll b/llvm/test/CodeGen/EVM/unused_function_arguments.ll new file mode 100644 index 000000000000..0aa142b88b10 --- /dev/null +++ b/llvm/test/CodeGen/EVM/unused_function_arguments.ll @@ -0,0 +1,52 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "E-p:256:256-i256:256:256-S256-a:256:256" +target triple = "evm" + +define i256 @foo(i256 %a1, i256 %a2, i256 %a3) nounwind { +; CHECK-LABEL: @foo +; CHECK: JUMPDEST +; CHECK-NEXT: SWAP2 +; CHECK-NEXT: POP +; CHECK-NEXT: POP +; CHECK-NEXT: DUP1 +; CHECK-NEXT: ADD +; CHECK-NEXT: SWAP1 +; CHECK-NEXT: JUMP + + %x1 = add i256 %a1, %a1 + ret i256 %x1 +} + +define i256 @wat(i256 %a1, i256 %a2, i256 %a3) nounwind { +; CHECK-LABEL: @wat +; CHECK: JUMPDEST +; CHECK-NEXT: POP +; CHECK-NEXT: SWAP1 +; CHECK-NEXT: POP +; CHECK-NEXT: DUP1 +; CHECK-NEXT: ADD +; CHECK-NEXT: SWAP1 +; CHECK-NEXT: JUMP + + %x1 = add i256 %a2, %a2 + ret i256 %x1 +} + +define i256 @bar() nounwind { +; CHECK-LABEL: @bar +; CHECK: JUMPDEST +; CHECK-NEXT: PUSH4 @.FUNC_RET0 +; CHECK-NEXT: PUSH1 3 +; CHECK-NEXT: PUSH1 2 +; CHECK-NEXT: PUSH1 1 +; CHECK-NEXT: PUSH4 @foo +; CHECK-NEXT: JUMP +; CHECK-LABEL: .FUNC_RET0: +; CHECK-NEXT: JUMPDEST +; CHECK-NEXT: SWAP1 +; CHECK-NEXT: JUMP + + %res = call i256 @foo(i256 1, i256 2, i256 3) + ret i256 %res +}