[PATCH] D26096: [ValueTracking] recognize obfuscated variants of umin/umax
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 28 12:45:14 PDT 2016
spatel created this revision.
spatel added reviewers: efriedma, majnemer, sanjoy.
spatel added a subscriber: llvm-commits.
Herald added a subscriber: mcrosier.
The smallest tests that I could find to expose this are codegen tests (because SelectionDAGBuilder::visitSelect() uses matchSelectPattern to create UMAX/UMIN nodes), so I've semi-arbitrarily chosen x86 as the target for the regression tests.
If these were written as unsigned compares in IR, InstCombine canonicalizes the unsigned compares to signed compares. Ie, running the optimizer pessimizes the codegen for this case on trunk:
define <4 x i32> @umax_vec(<4 x i32> %x) {
%cmp = icmp ugt <4 x i32> %x, <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
%sel = select <4 x i1> %cmp, <4 x i32> %x, <4 x i32> <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
ret <4 x i32> %sel
}
$ ./opt umax.ll -S | ./llc -o - -mattr=avx
vpmaxud LCPI0_0(%rip), %xmm0, %xmm0
$ ./opt -instcombine umax.ll -S | ./llc -o - -mattr=avx
vpxor %xmm1, %xmm1, %xmm1
vpcmpgtd %xmm0, %xmm1, %xmm1
vmovaps LCPI0_0(%rip), %xmm2 ## xmm2 = [2147483647,2147483647,2147483647,2147483647]
vblendvps %xmm1, %xmm0, %xmm2, %xmm0
https://reviews.llvm.org/D26096
Files:
lib/Analysis/ValueTracking.cpp
test/CodeGen/X86/vec_umin_umax.ll
Index: test/CodeGen/X86/vec_umin_umax.ll
===================================================================
--- test/CodeGen/X86/vec_umin_umax.ll
+++ test/CodeGen/X86/vec_umin_umax.ll
@@ -1,15 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s
-; FIXME: These are unsigned min/max ops.
-
define <4 x i32> @umax_vec1(<4 x i32> %x) {
; CHECK-LABEL: umax_vec1:
; CHECK: # BB#0:
-; CHECK-NEXT: vpxor %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm1
-; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [2147483647,2147483647,2147483647,2147483647]
-; CHECK-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0
+; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm0
; CHECK-NEXT: retq
;
%cmp = icmp slt <4 x i32> %x, zeroinitializer
@@ -20,9 +15,7 @@
define <4 x i32> @umax_vec2(<4 x i32> %x) {
; CHECK-LABEL: umax_vec2:
; CHECK: # BB#0:
-; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %xmm1
-; CHECK-NEXT: vblendvps %xmm1, {{.*}}(%rip), %xmm0, %xmm0
+; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm0
; CHECK-NEXT: retq
;
%cmp = icmp sgt <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
@@ -33,9 +26,7 @@
define <4 x i32> @umin_vec1(<4 x i32> %x) {
; CHECK-LABEL: umin_vec1:
; CHECK: # BB#0:
-; CHECK-NEXT: vpxor %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm1
-; CHECK-NEXT: vblendvps %xmm1, {{.*}}(%rip), %xmm0, %xmm0
+; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0
; CHECK-NEXT: retq
;
%cmp = icmp slt <4 x i32> %x, zeroinitializer
@@ -46,10 +37,7 @@
define <4 x i32> @umin_vec2(<4 x i32> %x) {
; CHECK-LABEL: umin_vec2:
; CHECK: # BB#0:
-; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %xmm1
-; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648]
-; CHECK-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0
+; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0
; CHECK-NEXT: retq
;
%cmp = icmp sgt <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -3981,6 +3981,29 @@
return {SPF_SMIN, SPNB_NA, false};
}
}
+
+ // An unsigned min/max can be written with a signed compare.
+ if ((CmpLHS == TrueVal && match(FalseVal, m_APInt(C2))) ||
+ (CmpLHS == FalseVal && match(TrueVal, m_APInt(C2)))) {
+ // Is the sign bit set?
+ // (X <s 0) ? X : MAXVAL ==> (X >u MAXVAL) ? X : MAXVAL ==> UMAX
+ // (X <s 0) ? MAXVAL : X ==> (X >u MAXVAL) ? MAXVAL : X ==> UMIN
+ if (Pred == CmpInst::ICMP_SLT && *C1 == 0 && C2->isMaxSignedValue()) {
+ LHS = TrueVal;
+ RHS = FalseVal;
+ return {TrueVal == CmpLHS ? SPF_UMAX : SPF_UMIN, SPNB_NA, false};
+ }
+
+ // Is the sign bit clear?
+ // (X >s -1) ? X : MINVAL ==> (X <u MINVAL) ? X : MINVAL ==> UMIN
+ // (X >s -1) ? MINVAL : X ==> (X <u MINVAL) ? MINVAL : X ==> UMAX
+ if (Pred == CmpInst::ICMP_SGT && C1->isAllOnesValue() &&
+ C2->isMinSignedValue()) {
+ LHS = TrueVal;
+ RHS = FalseVal;
+ return {TrueVal == CmpLHS ? SPF_UMIN : SPF_UMAX, SPNB_NA, false};
+ }
+ }
}
// TODO: (X > 4) ? X : 5 --> (X >= 5) ? X : 5 --> MAX(X, 5)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26096.76236.patch
Type: text/x-patch
Size: 3503 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161028/cf0353ec/attachment.bin>
More information about the llvm-commits
mailing list