[PATCH] D109058: [InstCombine] use isFreeToInvert to generalize min/max with 'not'
Sanjay Patel via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 1 05:59:58 PDT 2021
spatel created this revision.
spatel added reviewers: lebedev.ri, t.p.northover, nikic, dmgreen.
Herald added subscribers: hiraditya, mcrosier.
spatel requested review of this revision.
Herald added a project: LLVM.
This mimics the code for the corresponding cmp-select idiom.
This also prevents an infinite loop because isFreeToInvert does not match constant expressions.
So this patch solves the same problem as D108814 <https://reviews.llvm.org/D108814> and would overwrite it, but my main motivation is to enhance the pattern matching to allow more invertible ops. I'll post that change as a follow-up patch on top of this one.
https://reviews.llvm.org/D109058
Files:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
Index: llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
===================================================================
--- llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
+++ llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
@@ -411,7 +411,7 @@
; CHECK-LABEL: @umax_of_nots(
; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: call void @use(i8 [[NOTX]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y:%.*]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X]])
; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1
; CHECK-NEXT: ret i8 [[M]]
;
@@ -548,6 +548,19 @@
ret i8 %m2
}
+; Negative test - don't infinite loop on constant expression
+
+define i8 @umin_of_not_and_nontrivial_const(i8 %x) {
+; CHECK-LABEL: @umin_of_not_and_nontrivial_const(
+; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 ptrtoint (i8 (i8)* @umin_of_not_and_nontrivial_const to i8))
+; CHECK-NEXT: ret i8 [[M]]
+;
+ %notx = xor i8 %x, -1
+ %m = call i8 @llvm.umin.i8(i8 ptrtoint (i8(i8)* @umin_of_not_and_nontrivial_const to i8), i8 %notx)
+ ret i8 %m
+}
+
; Negative test - too many uses
define i8 @umin_of_not_and_const_uses(i8 %x) {
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1076,21 +1076,31 @@
}
}
- if (match(I0, m_Not(m_Value(X)))) {
- // max (not X), (not Y) --> not (min X, Y)
- Intrinsic::ID InvID = getInverseMinMaxIntrinsic(IID);
- if (match(I1, m_Not(m_Value(Y))) &&
- (I0->hasOneUse() || I1->hasOneUse())) {
- Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, Y);
- return BinaryOperator::CreateNot(InvMaxMin);
- }
- // max (not X), C --> not(min X, ~C)
- if (match(I1, m_Constant(C)) && I0->hasOneUse()) {
- Constant *NotC = ConstantExpr::getNot(C);
- Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, NotC);
+ // If we can eliminate ~A and Y is free to invert:
+ // max ~A, Y --> ~(min A, ~Y)
+ //
+ // Examples:
+ // max ~A, ~Y --> ~(min A, Y)
+ // max ~A, C --> ~(min A, ~C)
+ auto moveNotAfterMinMax = [&](Value *X, Value *Y) -> Instruction * {
+ Value *A;
+ if (match(X, m_OneUse(m_Not(m_Value(A)))) &&
+ !isFreeToInvert(A, A->hasOneUse()) &&
+ // Passing false to only consider m_Not and constants.
+ // TODO: Allow Y to match other patterns by checking use count.
+ isFreeToInvert(Y, false)) {
+ Value *NotY = Builder.CreateNot(Y);
+ Intrinsic::ID InvID = getInverseMinMaxIntrinsic(IID);
+ Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, A, NotY);
return BinaryOperator::CreateNot(InvMaxMin);
}
- }
+ return nullptr;
+ };
+
+ if (Instruction *I = moveNotAfterMinMax(I0, I1))
+ return I;
+ if (Instruction *I = moveNotAfterMinMax(I1, I0))
+ return I;
// smax(X, -X) --> abs(X)
// smin(X, -X) --> -abs(X)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D109058.369911.patch
Type: text/x-patch
Size: 3238 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210901/a3d524f5/attachment.bin>
More information about the llvm-commits
mailing list