diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 7790255e22c4bc..4d7e281312bace 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3928,9 +3928,14 @@ static Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, return nullptr; auto *I = dyn_cast(V); - if (!I) + 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; }); + // Consider: // %cmp = icmp eq i32 %x, 2147483647 // %add = add nsw i32 %x, 1 @@ -3942,89 +3947,54 @@ static Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, if (!AllowRefinement && canCreatePoison(cast(I))) return nullptr; - // The simplification queries below may return the original value. Consider: - // %div = udiv i32 %arg, %arg2 - // %mul = mul nsw i32 %div, %arg2 - // %cmp = icmp eq i32 %mul, %arg - // %sel = select i1 %cmp, i32 %div, i32 undef - // Replacing %arg by %mul, %div becomes "udiv i32 %mul, %arg2", which - // 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; - }; - - // If this is a binary operator, try to simplify it with the replaced op. - if (auto *B = dyn_cast(I)) { - if (MaxRecurse) { - if (B->getOperand(0) == Op) - return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), RepOp, - B->getOperand(1), Q, - MaxRecurse - 1)); - if (B->getOperand(1) == Op) - return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), - B->getOperand(0), RepOp, Q, - MaxRecurse - 1)); - } - } + if (MaxRecurse) { + // The simplification queries below may return the original value. Consider: + // %div = udiv i32 %arg, %arg2 + // %mul = mul nsw i32 %div, %arg2 + // %cmp = icmp eq i32 %mul, %arg + // %sel = select i1 %cmp, i32 %div, i32 undef + // Replacing %arg by %mul, %div becomes "udiv i32 %mul, %arg2", which + // 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; + }; - // Same for CmpInsts. - if (CmpInst *C = dyn_cast(I)) { - if (MaxRecurse) { - if (C->getOperand(0) == Op) - return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), RepOp, - C->getOperand(1), Q, - MaxRecurse - 1)); - if (C->getOperand(1) == Op) - return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), - C->getOperand(0), RepOp, Q, - MaxRecurse - 1)); - } - } + if (auto *B = dyn_cast(I)) + return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), NewOps[0], + NewOps[1], Q, MaxRecurse - 1)); + + if (CmpInst *C = dyn_cast(I)) + return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), NewOps[0], + NewOps[1], Q, MaxRecurse - 1)); - // Same for GEPs. - if (auto *GEP = dyn_cast(I)) { - if (MaxRecurse) { - SmallVector NewOps(GEP->getNumOperands()); - transform(GEP->operands(), NewOps.begin(), - [&](Value *V) { return V == Op ? RepOp : V; }); + if (auto *GEP = dyn_cast(I)) return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(), NewOps, Q, MaxRecurse - 1)); - } - } - // TODO: We could hand off more cases to instsimplify here. + // TODO: We could hand off more cases to instsimplify here. + } // If all operands are constant after substituting Op for RepOp then we can // constant fold the instruction. - if (Constant *CRepOp = dyn_cast(RepOp)) { - // Build a list of all constant operands. - SmallVector ConstOps; - for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { - if (I->getOperand(i) == Op) - ConstOps.push_back(CRepOp); - else if (Constant *COp = dyn_cast(I->getOperand(i))) - ConstOps.push_back(COp); - else - break; - } - - // All operands were constants, fold it. - if (ConstOps.size() == I->getNumOperands()) { - if (CmpInst *C = dyn_cast(I)) - return ConstantFoldCompareInstOperands(C->getPredicate(), ConstOps[0], - ConstOps[1], Q.DL, Q.TLI); + SmallVector ConstOps; + for (Value *NewOp : NewOps) { + if (Constant *ConstOp = dyn_cast(NewOp)) + ConstOps.push_back(ConstOp); + else + return nullptr; + } - if (LoadInst *LI = dyn_cast(I)) - if (!LI->isVolatile()) - return ConstantFoldLoadFromConstPtr(ConstOps[0], LI->getType(), Q.DL); + if (CmpInst *C = dyn_cast(I)) + return ConstantFoldCompareInstOperands(C->getPredicate(), ConstOps[0], + ConstOps[1], Q.DL, Q.TLI); - return ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI); - } - } + if (LoadInst *LI = dyn_cast(I)) + if (!LI->isVolatile()) + return ConstantFoldLoadFromConstPtr(ConstOps[0], LI->getType(), Q.DL); - return nullptr; + return ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI); } Value *llvm::SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,