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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // IR level peephole optimization, specifically removing @llvm.stacksave() and 10 // @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/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" 23 24 #define DEBUG_TYPE "bpf-ir-peephole" 25 26 using namespace llvm; 27 28 namespace { 29 30 static bool BPFIRPeepholeImpl(Function &F) { 31 LLVM_DEBUG(dbgs() << "******** BPF IR Peephole ********\n"); 32 33 bool Changed = false; 34 Instruction *ToErase = nullptr; 35 for (auto &BB : F) { 36 for (auto &I : BB) { 37 // The following code pattern is handled: 38 // %3 = call i8* @llvm.stacksave() 39 // store i8* %3, i8** %saved_stack, align 8 40 // ... 41 // %4 = load i8*, i8** %saved_stack, align 8 42 // 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 depending 49 // on code pattern, it may still miss some. 50 // 51 // With unconditionally removing these instructions, if alloca is 52 // constant, we are okay then. Otherwise, SelectionDag will complain 53 // since BPF does not support dynamic allocation yet. 54 if (ToErase) { 55 ToErase->eraseFromParent(); 56 ToErase = nullptr; 57 } 58 59 if (auto *Call = dyn_cast<CallInst>(&I)) { 60 if (auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand())) { 61 if (!GV->getName().equals("llvm.stacksave")) 62 continue; 63 if (!Call->hasOneUser()) 64 continue; 65 auto *Inst = cast<Instruction>(*Call->user_begin()); 66 LLVM_DEBUG(dbgs() << "Remove:"; I.dump()); 67 LLVM_DEBUG(dbgs() << "Remove:"; Inst->dump(); dbgs() << '\n'); 68 Changed = true; 69 Inst->eraseFromParent(); 70 ToErase = &I; 71 } 72 continue; 73 } 74 75 if (auto *LD = dyn_cast<LoadInst>(&I)) { 76 if (!LD->hasOneUser()) 77 continue; 78 auto *Call = dyn_cast<CallInst>(*LD->user_begin()); 79 if (!Call) 80 continue; 81 auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); 82 if (!GV) 83 continue; 84 if (!GV->getName().equals("llvm.stackrestore")) 85 continue; 86 LLVM_DEBUG(dbgs() << "Remove:"; I.dump()); 87 LLVM_DEBUG(dbgs() << "Remove:"; Call->dump(); dbgs() << '\n'); 88 Changed = true; 89 Call->eraseFromParent(); 90 ToErase = &I; 91 } 92 } 93 } 94 95 return Changed; 96 } 97 98 class BPFIRPeephole final : public FunctionPass { 99 bool runOnFunction(Function &F) override; 100 101 public: 102 static char ID; 103 BPFIRPeephole() : FunctionPass(ID) {} 104 }; 105 } // End anonymous namespace 106 107 char BPFIRPeephole::ID = 0; 108 INITIALIZE_PASS(BPFIRPeephole, DEBUG_TYPE, "BPF IR Peephole", false, false) 109 110 FunctionPass *llvm::createBPFIRPeephole() { return new BPFIRPeephole(); } 111 112 bool BPFIRPeephole::runOnFunction(Function &F) { return BPFIRPeepholeImpl(F); } 113 114 PreservedAnalyses BPFIRPeepholePass::run(Function &F, 115 FunctionAnalysisManager &AM) { 116 return BPFIRPeepholeImpl(F) ? PreservedAnalyses::none() 117 : PreservedAnalyses::all(); 118 } 119