1//===- ReduceSinkDefsToUses.cpp - Specialized Delta Pass ------------------===//
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// Try to move defs to be next to their uses
10//
11//===----------------------------------------------------------------------===//
12
13#include "ReduceSinkDefsToUses.h"
14#include "Utils.h"
15#include "llvm/IR/Dominators.h"
16#include "llvm/IR/Instructions.h"
17
18using namespace llvm;
19
20static bool shouldPreserveUsePosition(const Instruction &I) {
21 return isa<AllocaInst>(Val: I) || isa<PHINode>(Val: I) || I.isEHPad();
22}
23
24static bool shouldPreserveDefPosition(const Instruction &I) {
25 return shouldPreserveUsePosition(I) || I.isTerminator();
26}
27
28static void sinkDefsToUsesInFunction(Oracle &O, Function &F) {
29 DominatorTree DT(F);
30
31 for (BasicBlock &BB : F) {
32 for (Instruction &UseInst : make_early_inc_range(Range: reverse(C&: BB))) {
33 if (shouldPreserveUsePosition(I: UseInst))
34 continue;
35
36 for (Value *UseOp : UseInst.operands()) {
37 Instruction *DefInst = dyn_cast<Instruction>(Val: UseOp);
38 if (!DefInst || shouldPreserveDefPosition(I: *DefInst))
39 continue;
40
41 if (!all_of(Range: DefInst->users(), P: [&](const User *DefUser) {
42 return DefUser == &UseInst ||
43 DT.dominates(Def: &UseInst, User: cast<Instruction>(Val: DefUser));
44 })) {
45 continue;
46 }
47
48 if (!O.shouldKeep())
49 DefInst->moveBeforePreserving(MovePos: UseInst.getIterator());
50 }
51 }
52 }
53}
54
55void llvm::reduceSinkDefsToUsesDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {
56 Module &M = WorkItem.getModule();
57 for (Function &F : M) {
58 if (!F.isDeclaration())
59 sinkDefsToUsesInFunction(O, F);
60 }
61}
62