mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[x86] add SBB optimization for SETBE (ule) condition code
x86 scalar select-of-constants (Cond ? C1 : C2) combining/lowering is a mess with missing optimizations. We handle some patterns, but miss logical variants. To clean that up, we should convert all select-of-constants to logic/math and enhance the combining for the expected patterns from that. Selecting 0 or -1 needs extra attention to produce the optimal code as shown here. Attempt to verify that all of these IR forms are logically equivalent: http://rise4fun.com/Alive/plxs Earlier steps in this series: rL306040 rL306072 rL307404 (D34652) As acknowledged in the earlier review, there's a possibility that some Intel uarch would prefer to produce an xor to clear the fake register operand with sbb %eax, %eax. This will likely need to be addressed in a separate pass. llvm-svn: 307471
This commit is contained in:
parent
0cc0979214
commit
0c17c0063e
@ -35027,7 +35027,19 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, SelectionDAG &DAG) {
|
||||
Y.getOperand(1));
|
||||
}
|
||||
|
||||
// TODO: Handle COND_BE if it was produced by X86ISD::SUB similar to below.
|
||||
SDValue EFLAGS = Y->getOperand(1);
|
||||
if (CC == X86::COND_BE && EFLAGS.getOpcode() == X86ISD::SUB &&
|
||||
EFLAGS.hasOneUse() && EFLAGS.getValueType().isInteger() &&
|
||||
!isa<ConstantSDNode>(EFLAGS.getOperand(1))) {
|
||||
// Swap the operands of a SUB, and we have the same pattern as above.
|
||||
// -1 + SETBE (SUB A, B) --> -1 + SETAE (SUB B, A) --> SBB %eax, %eax
|
||||
SDValue NewSub =
|
||||
DAG.getNode(X86ISD::SUB, SDLoc(EFLAGS), EFLAGS.getNode()->getVTList(),
|
||||
EFLAGS.getOperand(1), EFLAGS.getOperand(0));
|
||||
SDValue NewEFLAGS = SDValue(NewSub.getNode(), EFLAGS.getResNo());
|
||||
return DAG.getNode(X86ISD::SETCC_CARRY, DL, VT,
|
||||
DAG.getConstant(X86::COND_B, DL, MVT::i8), NewEFLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
if (CC == X86::COND_A) {
|
||||
|
@ -161,10 +161,8 @@ define i32 @uge_select_0_or_neg1(i32 %x, i32 %y) nounwind {
|
||||
define i32 @ule_select_0_or_neg1(i32 %x, i32 %y) nounwind {
|
||||
; CHECK-LABEL: ule_select_0_or_neg1:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: xorl %eax, %eax
|
||||
; CHECK-NEXT: cmpl %edi, %esi
|
||||
; CHECK-NEXT: setbe %al
|
||||
; CHECK-NEXT: decl %eax
|
||||
; CHECK-NEXT: cmpl %esi, %edi
|
||||
; CHECK-NEXT: sbbl %eax, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%cmp = icmp ule i32 %y, %x
|
||||
%ext = zext i1 %cmp to i32
|
||||
|
Loading…
Reference in New Issue
Block a user