1 //===----------------------------------------------------------------------===//
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 #include "ReduceOperands.h"
10 #include "llvm/IR/Constants.h"
11 #include "llvm/IR/InstIterator.h"
12 #include "llvm/IR/Operator.h"
13 #include "llvm/IR/Type.h"
14 
15 using namespace llvm;
16 
17 static void
18 extractOperandsFromModule(Oracle &O, Module &Program,
19                           function_ref<Value *(Use &)> ReduceValue) {
20   for (auto &F : Program.functions()) {
21     for (auto &I : instructions(&F)) {
22       for (auto &Op : I.operands()) {
23         Value *Reduced = ReduceValue(Op);
24         if (Reduced && !O.shouldKeep())
25           Op.set(Reduced);
26       }
27     }
28   }
29 }
30 
31 static int countOperands(Module &Program,
32                          function_ref<Value *(Use &)> ReduceValue) {
33   int Count = 0;
34   for (auto &F : Program.functions()) {
35     for (auto &I : instructions(&F)) {
36       for (auto &Op : I.operands()) {
37         if (ReduceValue(Op))
38           Count++;
39       }
40     }
41   }
42   return Count;
43 }
44 
45 static bool isOne(Use &Op) {
46   auto *C = dyn_cast<Constant>(Op);
47   return C && C->isOneValue();
48 }
49 
50 static bool isZero(Use &Op) {
51   auto *C = dyn_cast<Constant>(Op);
52   return C && C->isNullValue();
53 }
54 
55 void llvm::reduceOperandsUndefDeltaPass(TestRunner &Test) {
56   errs() << "*** Reducing Operands to undef...\n";
57   auto ReduceValue = [](Use &Op) -> Value * {
58     if (isa<GEPOperator>(Op.getUser()))
59       return nullptr;
60     if (Op->getType()->isLabelTy())
61       return nullptr;
62     // Don't replace existing ConstantData Uses.
63     return isa<ConstantData>(*Op) ? nullptr : UndefValue::get(Op->getType());
64   };
65   int Count = countOperands(Test.getProgram(), ReduceValue);
66   runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
67     extractOperandsFromModule(O, Program, ReduceValue);
68   });
69 }
70 
71 void llvm::reduceOperandsOneDeltaPass(TestRunner &Test) {
72   errs() << "*** Reducing Operands to one...\n";
73   auto ReduceValue = [](Use &Op) -> Value * {
74     // TODO: support floats
75     if (isa<GEPOperator>(Op.getUser()))
76       return nullptr;
77     auto *Ty = dyn_cast<IntegerType>(Op->getType());
78     if (!Ty)
79       return nullptr;
80     // Don't replace existing ones and zeroes.
81     return (isOne(Op) || isZero(Op)) ? nullptr : ConstantInt::get(Ty, 1);
82   };
83   int Count = countOperands(Test.getProgram(), ReduceValue);
84   runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
85     extractOperandsFromModule(O, Program, ReduceValue);
86   });
87 }
88 
89 void llvm::reduceOperandsZeroDeltaPass(TestRunner &Test) {
90   errs() << "*** Reducing Operands to zero...\n";
91   auto ReduceValue = [](Use &Op) -> Value * {
92     // TODO: be more precise about which GEP operands we can reduce (e.g. array
93     // indexes)
94     if (isa<GEPOperator>(Op.getUser()))
95       return nullptr;
96     if (Op->getType()->isLabelTy())
97       return nullptr;
98     // Don't replace existing zeroes.
99     return isZero(Op) ? nullptr : Constant::getNullValue(Op->getType());
100   };
101   int Count = countOperands(Test.getProgram(), ReduceValue);
102   runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
103     extractOperandsFromModule(O, Program, ReduceValue);
104   });
105 }
106