From: Simon Pilgrim Date: Thu, 17 Jun 2021 12:17:51 +0000 (+0100) Subject: [X86] combineSelect - refactor MIN/MAX detection code to make it easier to add additi... X-Git-Tag: llvmorg-14-init~3713 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cdb4fcf9a19ca35b50754791f3986337046d9406;p=platform%2Fupstream%2Fllvm.git [X86] combineSelect - refactor MIN/MAX detection code to make it easier to add additional select(setcc,x,y) folds. NFCI. I need to add some additional handling to address some of the regressions from D101074 --- diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 66c91f8..5477c80 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -41796,41 +41796,44 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG, if (SDValue V = combineSelectOfTwoConstants(N, DAG)) return V; - // Canonicalize min/max: - // (x > 0) ? x : 0 -> (x >= 0) ? x : 0 - // (x < -1) ? x : -1 -> (x <= -1) ? x : -1 - // This allows use of COND_S / COND_NS (see TranslateX86CC) which eliminates - // the need for an extra compare against zero. e.g. - // (a - b) > 0 : (a - b) ? 0 -> (a - b) >= 0 : (a - b) ? 0 - // subl %esi, %edi - // testl %edi, %edi - // movl $0, %eax - // cmovgl %edi, %eax - // => - // xorl %eax, %eax - // subl %esi, $edi - // cmovsl %eax, %edi - // - // We can also canonicalize - // (x s> 1) ? x : 1 -> (x s>= 1) ? x : 1 -> (x s> 0) ? x : 1 - // (x u> 1) ? x : 1 -> (x u>= 1) ? x : 1 -> (x != 0) ? x : 1 - // This allows the use of a test instruction for the compare. if (N->getOpcode() == ISD::SELECT && Cond.getOpcode() == ISD::SETCC && - Cond.hasOneUse() && - LHS == Cond.getOperand(0) && RHS == Cond.getOperand(1)) { + Cond.hasOneUse()) { + EVT CondVT = Cond.getValueType(); + SDValue Cond0 = Cond.getOperand(0); + SDValue Cond1 = Cond.getOperand(1); ISD::CondCode CC = cast(Cond.getOperand(2))->get(); - if ((CC == ISD::SETGT && (isNullConstant(RHS) || isOneConstant(RHS))) || - (CC == ISD::SETLT && isAllOnesConstant(RHS))) { - ISD::CondCode NewCC = CC == ISD::SETGT ? ISD::SETGE : ISD::SETLE; - Cond = DAG.getSetCC(SDLoc(Cond), Cond.getValueType(), - Cond.getOperand(0), Cond.getOperand(1), NewCC); - return DAG.getSelect(DL, VT, Cond, LHS, RHS); - } - if (CC == ISD::SETUGT && isOneConstant(RHS)) { - ISD::CondCode NewCC = ISD::SETUGE; - Cond = DAG.getSetCC(SDLoc(Cond), Cond.getValueType(), - Cond.getOperand(0), Cond.getOperand(1), NewCC); - return DAG.getSelect(DL, VT, Cond, LHS, RHS); + + // Canonicalize min/max: + // (x > 0) ? x : 0 -> (x >= 0) ? x : 0 + // (x < -1) ? x : -1 -> (x <= -1) ? x : -1 + // This allows use of COND_S / COND_NS (see TranslateX86CC) which eliminates + // the need for an extra compare against zero. e.g. + // (a - b) > 0 : (a - b) ? 0 -> (a - b) >= 0 : (a - b) ? 0 + // subl %esi, %edi + // testl %edi, %edi + // movl $0, %eax + // cmovgl %edi, %eax + // => + // xorl %eax, %eax + // subl %esi, $edi + // cmovsl %eax, %edi + // + // We can also canonicalize + // (x s> 1) ? x : 1 -> (x s>= 1) ? x : 1 -> (x s> 0) ? x : 1 + // (x u> 1) ? x : 1 -> (x u>= 1) ? x : 1 -> (x != 0) ? x : 1 + // This allows the use of a test instruction for the compare. + if (LHS == Cond0 && RHS == Cond1) { + if ((CC == ISD::SETGT && (isNullConstant(RHS) || isOneConstant(RHS))) || + (CC == ISD::SETLT && isAllOnesConstant(RHS))) { + ISD::CondCode NewCC = CC == ISD::SETGT ? ISD::SETGE : ISD::SETLE; + Cond = DAG.getSetCC(SDLoc(Cond), CondVT, Cond0, Cond1, NewCC); + return DAG.getSelect(DL, VT, Cond, LHS, RHS); + } + if (CC == ISD::SETUGT && isOneConstant(RHS)) { + ISD::CondCode NewCC = ISD::SETUGE; + Cond = DAG.getSetCC(SDLoc(Cond), CondVT, Cond0, Cond1, NewCC); + return DAG.getSelect(DL, VT, Cond, LHS, RHS); + } } }