Path: blob/main/contrib/llvm-project/llvm/lib/Target/BPF/BPFIRPeephole.cpp
35267 views
//===------------ BPFIRPeephole.cpp - IR Peephole Transformation ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// IR level peephole optimization, specifically removing @llvm.stacksave() and9// @llvm.stackrestore().10//11//===----------------------------------------------------------------------===//1213#include "BPF.h"14#include "llvm/IR/Instruction.h"15#include "llvm/IR/Instructions.h"16#include "llvm/IR/IntrinsicInst.h"17#include "llvm/IR/Module.h"18#include "llvm/IR/PassManager.h"19#include "llvm/IR/Type.h"20#include "llvm/IR/User.h"21#include "llvm/IR/Value.h"22#include "llvm/Pass.h"2324#define DEBUG_TYPE "bpf-ir-peephole"2526using namespace llvm;2728namespace {2930static bool BPFIRPeepholeImpl(Function &F) {31LLVM_DEBUG(dbgs() << "******** BPF IR Peephole ********\n");3233bool Changed = false;34Instruction *ToErase = nullptr;35for (auto &BB : F) {36for (auto &I : BB) {37// The following code pattern is handled:38// %3 = call i8* @llvm.stacksave()39// store i8* %3, i8** %saved_stack, align 840// ...41// %4 = load i8*, i8** %saved_stack, align 842// call void @llvm.stackrestore(i8* %4)43// ...44// The goal is to remove the above four instructions,45// so we won't have instructions with r11 (stack pointer)46// if eventually there is no variable length stack allocation.47// InstrCombine also tries to remove the above instructions,48// if it is proven safe (constant alloca etc.), but depending49// on code pattern, it may still miss some.50//51// With unconditionally removing these instructions, if alloca is52// constant, we are okay then. Otherwise, SelectionDag will complain53// since BPF does not support dynamic allocation yet.54if (ToErase) {55ToErase->eraseFromParent();56ToErase = nullptr;57}5859if (auto *II = dyn_cast<IntrinsicInst>(&I)) {60if (II->getIntrinsicID() != Intrinsic::stacksave)61continue;62if (!II->hasOneUser())63continue;64auto *Inst = cast<Instruction>(*II->user_begin());65LLVM_DEBUG(dbgs() << "Remove:"; I.dump());66LLVM_DEBUG(dbgs() << "Remove:"; Inst->dump(); dbgs() << '\n');67Changed = true;68Inst->eraseFromParent();69ToErase = &I;70continue;71}7273if (auto *LD = dyn_cast<LoadInst>(&I)) {74if (!LD->hasOneUser())75continue;76auto *II = dyn_cast<IntrinsicInst>(*LD->user_begin());77if (!II)78continue;79if (II->getIntrinsicID() != Intrinsic::stackrestore)80continue;81LLVM_DEBUG(dbgs() << "Remove:"; I.dump());82LLVM_DEBUG(dbgs() << "Remove:"; II->dump(); dbgs() << '\n');83Changed = true;84II->eraseFromParent();85ToErase = &I;86}87}88}8990return Changed;91}92} // End anonymous namespace9394PreservedAnalyses BPFIRPeepholePass::run(Function &F,95FunctionAnalysisManager &AM) {96return BPFIRPeepholeImpl(F) ? PreservedAnalyses::none()97: PreservedAnalyses::all();98}99100101