xref: /llvm-project/llvm/lib/Target/BPF/BPFIRPeephole.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
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/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 
25 using namespace llvm;
26 
27 namespace {
28 
29 static 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 8
39       //     ...
40       //     %4 = load i8*, i8** %saved_stack, align 8
41       //     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 depending
48       // on code pattern, it may still miss some.
49       //
50       // With unconditionally removing these instructions, if alloca is
51       // constant, we are okay then. Otherwise, SelectionDag will complain
52       // 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 namespace
92 
93 PreservedAnalyses BPFIRPeepholePass::run(Function &F,
94                                          FunctionAnalysisManager &AM) {
95   return BPFIRPeepholeImpl(F) ? PreservedAnalyses::none()
96                               : PreservedAnalyses::all();
97 }
98