1 //===- ReduceOperands.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 // This file implements a function to reduce operands to undef.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "ReduceOperands.h"
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/InstIterator.h"
16 
17 using namespace llvm;
18 
19 /// Returns if the given operand is undef.
20 static bool operandIsUndefValue(Use &Op) {
21   if (auto *C = dyn_cast<Constant>(Op)) {
22     return isa<UndefValue>(C);
23   }
24   return false;
25 }
26 
27 /// Returns if an operand can be reduced to undef.
28 /// TODO: make this logic check what types are reducible rather than
29 /// check what types that are not reducible.
30 static bool canReduceOperand(Use &Op) {
31   auto *Ty = Op->getType();
32   // Can't reduce labels to undef
33   return !Ty->isLabelTy() && !operandIsUndefValue(Op);
34 }
35 
36 /// Sets Operands to undef.
37 static void extractOperandsFromModule(std::vector<Chunk> ChunksToKeep,
38                                       Module *Program) {
39   Oracle O(ChunksToKeep);
40 
41   // Extract Operands from the module.
42   for (auto &F : Program->functions()) {
43     for (auto &I : instructions(&F)) {
44       for (auto &Op : I.operands()) {
45         // Filter Operands then set to undef.
46         if (canReduceOperand(Op) && !O.shouldKeep()) {
47           auto *Ty = Op->getType();
48           Op.set(UndefValue::get(Ty));
49         }
50       }
51     }
52   }
53 }
54 
55 /// Counts the amount of operands in the module that can be reduced.
56 static int countOperands(Module *Program) {
57   int Count = 0;
58   for (auto &F : Program->functions()) {
59     for (auto &I : instructions(&F)) {
60       for (auto &Op : I.operands()) {
61         if (canReduceOperand(Op)) {
62           Count++;
63         }
64       }
65     }
66   }
67   return Count;
68 }
69 
70 void llvm::reduceOperandsDeltaPass(TestRunner &Test) {
71   errs() << "*** Reducing Operands...\n";
72   int Count = countOperands(Test.getProgram());
73   runDeltaPass(Test, Count, extractOperandsFromModule);
74 }
75