From 359c2dcf35cf7f06d68aa7d9f9e094da706439cd Mon Sep 17 00:00:00 2001 From: Artur Gainullin Date: Fri, 27 Oct 2017 20:53:41 +0000 Subject: [PATCH] Improve clamp recognition in ValueTracking. Summary: ValueTracking was recognizing not all variations of clamp. Swapping of true value and false value of select was added to fix this problem. The first patch was reverted because it caused miscompile in NVPTX target. Added corresponding test cases. Reviewers: spatel, majnemer, efriedma, reames Subscribers: llvm-commits, jholewinski Differential Revision: https://reviews.llvm.org/D39240 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316795 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ValueTracking.cpp | 38 +++++++++++++++------- test/CodeGen/NVPTX/minmax-negative.ll | 9 +++++ test/Transforms/InstCombine/minmax-fold.ll | 20 ++++++------ 3 files changed, 45 insertions(+), 22 deletions(-) create mode 100644 test/CodeGen/NVPTX/minmax-negative.ll diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 182377d39c0..3f53fc517e3 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -4063,21 +4063,19 @@ static SelectPatternResult matchFastFloatClamp(CmpInst::Predicate Pred, return {SPF_UNKNOWN, SPNB_NA, false}; } -/// Match non-obvious integer minimum and maximum sequences. -static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, - Value *CmpLHS, Value *CmpRHS, - Value *TrueVal, Value *FalseVal, - Value *&LHS, Value *&RHS) { - // Assume success. If there's no match, callers should not use these anyway. - LHS = TrueVal; - RHS = FalseVal; - - // Recognize variations of: - // CLAMP(v,l,h) ==> ((v) < (l) ? (l) : ((v) > (h) ? (h) : (v))) +/// Recognize variations of: +/// CLAMP(v,l,h) ==> ((v) < (l) ? (l) : ((v) > (h) ? (h) : (v))) +static SelectPatternResult matchClamp(CmpInst::Predicate Pred, + Value *CmpLHS, Value *CmpRHS, + Value *TrueVal, Value *FalseVal) { + // Swap the select operands and predicate to match the patterns below. + if (CmpRHS != TrueVal) { + Pred = ICmpInst::getSwappedPredicate(Pred); + std::swap(TrueVal, FalseVal); + } const APInt *C1; if (CmpRHS == TrueVal && match(CmpRHS, m_APInt(C1))) { const APInt *C2; - // (X SMAX(SMIN(X, C2), C1) if (match(FalseVal, m_SMin(m_Specific(CmpLHS), m_APInt(C2))) && C1->slt(*C2) && Pred == CmpInst::ICMP_SLT) @@ -4098,6 +4096,21 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, C1->ugt(*C2) && Pred == CmpInst::ICMP_UGT) return {SPF_UMIN, SPNB_NA, false}; } + return {SPF_UNKNOWN, SPNB_NA, false}; +} + +/// Match non-obvious integer minimum and maximum sequences. +static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, + Value *CmpLHS, Value *CmpRHS, + Value *TrueVal, Value *FalseVal, + Value *&LHS, Value *&RHS) { + // Assume success. If there's no match, callers should not use these anyway. + LHS = TrueVal; + RHS = FalseVal; + + SelectPatternResult SPR = matchClamp(Pred, CmpLHS, CmpRHS, TrueVal, FalseVal); + if (SPR.Flavor != SelectPatternFlavor::SPF_UNKNOWN) + return SPR; if (Pred != CmpInst::ICMP_SGT && Pred != CmpInst::ICMP_SLT) return {SPF_UNKNOWN, SPNB_NA, false}; @@ -4116,6 +4129,7 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, match(TrueVal, m_NSWSub(m_Specific(CmpLHS), m_Specific(CmpRHS)))) return {Pred == CmpInst::ICMP_SGT ? SPF_SMAX : SPF_SMIN, SPNB_NA, false}; + const APInt *C1; if (!match(CmpRHS, m_APInt(C1))) return {SPF_UNKNOWN, SPNB_NA, false}; diff --git a/test/CodeGen/NVPTX/minmax-negative.ll b/test/CodeGen/NVPTX/minmax-negative.ll new file mode 100644 index 00000000000..73bd9e049e7 --- /dev/null +++ b/test/CodeGen/NVPTX/minmax-negative.ll @@ -0,0 +1,9 @@ +; RUN: llc < %s -march=nvptx -O0 | FileCheck %s + +define i16 @test1(i16* %sur1) { +; CHECK-NOT: mov.u16 %rs{{[0-9]+}}, 32767 + %_tmp21.i = icmp sle i16 0, 0 + %_tmp22.i = select i1 %_tmp21.i, i16 0, i16 32767 + store i16 %_tmp22.i, i16* %sur1 + ret i16 0 +} diff --git a/test/Transforms/InstCombine/minmax-fold.ll b/test/Transforms/InstCombine/minmax-fold.ll index f80e989bcbd..6004a55f0f8 100644 --- a/test/Transforms/InstCombine/minmax-fold.ll +++ b/test/Transforms/InstCombine/minmax-fold.ll @@ -404,8 +404,8 @@ define i32 @clamp_signed3(i32 %x) { ; CHECK-LABEL: @clamp_signed3( ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X:%.*]], 255 ; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], i32 [[X]], i32 255 -; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], 15 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], i32 [[MIN]], i32 15 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[MIN]], 15 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[MIN]], i32 15 ; CHECK-NEXT: ret i32 [[R]] ; %cmp2 = icmp slt i32 %x, 255 @@ -421,8 +421,8 @@ define i32 @clamp_signed4(i32 %x) { ; CHECK-LABEL: @clamp_signed4( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X:%.*]], 15 ; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], i32 [[X]], i32 15 -; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X]], 255 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], i32 [[MAX]], i32 255 +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[MAX]], 255 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[MAX]], i32 255 ; CHECK-NEXT: ret i32 [[R]] ; %cmp2 = icmp sgt i32 %x, 15 @@ -472,8 +472,8 @@ define i32 @clamp_unsigned3(i32 %x) { ; CHECK-LABEL: @clamp_unsigned3( ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[X:%.*]], 255 ; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], i32 [[X]], i32 255 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[X]], 15 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], i32 [[MIN]], i32 15 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[MIN]], 15 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[MIN]], i32 15 ; CHECK-NEXT: ret i32 [[R]] ; %cmp2 = icmp ult i32 %x, 255 @@ -489,8 +489,8 @@ define i32 @clamp_unsigned4(i32 %x) { ; CHECK-LABEL: @clamp_unsigned4( ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[X:%.*]], 15 ; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], i32 [[X]], i32 15 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X]], 255 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], i32 [[MAX]], i32 255 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[MAX]], 255 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[MAX]], i32 255 ; CHECK-NEXT: ret i32 [[R]] ; %cmp2 = icmp ugt i32 %x, 15 @@ -523,8 +523,8 @@ define i32 @clamp_check_for_no_infinite_loop2(i32 %i) { ; CHECK-LABEL: @clamp_check_for_no_infinite_loop2( ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[I:%.*]], -255 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CMP1]], i32 [[I]], i32 -255 -; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 0 -; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP2]], i32 [[SEL1]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[SEL1]], 0 +; CHECK-NEXT: [[RES:%.*]] = select i1 [[TMP1]], i32 [[SEL1]], i32 0 ; CHECK-NEXT: ret i32 [[RES]] ; %cmp1 = icmp sgt i32 %i, -255 -- 2.50.1