|
1 |
| -//===- ReduceOperands.cpp - Specialized Delta Pass ------------------------===// |
| 1 | +//===----------------------------------------------------------------------===// |
2 | 2 | //
|
3 | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
4 | 4 | // See https://llvm.org/LICENSE.txt for license information.
|
5 | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
6 | 6 | //
|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 |
| -// |
9 |
| -// This file implements a function to reduce operands to undef. |
10 |
| -// |
11 |
| -//===----------------------------------------------------------------------===// |
12 | 8 |
|
13 | 9 | #include "ReduceOperands.h"
|
14 | 10 | #include "llvm/IR/Constants.h"
|
15 | 11 | #include "llvm/IR/InstIterator.h"
|
| 12 | +#include "llvm/IR/Operator.h" |
| 13 | +#include "llvm/IR/Type.h" |
16 | 14 |
|
17 | 15 | using namespace llvm;
|
18 | 16 |
|
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(Oracle &O, Module &Program) { |
38 |
| - // Extract Operands from the module. |
| 17 | +static void |
| 18 | +extractOperandsFromModule(Oracle &O, Module &Program, |
| 19 | + function_ref<Value *(Use &)> ReduceValue) { |
39 | 20 | for (auto &F : Program.functions()) {
|
40 | 21 | for (auto &I : instructions(&F)) {
|
41 | 22 | for (auto &Op : I.operands()) {
|
42 |
| - // Filter Operands then set to undef. |
43 |
| - if (canReduceOperand(Op) && !O.shouldKeep()) { |
44 |
| - auto *Ty = Op->getType(); |
45 |
| - Op.set(UndefValue::get(Ty)); |
46 |
| - } |
| 23 | + Value *Reduced = ReduceValue(Op); |
| 24 | + if (Reduced && !O.shouldKeep()) |
| 25 | + Op.set(Reduced); |
47 | 26 | }
|
48 | 27 | }
|
49 | 28 | }
|
50 | 29 | }
|
51 | 30 |
|
52 |
| -/// Counts the amount of operands in the module that can be reduced. |
53 |
| -static int countOperands(Module &Program) { |
| 31 | +static int countOperands(Module &Program, |
| 32 | + function_ref<Value *(Use &)> ReduceValue) { |
54 | 33 | int Count = 0;
|
55 | 34 | for (auto &F : Program.functions()) {
|
56 | 35 | for (auto &I : instructions(&F)) {
|
57 | 36 | for (auto &Op : I.operands()) {
|
58 |
| - if (canReduceOperand(Op)) { |
| 37 | + if (ReduceValue(Op)) |
59 | 38 | Count++;
|
60 |
| - } |
61 | 39 | }
|
62 | 40 | }
|
63 | 41 | }
|
64 | 42 | return Count;
|
65 | 43 | }
|
66 | 44 |
|
67 |
| -void llvm::reduceOperandsDeltaPass(TestRunner &Test) { |
68 |
| - errs() << "*** Reducing Operands...\n"; |
69 |
| - int Count = countOperands(Test.getProgram()); |
70 |
| - runDeltaPass(Test, Count, extractOperandsFromModule); |
| 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 | + }); |
71 | 105 | }
|
0 commit comments