Skip to content

Commit f0febbd

Browse files
committed
[InstSimplify] Refactor simplifyWithOpsReplaced to allow multiple replacements; NFC
This allows for multiple ops to be replaced at once. This can be useful if say replacing in the context of `X | Y == 0`, where some replacements will only be available if we replace `X` and `Y` with `0` at the same time.
1 parent c56b743 commit f0febbd

File tree

1 file changed

+46
-24
lines changed

1 file changed

+46
-24
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4275,25 +4275,23 @@ Value *llvm::simplifyFCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS,
42754275
return ::simplifyFCmpInst(Predicate, LHS, RHS, FMF, Q, RecursionLimit);
42764276
}
42774277

4278-
static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
4279-
const SimplifyQuery &Q,
4280-
bool AllowRefinement,
4281-
SmallVectorImpl<Instruction *> *DropFlags,
4282-
unsigned MaxRecurse) {
4278+
static Value *simplifyWithOpsReplaced(Value *V,
4279+
ArrayRef<std::pair<Value *, Value *>> Ops,
4280+
const SimplifyQuery &Q,
4281+
bool AllowRefinement,
4282+
SmallVectorImpl<Instruction *> *DropFlags,
4283+
unsigned MaxRecurse) {
42834284
assert((AllowRefinement || !Q.CanUseUndef) &&
42844285
"If AllowRefinement=false then CanUseUndef=false");
4285-
4286-
// Trivial replacement.
4287-
if (V == Op)
4288-
return RepOp;
4286+
for (const auto &OpAndRepOp : Ops) {
4287+
// Trivial replacement.
4288+
if (V == OpAndRepOp.first)
4289+
return OpAndRepOp.second;
4290+
}
42894291

42904292
if (!MaxRecurse--)
42914293
return nullptr;
42924294

4293-
// We cannot replace a constant, and shouldn't even try.
4294-
if (isa<Constant>(Op))
4295-
return nullptr;
4296-
42974295
auto *I = dyn_cast<Instruction>(V);
42984296
if (!I)
42994297
return nullptr;
@@ -4303,11 +4301,6 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43034301
if (isa<PHINode>(I))
43044302
return nullptr;
43054303

4306-
// For vector types, the simplification must hold per-lane, so forbid
4307-
// potentially cross-lane operations like shufflevector.
4308-
if (Op->getType()->isVectorTy() && !isNotCrossLaneOperation(I))
4309-
return nullptr;
4310-
43114304
// Don't fold away llvm.is.constant checks based on assumptions.
43124305
if (match(I, m_Intrinsic<Intrinsic::is_constant>()))
43134306
return nullptr;
@@ -4316,12 +4309,30 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43164309
if (isa<FreezeInst>(I))
43174310
return nullptr;
43184311

4312+
SmallVector<std::pair<Value *, Value *>> ValidReplacements{};
4313+
for (const auto &OpAndRepOp : Ops) {
4314+
// We cannot replace a constant, and shouldn't even try.
4315+
if (isa<Constant>(OpAndRepOp.first))
4316+
return nullptr;
4317+
4318+
// For vector types, the simplification must hold per-lane, so forbid
4319+
// potentially cross-lane operations like shufflevector.
4320+
if (OpAndRepOp.first->getType()->isVectorTy() &&
4321+
!isNotCrossLaneOperation(I))
4322+
continue;
4323+
ValidReplacements.emplace_back(OpAndRepOp);
4324+
}
4325+
4326+
if (ValidReplacements.empty())
4327+
return nullptr;
4328+
43194329
// Replace Op with RepOp in instruction operands.
43204330
SmallVector<Value *, 8> NewOps;
43214331
bool AnyReplaced = false;
43224332
for (Value *InstOp : I->operands()) {
4323-
if (Value *NewInstOp = simplifyWithOpReplaced(
4324-
InstOp, Op, RepOp, Q, AllowRefinement, DropFlags, MaxRecurse)) {
4333+
if (Value *NewInstOp =
4334+
simplifyWithOpsReplaced(InstOp, ValidReplacements, Q,
4335+
AllowRefinement, DropFlags, MaxRecurse)) {
43254336
NewOps.push_back(NewInstOp);
43264337
AnyReplaced = InstOp != NewInstOp;
43274338
} else {
@@ -4372,7 +4383,9 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43724383
// by assumption and this case never wraps, so nowrap flags can be
43734384
// ignored.
43744385
if ((Opcode == Instruction::Sub || Opcode == Instruction::Xor) &&
4375-
NewOps[0] == RepOp && NewOps[1] == RepOp)
4386+
any_of(ValidReplacements, [=](const auto &Rep) {
4387+
return NewOps[0] == NewOps[1] && NewOps[0] == Rep.second;
4388+
}))
43764389
return Constant::getNullValue(I->getType());
43774390

43784391
// If we are substituting an absorber constant into a binop and extra
@@ -4382,10 +4395,10 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43824395
// (Op == 0) ? 0 : (Op & -Op) --> Op & -Op
43834396
// (Op == 0) ? 0 : (Op * (binop Op, C)) --> Op * (binop Op, C)
43844397
// (Op == -1) ? -1 : (Op | (binop C, Op) --> Op | (binop C, Op)
4385-
Constant *Absorber =
4386-
ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
4398+
Constant *Absorber = ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
43874399
if ((NewOps[0] == Absorber || NewOps[1] == Absorber) &&
4388-
impliesPoison(BO, Op))
4400+
all_of(ValidReplacements,
4401+
[=](const auto &Rep) { return impliesPoison(BO, Rep.first); }))
43894402
return Absorber;
43904403
}
43914404

@@ -4453,6 +4466,15 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
44534466
/*AllowNonDeterministic=*/false);
44544467
}
44554468

4469+
static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
4470+
const SimplifyQuery &Q,
4471+
bool AllowRefinement,
4472+
SmallVectorImpl<Instruction *> *DropFlags,
4473+
unsigned MaxRecurse) {
4474+
return simplifyWithOpsReplaced(V, {{Op, RepOp}}, Q, AllowRefinement,
4475+
DropFlags, MaxRecurse);
4476+
}
4477+
44564478
Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
44574479
const SimplifyQuery &Q,
44584480
bool AllowRefinement,

0 commit comments

Comments
 (0)