Skip to content

Commit fed0f89

Browse files
committed
InstCombine: Negator: don't rely on complexity sorting already being performed (PR47752)
In some cases, we can negate instruction if only one of it's operands negates. Previously, we assumed that constants would have been canonicalized to RHS already, but that isn't guaranteed to happen, because of InstCombine worklist visitation order, as the added test (previously-hanging) shows. So if we only need to negate a single operand, we should ensure ourselves that we try constant operand first. Do that by re-doing the complexity sorting ourselves, when we actually care about it. Fixes https://bugs.llvm.org/show_bug.cgi?id=47752
1 parent f71f5f3 commit fed0f89

File tree

3 files changed

+59
-13
lines changed

3 files changed

+59
-13
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,8 @@ class Negator final {
762762
using Result = std::pair<ArrayRef<Instruction *> /*NewInstructions*/,
763763
Value * /*NegatedRoot*/>;
764764

765+
std::array<Value *, 2> getSortedOperandsOfBinOp(Instruction *I);
766+
765767
LLVM_NODISCARD Value *visitImpl(Value *V, unsigned Depth);
766768

767769
LLVM_NODISCARD Value *negate(Value *V, unsigned Depth);

llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,19 @@ Negator::~Negator() {
115115
}
116116
#endif
117117

118+
// Due to the InstCombine's worklist management, there are no guarantees that
119+
// each instruction we'll encounter has been visited by InstCombine already.
120+
// In particular, most importantly for us, that means we have to canonicalize
121+
// constants to RHS ourselves, since that is helpful sometimes.
122+
std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
123+
assert(I->getNumOperands() == 2 && "Only for binops!");
124+
std::array<Value *, 2> Ops{I->getOperand(0), I->getOperand(1)};
125+
if (I->isCommutative() && InstCombiner::getComplexity(I->getOperand(0)) <
126+
InstCombiner::getComplexity(I->getOperand(1)))
127+
std::swap(Ops[0], Ops[1]);
128+
return Ops;
129+
}
130+
118131
// FIXME: can this be reworked into a worklist-based algorithm while preserving
119132
// the depth-first, early bailout traversal?
120133
LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) {
@@ -159,11 +172,13 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) {
159172

160173
// In some cases we can give the answer without further recursion.
161174
switch (I->getOpcode()) {
162-
case Instruction::Add:
175+
case Instruction::Add: {
176+
std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I);
163177
// `inc` is always negatible.
164-
if (match(I->getOperand(1), m_One()))
165-
return Builder.CreateNot(I->getOperand(0), I->getName() + ".neg");
178+
if (match(Ops[1], m_One()))
179+
return Builder.CreateNot(Ops[0], I->getName() + ".neg");
166180
break;
181+
}
167182
case Instruction::Xor:
168183
// `not` is always negatible.
169184
if (match(I, m_Not(m_Value(X))))
@@ -344,16 +359,18 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) {
344359
ConstantExpr::getShl(Constant::getAllOnesValue(Op1C->getType()), Op1C),
345360
I->getName() + ".neg");
346361
}
347-
case Instruction::Or:
362+
case Instruction::Or: {
348363
if (!haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1), DL, &AC, I,
349364
&DT))
350365
return nullptr; // Don't know how to handle `or` in general.
366+
std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I);
351367
// `or`/`add` are interchangeable when operands have no common bits set.
352368
// `inc` is always negatible.
353-
if (match(I->getOperand(1), m_One()))
354-
return Builder.CreateNot(I->getOperand(0), I->getName() + ".neg");
369+
if (match(Ops[1], m_One()))
370+
return Builder.CreateNot(Ops[0], I->getName() + ".neg");
355371
// Else, just defer to Instruction::Add handling.
356372
LLVM_FALLTHROUGH;
373+
}
357374
case Instruction::Add: {
358375
// `add` is negatible if both of its operands are negatible.
359376
SmallVector<Value *, 2> NegatedOps, NonNegatedOps;
@@ -383,26 +400,29 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) {
383400
return Builder.CreateSub(NegatedOps[0], NonNegatedOps[0],
384401
I->getName() + ".neg");
385402
}
386-
case Instruction::Xor:
403+
case Instruction::Xor: {
404+
std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I);
387405
// `xor` is negatible if one of its operands is invertible.
388406
// FIXME: InstCombineInverter? But how to connect Inverter and Negator?
389-
if (auto *C = dyn_cast<Constant>(I->getOperand(1))) {
390-
Value *Xor = Builder.CreateXor(I->getOperand(0), ConstantExpr::getNot(C));
407+
if (auto *C = dyn_cast<Constant>(Ops[1])) {
408+
Value *Xor = Builder.CreateXor(Ops[0], ConstantExpr::getNot(C));
391409
return Builder.CreateAdd(Xor, ConstantInt::get(Xor->getType(), 1),
392410
I->getName() + ".neg");
393411
}
394412
return nullptr;
413+
}
395414
case Instruction::Mul: {
415+
std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I);
396416
// `mul` is negatible if one of its operands is negatible.
397417
Value *NegatedOp, *OtherOp;
398418
// First try the second operand, in case it's a constant it will be best to
399419
// just invert it instead of sinking the `neg` deeper.
400-
if (Value *NegOp1 = negate(I->getOperand(1), Depth + 1)) {
420+
if (Value *NegOp1 = negate(Ops[1], Depth + 1)) {
401421
NegatedOp = NegOp1;
402-
OtherOp = I->getOperand(0);
403-
} else if (Value *NegOp0 = negate(I->getOperand(0), Depth + 1)) {
422+
OtherOp = Ops[0];
423+
} else if (Value *NegOp0 = negate(Ops[0], Depth + 1)) {
404424
NegatedOp = NegOp0;
405-
OtherOp = I->getOperand(1);
425+
OtherOp = Ops[1];
406426
} else
407427
// Can't negate either of them.
408428
return nullptr;

llvm/test/Transforms/InstCombine/sub-of-negatible.ll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,5 +1239,29 @@ define i4 @negate_freeze_extrause(i4 %x, i4 %y, i4 %z) {
12391239
ret i4 %t2
12401240
}
12411241

1242+
; Due to the InstCombine's worklist management, there are no guarantees that
1243+
; each instruction we'll encounter has been visited by InstCombine already.
1244+
; In particular, most importantly for us, that means we have to canonicalize
1245+
; constants to RHS ourselves, since that is helpful sometimes.
1246+
; This used to cause an endless combine loop.
1247+
define void @noncanonical_mul_with_constant_as_first_operand() {
1248+
; CHECK-LABEL: @noncanonical_mul_with_constant_as_first_operand(
1249+
; CHECK-NEXT: entry:
1250+
; CHECK-NEXT: br label [[IF_END:%.*]]
1251+
; CHECK: if.end:
1252+
; CHECK-NEXT: br label [[IF_END]]
1253+
;
1254+
entry:
1255+
br label %if.end
1256+
1257+
if.end:
1258+
%e.0 = phi i32 [ undef, %entry ], [ %div, %if.end ]
1259+
%conv = trunc i32 %e.0 to i16
1260+
%mul.i = mul nsw i16 -1, %conv
1261+
%conv1 = sext i16 %mul.i to i32
1262+
%div = sub nsw i32 0, %conv1
1263+
br label %if.end
1264+
}
1265+
12421266
; CHECK: !0 = !{!"branch_weights", i32 40, i32 1}
12431267
!0 = !{!"branch_weights", i32 40, i32 1}

0 commit comments

Comments
 (0)