[llvm] r285499 - [ValueTracking] recognize more variants of smin/smax
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 29 09:21:19 PDT 2016
Author: spatel
Date: Sat Oct 29 11:21:19 2016
New Revision: 285499
URL: http://llvm.org/viewvc/llvm-project?rev=285499&view=rev
Log:
[ValueTracking] recognize more variants of smin/smax
Try harder to detect obfuscated min/max patterns: the initial pattern was added with D9352 / rL236202.
There was a bug fix for PR27137 at rL264996, but I think we can do better by folding the corresponding
smax pattern and commuted variants.
The codegen tests demonstrate the effect of ValueTracking on the backend via SelectionDAGBuilder. We
can't expose these differences minimally in IR because we don't have smin/smax intrinsics for IR.
Differential Revision: https://reviews.llvm.org/D26091
Modified:
llvm/trunk/lib/Analysis/ValueTracking.cpp
llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll
llvm/trunk/test/Transforms/InstCombine/max-of-nots.ll
llvm/trunk/test/Transforms/InstCombine/select.ll
Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=285499&r1=285498&r2=285499&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Sat Oct 29 11:21:19 2016
@@ -3969,17 +3969,25 @@ static SelectPatternResult matchSelectPa
}
}
- // Y >s C ? ~Y : ~C == ~Y <s ~C ? ~Y : ~C = SMIN(~Y, ~C)
+ // (X >s C) ? ~X : ~C ==> (~X <s ~C) ? ~X : ~C ==> SMIN(~X, ~C)
+ // (X <s C) ? ~X : ~C ==> (~X >s ~C) ? ~X : ~C ==> SMAX(~X, ~C)
const APInt *C2;
- if (match(FalseVal, m_APInt(C2))) {
- if (Pred == ICmpInst::ICMP_SGT &&
- CmpRHS->getType() == FalseVal->getType() && ~(*C1) == *C2 &&
- (match(TrueVal, m_Not(m_Specific(CmpLHS))) ||
- match(CmpLHS, m_Not(m_Specific(TrueVal))))) {
- LHS = TrueVal;
- RHS = FalseVal;
- return {SPF_SMIN, SPNB_NA, false};
- }
+ if (match(TrueVal, m_Not(m_Specific(CmpLHS))) &&
+ match(FalseVal, m_APInt(C2)) && ~(*C1) == *C2 &&
+ (Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SLT)) {
+ LHS = TrueVal;
+ RHS = FalseVal;
+ return {Pred == CmpInst::ICMP_SGT ? SPF_SMIN : SPF_SMAX, SPNB_NA, false};
+ }
+
+ // (X >s C) ? ~C : ~X ==> (~X <s ~C) ? ~C : ~X ==> SMAX(~C, ~X)
+ // (X <s C) ? ~C : ~X ==> (~X >s ~C) ? ~C : ~X ==> SMIN(~C, ~X)
+ if (match(FalseVal, m_Not(m_Specific(CmpLHS))) &&
+ match(TrueVal, m_APInt(C2)) && ~(*C1) == *C2 &&
+ (Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SLT)) {
+ LHS = TrueVal;
+ RHS = FalseVal;
+ return {Pred == CmpInst::ICMP_SGT ? SPF_SMAX : SPF_SMIN, SPNB_NA, false};
}
}
Modified: llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll?rev=285499&r1=285498&r2=285499&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll (original)
+++ llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll Sat Oct 29 11:21:19 2016
@@ -18,16 +18,12 @@ define <4 x i32> @smin_vec1(<4 x i32> %x
ret <4 x i32> %sel
}
-; FIXME: These are signed min/max ops.
-
define <4 x i32> @smin_vec2(<4 x i32> %x) {
; CHECK-LABEL: smin_vec2:
; CHECK: # BB#0:
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm1
-; CHECK-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; CHECK-NEXT: vpcmpgtd %xmm0, %xmm2, %xmm0
-; CHECK-NEXT: vpor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vpminsd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: retq
;
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
@@ -40,11 +36,8 @@ define <4 x i32> @smax_vec1(<4 x i32> %x
; CHECK-LABEL: smax_vec1:
; CHECK: # BB#0:
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm2
-; CHECK-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; CHECK-NEXT: vpcmpgtd %xmm0, %xmm3, %xmm0
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
-; CHECK-NEXT: vpor %xmm2, %xmm0, %xmm0
+; CHECK-NEXT: vpmaxsd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: retq
;
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
@@ -57,10 +50,8 @@ define <4 x i32> @smax_vec2(<4 x i32> %x
; CHECK-LABEL: smax_vec2:
; CHECK: # BB#0:
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm1
-; CHECK-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; CHECK-NEXT: vpcmpgtd %xmm2, %xmm0, %xmm0
-; CHECK-NEXT: vpor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vpmaxsd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: retq
;
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
Modified: llvm/trunk/test/Transforms/InstCombine/max-of-nots.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/max-of-nots.ll?rev=285499&r1=285498&r2=285499&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/max-of-nots.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/max-of-nots.ll Sat Oct 29 11:21:19 2016
@@ -140,12 +140,7 @@ define i32 @max_of_min(i32 %a) {
; max(min(%a, -1), -1) == -1 (swap predicate and select ops)
define i32 @max_of_min_swap(i32 %a) {
; CHECK-LABEL: @max_of_min_swap(
-; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
-; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 %a, 0
-; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 -1, i32 [[NOT_A]]
-; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[S0]], -1
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 -1
-; CHECK-NEXT: ret i32 [[S1]]
+; CHECK-NEXT: ret i32 -1
;
%not_a = xor i32 %a, -1
%c0 = icmp slt i32 %a, 0
@@ -158,12 +153,7 @@ define i32 @max_of_min_swap(i32 %a) {
; min(max(%a, -1), -1) == -1
define i32 @min_of_max(i32 %a) {
; CHECK-LABEL: @min_of_max(
-; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
-; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 %a, 0
-; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 [[NOT_A]], i32 -1
-; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 [[S0]], -1
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 -1
-; CHECK-NEXT: ret i32 [[S1]]
+; CHECK-NEXT: ret i32 -1
;
%not_a = xor i32 %a, -1
%c0 = icmp slt i32 %a, 0
@@ -176,12 +166,7 @@ define i32 @min_of_max(i32 %a) {
; min(max(%a, -1), -1) == -1 (swap predicate and select ops)
define i32 @min_of_max_swap(i32 %a) {
; CHECK-LABEL: @min_of_max_swap(
-; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
-; CHECK-NEXT: [[C0:%.*]] = icmp sgt i32 %a, 0
-; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 -1, i32 [[NOT_A]]
-; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 [[S0]], -1
-; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 -1
-; CHECK-NEXT: ret i32 [[S1]]
+; CHECK-NEXT: ret i32 -1
;
%not_a = xor i32 %a, -1
%c0 = icmp sgt i32 %a, 0
Modified: llvm/trunk/test/Transforms/InstCombine/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/select.ll?rev=285499&r1=285498&r2=285499&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/select.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/select.ll Sat Oct 29 11:21:19 2016
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
; PR1822
@@ -1765,14 +1764,15 @@ define i32 @PR23757(i32 %x) {
ret i32 %sel
}
+; max(max(~a, -1), -1) --> max(~a, -1)
+
define i32 @PR27137(i32 %a) {
; CHECK-LABEL: @PR27137(
-; CHECK-NEXT: %not_a = xor i32 %a, -1
-; CHECK-NEXT: %c0 = icmp slt i32 %a, 0
-; CHECK-NEXT: %s0 = select i1 %c0, i32 %not_a, i32 -1
-; CHECK-NEXT: %c1 = icmp sgt i32 %s0, -1
-; CHECK-NEXT: %s1 = select i1 %c1, i32 %s0, i32 -1
-; CHECK-NEXT: ret i32 %s1
+; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
+; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 %a, 0
+; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 [[NOT_A]], i32 -1
+; CHECK-NEXT: ret i32 [[S0]]
+;
%not_a = xor i32 %a, -1
%c0 = icmp slt i32 %a, 0
More information about the llvm-commits
mailing list