diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h --- a/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -319,6 +319,13 @@ Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, const SimplifyQuery &Q, bool AllowRefinement); +/// See if V simplifies when its operands are replaced with \p NewOps. If not, +/// return null. +/// AllowRefinement specifies whether the simplification can be a refinement +/// (e.g. 0 instead of poison), or whether it needs to be strictly identical. +Value *simplifyWithOpsReplaced(Value *V, ArrayRef NewOps, + const SimplifyQuery &Q, bool AllowRefinement); + /// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively. /// /// This first performs a normal RAUW of I with SimpleV. It then recursively diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3891,28 +3891,11 @@ return ::SimplifyFCmpInst(Predicate, LHS, RHS, FMF, Q, RecursionLimit); } -static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, - const SimplifyQuery &Q, - bool AllowRefinement, - unsigned MaxRecurse) { - assert(!Op->getType()->isVectorTy() && "This is not safe for vectors"); - - // Trivial replacement. - if (V == Op) - return RepOp; - - // We cannot replace a constant, and shouldn't even try. - if (isa(Op)) - return nullptr; - - auto *I = dyn_cast(V); - if (!I || !is_contained(I->operands(), Op)) - return nullptr; - - // Replace Op with RepOp in instruction operands. - SmallVector NewOps(I->getNumOperands()); - transform(I->operands(), NewOps.begin(), - [&](Value *V) { return V == Op ? RepOp : V; }); +static Value *simplifyWithOpsReplaced(Instruction *I, + ArrayRef NewOps, + const SimplifyQuery &Q, + bool AllowRefinement, + unsigned MaxRecurse) { if (!AllowRefinement) { // General InstSimplify functions may refine the result, e.g. by returning @@ -3950,8 +3933,8 @@ // simplifies back to %arg. This can only happen because %mul does not // dominate %div. To ensure a consistent return value contract, we make sure // that this case returns nullptr as well. - auto PreventSelfSimplify = [V](Value *Simplified) { - return Simplified != V ? Simplified : nullptr; + auto PreventSelfSimplify = [I](Value *Simplified) { + return Simplified != I ? Simplified : nullptr; }; if (auto *B = dyn_cast(I)) @@ -4006,6 +3989,32 @@ return ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI); } +static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, + const SimplifyQuery &Q, + bool AllowRefinement, + unsigned MaxRecurse) { + assert(!Op->getType()->isVectorTy() && "This is not safe for vectors"); + + // Trivial replacement. + if (V == Op) + return RepOp; + + // We cannot replace a constant, and shouldn't even try. + if (isa(Op)) + return nullptr; + + auto *I = dyn_cast(V); + if (!I || !is_contained(I->operands(), Op)) + return nullptr; + + // Replace Op with RepOp in instruction operands. + SmallVector NewOps(I->getNumOperands()); + transform(I->operands(), NewOps.begin(), + [&](Value *V) { return V == Op ? RepOp : V; }); + return ::simplifyWithOpsReplaced(I, NewOps, Q, AllowRefinement, + RecursionLimit); +} + Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, const SimplifyQuery &Q, bool AllowRefinement) { @@ -4013,6 +4022,17 @@ RecursionLimit); } +Value *llvm::simplifyWithOpsReplaced(Value *V, ArrayRef NewOps, + const SimplifyQuery &Q, + bool AllowRefinement) { + auto *I = dyn_cast(V); + if (!I) + return nullptr; + + return ::simplifyWithOpsReplaced(I, NewOps, Q, AllowRefinement, + RecursionLimit); +} + /// Try to simplify a select instruction when its condition operand is an /// integer comparison where one operand of the compare is a constant. static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X,