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