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