diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index d0fd1046fdeb..8306e3a23f47 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -40939,8 +40939,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG, // (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. + // 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 @@ -40950,17 +40949,28 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG, // 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)) { ISD::CondCode CC = cast(Cond.getOperand(2))->get(); - if ((CC == ISD::SETGT && isNullConstant(RHS)) || + 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); + } } // Match VSELECTs into subs with unsigned saturation. diff --git a/llvm/test/CodeGen/X86/cmov.ll b/llvm/test/CodeGen/X86/cmov.ll index 41ebc322b430..b77d3c8e10e0 100644 --- a/llvm/test/CodeGen/X86/cmov.ll +++ b/llvm/test/CodeGen/X86/cmov.ll @@ -235,3 +235,27 @@ define i32 @pr47049_2(i32 %0) { %3 = select i1 %2, i32 %0, i32 -1 ret i32 %3 } + +define i32 @pr47049_3(i32 %0) { +; CHECK-LABEL: pr47049_3: +; CHECK: # %bb.0: +; CHECK-NEXT: testl %edi, %edi +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: cmovgl %edi, %eax +; CHECK-NEXT: retq + %2 = icmp sgt i32 %0, 1 + %3 = select i1 %2, i32 %0, i32 1 + ret i32 %3 +} + +define i32 @pr47049_4(i32 %0) { +; CHECK-LABEL: pr47049_4: +; CHECK: # %bb.0: +; CHECK-NEXT: testl %edi, %edi +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: cmovnel %edi, %eax +; CHECK-NEXT: retq + %2 = icmp ugt i32 %0, 1 + %3 = select i1 %2, i32 %0, i32 1 + ret i32 %3 +}