diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -48434,6 +48434,32 @@ if (SDValue R = combineLogicBlendIntoPBLENDV(N, DAG, Subtarget)) return R; + // (sext Cond) | C -> (zext (not Cond)) * (C + 1) - 1 if we can get a LEA out of it. + if (N0.getOpcode() == ISD::SUB && N0.hasOneUse() && + isNullConstant(N0.getOperand(0))) { + SDValue Cond = N0.getOperand(1); + if (Cond.getOpcode() == ISD::ZERO_EXTEND && Cond.hasOneUse()) + Cond = Cond.getOperand(0); + + if (Cond.getOpcode() == X86ISD::SETCC && Cond.hasOneUse()) { + if (ConstantSDNode *CN = dyn_cast(N1)) { + unsigned Val = CN->getZExtValue(); + if (Val == 1 || Val == 2 || Val == 3 || Val == 4 || Val == 7 || Val == 8) { + unsigned Scale = Val + 1; + + X86::CondCode CCode = (X86::CondCode)Cond.getConstantOperandVal(0); + CCode = X86::GetOppositeBranchCondition(CCode); + SDValue NotCond = getSETCC(CCode, Cond.getOperand(1), SDLoc(Cond), DAG); + + SDValue R = DAG.getZExtOrTrunc(NotCond, dl, VT); + R = DAG.getNode(ISD::MUL, dl, VT, R, DAG.getConstant(Scale, dl, VT)); + R = DAG.getNode(ISD::SUB, dl, VT, R, DAG.getConstant(1, dl, VT)); + return R; + } + } + } + } + // Combine OR(X,KSHIFTL(Y,Elts/2)) -> CONCAT_VECTORS(X,Y) == KUNPCK(X,Y). // Combine OR(KSHIFTL(X,Elts/2),Y) -> CONCAT_VECTORS(Y,X) == KUNPCK(Y,X). // iff the upper elements of the non-shifted arg are zero. diff --git a/llvm/test/CodeGen/X86/or-lea.ll b/llvm/test/CodeGen/X86/or-lea.ll --- a/llvm/test/CodeGen/X86/or-lea.ll +++ b/llvm/test/CodeGen/X86/or-lea.ll @@ -339,9 +339,8 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $43, %edi -; CHECK-NEXT: setge %al -; CHECK-NEXT: negl %eax -; CHECK-NEXT: orl $1, %eax +; CHECK-NEXT: setl %al +; CHECK-NEXT: leal -1(%rax,%rax), %eax ; CHECK-NEXT: retq %cmp = icmp sgt i32 %x, 42 %sext = sext i1 %cmp to i32 @@ -354,9 +353,8 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $43, %edi -; CHECK-NEXT: setge %al -; CHECK-NEXT: negl %eax -; CHECK-NEXT: orl $2, %eax +; CHECK-NEXT: setl %al +; CHECK-NEXT: leal -1(%rax,%rax,2), %eax ; CHECK-NEXT: retq %cmp = icmp sgt i32 %x, 42 %sext = sext i1 %cmp to i32 @@ -369,9 +367,8 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $43, %edi -; CHECK-NEXT: setge %al -; CHECK-NEXT: negl %eax -; CHECK-NEXT: orl $3, %eax +; CHECK-NEXT: setl %al +; CHECK-NEXT: leal -1(,%rax,4), %eax ; CHECK-NEXT: retq %cmp = icmp sgt i32 %x, 42 %sext = sext i1 %cmp to i32 @@ -384,9 +381,8 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $43, %edi -; CHECK-NEXT: setge %al -; CHECK-NEXT: negl %eax -; CHECK-NEXT: orl $4, %eax +; CHECK-NEXT: setl %al +; CHECK-NEXT: leal -1(%rax,%rax,4), %eax ; CHECK-NEXT: retq %cmp = icmp sgt i32 %x, 42 %sext = sext i1 %cmp to i32 @@ -399,9 +395,8 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $43, %edi -; CHECK-NEXT: setge %al -; CHECK-NEXT: negl %eax -; CHECK-NEXT: orl $7, %eax +; CHECK-NEXT: setl %al +; CHECK-NEXT: leal -1(,%rax,8), %eax ; CHECK-NEXT: retq %cmp = icmp sgt i32 %x, 42 %sext = sext i1 %cmp to i32 @@ -414,9 +409,8 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: cmpl $43, %edi -; CHECK-NEXT: setge %al -; CHECK-NEXT: negl %eax -; CHECK-NEXT: orl $8, %eax +; CHECK-NEXT: setl %al +; CHECK-NEXT: leal -1(%rax,%rax,8), %eax ; CHECK-NEXT: retq %cmp = icmp sgt i32 %x, 42 %sext = sext i1 %cmp to i32