brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.2 KiB · d82275c Raw
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