98 lines · cpp
1//===------------ BPFIRPeephole.cpp - IR Peephole Transformation ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// IR level peephole optimization, specifically removing @llvm.stacksave() and10// @llvm.stackrestore().11//12//===----------------------------------------------------------------------===//13 14#include "BPF.h"15#include "llvm/IR/Instruction.h"16#include "llvm/IR/Instructions.h"17#include "llvm/IR/IntrinsicInst.h"18#include "llvm/IR/PassManager.h"19#include "llvm/IR/Type.h"20#include "llvm/IR/Value.h"21#include "llvm/Pass.h"22 23#define DEBUG_TYPE "bpf-ir-peephole"24 25using namespace llvm;26 27namespace {28 29static bool BPFIRPeepholeImpl(Function &F) {30 LLVM_DEBUG(dbgs() << "******** BPF IR Peephole ********\n");31 32 bool Changed = false;33 Instruction *ToErase = nullptr;34 for (auto &BB : F) {35 for (auto &I : BB) {36 // The following code pattern is handled:37 // %3 = call i8* @llvm.stacksave()38 // store i8* %3, i8** %saved_stack, align 839 // ...40 // %4 = load i8*, i8** %saved_stack, align 841 // call void @llvm.stackrestore(i8* %4)42 // ...43 // The goal is to remove the above four instructions,44 // so we won't have instructions with r11 (stack pointer)45 // if eventually there is no variable length stack allocation.46 // InstrCombine also tries to remove the above instructions,47 // if it is proven safe (constant alloca etc.), but depending48 // on code pattern, it may still miss some.49 //50 // With unconditionally removing these instructions, if alloca is51 // constant, we are okay then. Otherwise, SelectionDag will complain52 // since BPF does not support dynamic allocation yet.53 if (ToErase) {54 ToErase->eraseFromParent();55 ToErase = nullptr;56 }57 58 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {59 if (II->getIntrinsicID() != Intrinsic::stacksave)60 continue;61 if (!II->hasOneUser())62 continue;63 auto *Inst = cast<Instruction>(*II->user_begin());64 LLVM_DEBUG(dbgs() << "Remove:"; I.dump());65 LLVM_DEBUG(dbgs() << "Remove:"; Inst->dump(); dbgs() << '\n');66 Changed = true;67 Inst->eraseFromParent();68 ToErase = &I;69 continue;70 }71 72 if (auto *LD = dyn_cast<LoadInst>(&I)) {73 if (!LD->hasOneUser())74 continue;75 auto *II = dyn_cast<IntrinsicInst>(*LD->user_begin());76 if (!II)77 continue;78 if (II->getIntrinsicID() != Intrinsic::stackrestore)79 continue;80 LLVM_DEBUG(dbgs() << "Remove:"; I.dump());81 LLVM_DEBUG(dbgs() << "Remove:"; II->dump(); dbgs() << '\n');82 Changed = true;83 II->eraseFromParent();84 ToErase = &I;85 }86 }87 }88 89 return Changed;90}91} // End anonymous namespace92 93PreservedAnalyses BPFIRPeepholePass::run(Function &F,94 FunctionAnalysisManager &AM) {95 return BPFIRPeepholeImpl(F) ? PreservedAnalyses::none()96 : PreservedAnalyses::all();97}98