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/IntrinsicInst.h" 18 #include "llvm/IR/Module.h" 19 #include "llvm/IR/PassManager.h" 20 #include "llvm/IR/Type.h" 21 #include "llvm/IR/User.h" 22 #include "llvm/IR/Value.h" 23 #include "llvm/Pass.h" 24 25 #define DEBUG_TYPE "bpf-ir-peephole" 26 27 using namespace llvm; 28 29 namespace { 30 31 static bool BPFIRPeepholeImpl(Function &F) { 32 LLVM_DEBUG(dbgs() << "******** BPF IR Peephole ********\n"); 33 34 bool Changed = false; 35 Instruction *ToErase = nullptr; 36 for (auto &BB : F) { 37 for (auto &I : BB) { 38 // The following code pattern is handled: 39 // %3 = call i8* @llvm.stacksave() 40 // store i8* %3, i8** %saved_stack, align 8 41 // ... 42 // %4 = load i8*, i8** %saved_stack, align 8 43 // call void @llvm.stackrestore(i8* %4) 44 // ... 45 // The goal is to remove the above four instructions, 46 // so we won't have instructions with r11 (stack pointer) 47 // if eventually there is no variable length stack allocation. 48 // InstrCombine also tries to remove the above instructions, 49 // if it is proven safe (constant alloca etc.), but depending 50 // on code pattern, it may still miss some. 51 // 52 // With unconditionally removing these instructions, if alloca is 53 // constant, we are okay then. Otherwise, SelectionDag will complain 54 // since BPF does not support dynamic allocation yet. 55 if (ToErase) { 56 ToErase->eraseFromParent(); 57 ToErase = nullptr; 58 } 59 60 if (auto *II = dyn_cast<IntrinsicInst>(&I)) { 61 if (II->getIntrinsicID() != Intrinsic::stacksave) 62 continue; 63 if (!II->hasOneUser()) 64 continue; 65 auto *Inst = cast<Instruction>(*II->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 continue; 72 } 73 74 if (auto *LD = dyn_cast<LoadInst>(&I)) { 75 if (!LD->hasOneUser()) 76 continue; 77 auto *II = dyn_cast<IntrinsicInst>(*LD->user_begin()); 78 if (!II) 79 continue; 80 if (II->getIntrinsicID() != Intrinsic::stackrestore) 81 continue; 82 LLVM_DEBUG(dbgs() << "Remove:"; I.dump()); 83 LLVM_DEBUG(dbgs() << "Remove:"; II->dump(); dbgs() << '\n'); 84 Changed = true; 85 II->eraseFromParent(); 86 ToErase = &I; 87 } 88 } 89 } 90 91 return Changed; 92 } 93 } // End anonymous namespace 94 95 PreservedAnalyses BPFIRPeepholePass::run(Function &F, 96 FunctionAnalysisManager &AM) { 97 return BPFIRPeepholeImpl(F) ? PreservedAnalyses::none() 98 : PreservedAnalyses::all(); 99 } 100