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