[InstCombine] Extract "freely invert" related helpers (NFC)

This commit is contained in:
Nikita Popov
2023-07-11 14:59:50 +02:00
parent 053d9e5832
commit b53e16ca0c
2 changed files with 31 additions and 47 deletions

View File

@@ -3994,6 +3994,29 @@ static Instruction *canonicalizeAbs(BinaryOperator &Xor,
return nullptr;
}
static bool canFreelyInvert(InstCombiner &IC, Value *Op,
Instruction *IgnoredUser) {
if (!IC.isFreeToInvert(Op, /*WillInvertAllUses=*/true))
return false;
return match(Op, m_ImmConstant()) ||
(isa<Instruction>(Op) && InstCombiner::canFreelyInvertAllUsersOf(
cast<Instruction>(Op), IgnoredUser));
}
static Value *freelyInvert(InstCombinerImpl &IC, Value *Op,
Instruction *IgnoredUser) {
if (auto *C = dyn_cast<Constant>(Op))
return ConstantExpr::getNot(C);
IC.Builder.SetInsertPoint(
&*cast<Instruction>(Op)->getInsertionPointAfterDef());
Value *NotOp = IC.Builder.CreateNot(Op, Op->getName() + ".not");
Op->replaceUsesWithIf(NotOp,
[NotOp](Use &U) { return U.getUser() != NotOp; });
IC.freelyInvertAllUsersOf(NotOp, IgnoredUser);
return NotOp;
}
// Transform
// z = ~(x &/| y)
// into:
@@ -4018,28 +4041,11 @@ bool InstCombinerImpl::sinkNotIntoLogicalOp(Instruction &I) {
return false;
// And can the operands be adapted?
for (Value *Op : {Op0, Op1})
if (!(InstCombiner::isFreeToInvert(Op, /*WillInvertAllUses=*/true) &&
(match(Op, m_ImmConstant()) ||
(isa<Instruction>(Op) &&
InstCombiner::canFreelyInvertAllUsersOf(cast<Instruction>(Op),
/*IgnoredUser=*/&I)))))
return false;
if (!canFreelyInvert(*this, Op0, &I) || !canFreelyInvert(*this, Op1, &I))
return false;
for (Value **Op : {&Op0, &Op1}) {
Value *NotOp;
if (auto *C = dyn_cast<Constant>(*Op)) {
NotOp = ConstantExpr::getNot(C);
} else {
Builder.SetInsertPoint(
&*cast<Instruction>(*Op)->getInsertionPointAfterDef());
NotOp = Builder.CreateNot(*Op, (*Op)->getName() + ".not");
(*Op)->replaceUsesWithIf(
NotOp, [NotOp](Use &U) { return U.getUser() != NotOp; });
freelyInvertAllUsersOf(NotOp, /*IgnoredUser=*/&I);
}
*Op = NotOp;
}
Op0 = freelyInvert(*this, Op0, &I);
Op1 = freelyInvert(*this, Op1, &I);
Builder.SetInsertPoint(I.getInsertionPointAfterDef());
Value *NewLogicOp;
@@ -4073,20 +4079,11 @@ bool InstCombinerImpl::sinkNotIntoOtherHandOfLogicalOp(Instruction &I) {
Value *NotOp0 = nullptr;
Value *NotOp1 = nullptr;
Value **OpToInvert = nullptr;
if (match(Op0, m_Not(m_Value(NotOp0))) &&
InstCombiner::isFreeToInvert(Op1, /*WillInvertAllUses=*/true) &&
(match(Op1, m_ImmConstant()) ||
(isa<Instruction>(Op1) &&
InstCombiner::canFreelyInvertAllUsersOf(cast<Instruction>(Op1),
/*IgnoredUser=*/&I)))) {
if (match(Op0, m_Not(m_Value(NotOp0))) && canFreelyInvert(*this, Op1, &I)) {
Op0 = NotOp0;
OpToInvert = &Op1;
} else if (match(Op1, m_Not(m_Value(NotOp1))) &&
InstCombiner::isFreeToInvert(Op0, /*WillInvertAllUses=*/true) &&
(match(Op0, m_ImmConstant()) ||
(isa<Instruction>(Op0) &&
InstCombiner::canFreelyInvertAllUsersOf(cast<Instruction>(Op0),
/*IgnoredUser=*/&I)))) {
canFreelyInvert(*this, Op0, &I)) {
Op1 = NotOp1;
OpToInvert = &Op0;
} else
@@ -4096,19 +4093,7 @@ bool InstCombinerImpl::sinkNotIntoOtherHandOfLogicalOp(Instruction &I) {
if (!InstCombiner::canFreelyInvertAllUsersOf(&I, /*IgnoredUser=*/nullptr))
return false;
if (auto *C = dyn_cast<Constant>(*OpToInvert)) {
*OpToInvert = ConstantExpr::getNot(C);
} else {
Builder.SetInsertPoint(
&*cast<Instruction>(*OpToInvert)->getInsertionPointAfterDef());
Value *NotOpToInvert =
Builder.CreateNot(*OpToInvert, (*OpToInvert)->getName() + ".not");
(*OpToInvert)->replaceUsesWithIf(NotOpToInvert, [NotOpToInvert](Use &U) {
return U.getUser() != NotOpToInvert;
});
freelyInvertAllUsersOf(NotOpToInvert, /*IgnoredUser=*/&I);
*OpToInvert = NotOpToInvert;
}
*OpToInvert = freelyInvert(*this, *OpToInvert, &I);
Builder.SetInsertPoint(&*I.getInsertionPointAfterDef());
Value *NewBinOp;

View File

@@ -331,8 +331,6 @@ private:
Instruction *foldNot(BinaryOperator &I);
Instruction *foldBinOpOfDisplacedShifts(BinaryOperator &I);
void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser = nullptr);
/// Determine if a pair of casts can be replaced by a single cast.
///
/// \param CI1 The first of a pair of casts.
@@ -665,6 +663,7 @@ public:
bool removeInstructionsBeforeUnreachable(Instruction &I);
bool handleUnreachableFrom(Instruction *I);
bool handlePotentiallyDeadSuccessors(BasicBlock *BB, BasicBlock *LiveSucc);
void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser = nullptr);
};
class Negator final {