Skip to content

Commit b48c814

Browse files
committed
[InstCombine] Make isFreeToInvert check recursively.
Some Instructions (select/min/max) are inverted by just inverting the operands. So the answer of whether they are free to invert is really just whether the operands are free to invert. Differential Revision: https://reviews.llvm.org/D159056
1 parent 8b0f425 commit b48c814

File tree

3 files changed

+65
-41
lines changed

3 files changed

+65
-41
lines changed

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -239,45 +239,67 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
239239
/// uses of V and only keep uses of ~V.
240240
///
241241
/// See also: canFreelyInvertAllUsersOf()
242-
static bool isFreeToInvert(Value *V, bool WillInvertAllUses) {
242+
static bool isFreeToInvertImpl(Value *V, bool WillInvertAllUses,
243+
bool &DoesConsume, unsigned Depth) {
244+
using namespace llvm::PatternMatch;
243245
// ~(~(X)) -> X.
244-
if (match(V, m_Not(PatternMatch::m_Value())))
246+
if (match(V, m_Not(m_Value()))) {
247+
DoesConsume = true;
245248
return true;
249+
}
246250

247251
// Constants can be considered to be not'ed values.
248-
if (match(V, PatternMatch::m_AnyIntegralConstant()))
252+
if (match(V, m_AnyIntegralConstant()))
249253
return true;
250254

255+
if (Depth++ >= MaxAnalysisRecursionDepth)
256+
return false;
257+
258+
// The rest of the cases require that we invert all uses so don't bother
259+
// doing the analysis if we know we can't use the result.
260+
if (!WillInvertAllUses)
261+
return false;
262+
251263
// Compares can be inverted if all of their uses are being modified to use
252264
// the ~V.
253265
if (isa<CmpInst>(V))
254-
return WillInvertAllUses;
255-
256-
// If `V` is of the form `A + Constant` then `-1 - V` can be folded into
257-
// `(-1 - Constant) - A` if we are willing to invert all of the uses.
258-
if (match(V, m_Add(PatternMatch::m_Value(), PatternMatch::m_ImmConstant())))
259-
return WillInvertAllUses;
260-
261-
// If `V` is of the form `Constant - A` then `-1 - V` can be folded into
262-
// `A + (-1 - Constant)` if we are willing to invert all of the uses.
263-
if (match(V, m_Sub(PatternMatch::m_ImmConstant(), PatternMatch::m_Value())))
264-
return WillInvertAllUses;
265-
266-
// Selects with invertible operands are freely invertible
267-
if (match(V,
268-
m_Select(PatternMatch::m_Value(), m_Not(PatternMatch::m_Value()),
269-
m_Not(PatternMatch::m_Value()))))
270-
return WillInvertAllUses;
271-
272-
// Min/max may be in the form of intrinsics, so handle those identically
273-
// to select patterns.
274-
if (match(V, m_MaxOrMin(m_Not(PatternMatch::m_Value()),
275-
m_Not(PatternMatch::m_Value()))))
276-
return WillInvertAllUses;
266+
return true;
267+
268+
Value *A, *B;
269+
// If `V` is of the form `A + B` then `-1 - V` can be folded into
270+
// `~B - A` or `~A - B` if we are willing to invert all of the uses.
271+
if (match(V, m_Add(m_Value(A), m_Value(B))))
272+
return isFreeToInvertImpl(A, A->hasOneUse(), DoesConsume, Depth) ||
273+
isFreeToInvertImpl(B, B->hasOneUse(), DoesConsume, Depth);
274+
275+
// If `V` is of the form `A - B` then `-1 - V` can be folded into
276+
// `~A + B` if we are willing to invert all of the uses.
277+
if (match(V, m_Sub(m_Value(A), m_Value())))
278+
return isFreeToInvertImpl(A, A->hasOneUse(), DoesConsume, Depth);
279+
280+
// LogicOps are special in that we canonicalize them at the cost of an
281+
// instruction.
282+
bool IsSelect = match(V, m_Select(m_Value(), m_Value(A), m_Value(B))) &&
283+
!shouldAvoidAbsorbingNotIntoSelect(*cast<SelectInst>(V));
284+
// Selects/min/max with invertible operands are freely invertible
285+
if (IsSelect || match(V, m_MaxOrMin(m_Value(A), m_Value(B))))
286+
return isFreeToInvertImpl(A, A->hasOneUse(), DoesConsume, Depth) &&
287+
isFreeToInvertImpl(B, B->hasOneUse(), DoesConsume, Depth);
277288

278289
return false;
279290
}
280291

292+
static bool isFreeToInvert(Value *V, bool WillInvertAllUses,
293+
bool &DoesConsume) {
294+
DoesConsume = false;
295+
return isFreeToInvertImpl(V, WillInvertAllUses, DoesConsume, /*Depth*/ 0);
296+
}
297+
298+
static bool isFreeToInvert(Value *V, bool WillInvertAllUses) {
299+
bool Unused;
300+
return isFreeToInvert(V, WillInvertAllUses, Unused);
301+
}
302+
281303
/// Given i1 V, can every user of V be freely adapted if V is changed to !V ?
282304
/// InstCombine's freelyInvertAllUsersOf() must be kept in sync with this fn.
283305
/// NOTE: for Instructions only!

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,14 +2222,17 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
22222222
}
22232223

22242224
// (~X) - (~Y) --> Y - X
2225-
// This is placed after the other reassociations and explicitly excludes a
2226-
// sub-of-sub pattern to avoid infinite looping.
2227-
if (isFreeToInvert(Op0, Op0->hasOneUse()) &&
2228-
isFreeToInvert(Op1, Op1->hasOneUse()) &&
2229-
!match(Op0, m_Sub(m_ImmConstant(), m_Value()))) {
2230-
Value *NotOp0 = Builder.CreateNot(Op0);
2231-
Value *NotOp1 = Builder.CreateNot(Op1);
2232-
return BinaryOperator::CreateSub(NotOp1, NotOp0);
2225+
{
2226+
// Need to ensure we can consume at least one of the `not` instructions,
2227+
// otherwise this can inf loop.
2228+
bool ConsumesOp0, ConsumesOp1;
2229+
if (isFreeToInvert(Op0, Op0->hasOneUse(), ConsumesOp0) &&
2230+
isFreeToInvert(Op1, Op1->hasOneUse(), ConsumesOp1) &&
2231+
(ConsumesOp0 || ConsumesOp1)) {
2232+
Value *NotOp0 = Builder.CreateNot(Op0);
2233+
Value *NotOp1 = Builder.CreateNot(Op1);
2234+
return BinaryOperator::CreateSub(NotOp1, NotOp0);
2235+
}
22332236
}
22342237

22352238
auto m_AddRdx = [](Value *&Vec) {

llvm/test/Transforms/InstCombine/minmax-intrinsics.ll

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,14 +1494,13 @@ define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) {
14941494

14951495
define i8 @sub_not_min_max(i8 %r, i8 %g, i8 %b) {
14961496
; CHECK-LABEL: @sub_not_min_max(
1497-
; CHECK-NEXT: [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
14981497
; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
14991498
; CHECK-NEXT: call void @use(i8 [[NOTG]])
15001499
; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
15011500
; CHECK-NEXT: call void @use(i8 [[NOTB]])
1502-
; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1503-
; CHECK-NEXT: [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1504-
; CHECK-NEXT: [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1501+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G]])
1502+
; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]])
1503+
; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
15051504
; CHECK-NEXT: ret i8 [[CK]]
15061505
;
15071506
%notr = xor i8 %r, -1
@@ -1523,9 +1522,9 @@ define i8 @sub_not_min_max_uses1(i8 %r, i8 %g, i8 %b) {
15231522
; CHECK-NEXT: call void @use(i8 [[NOTG]])
15241523
; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
15251524
; CHECK-NEXT: call void @use(i8 [[NOTB]])
1526-
; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]])
1527-
; CHECK-NEXT: [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]])
1528-
; CHECK-NEXT: [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
1525+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R]], i8 [[G]])
1526+
; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]])
1527+
; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]]
15291528
; CHECK-NEXT: ret i8 [[CK]]
15301529
;
15311530
%notr = xor i8 %r, -1

0 commit comments

Comments
 (0)