Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -4063,21 +4063,19 @@ 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 @@ 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 @@ 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}; Index: llvm/trunk/test/CodeGen/NVPTX/minmax-negative.ll =================================================================== --- llvm/trunk/test/CodeGen/NVPTX/minmax-negative.ll +++ llvm/trunk/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 +} Index: llvm/trunk/test/Transforms/InstCombine/minmax-fold.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/minmax-fold.ll +++ llvm/trunk/test/Transforms/InstCombine/minmax-fold.ll @@ -404,8 +404,8 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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