Skip to content

Commit

Permalink
[X86] Use carry flag from add for (seteq (add X, -1), -1).
Browse files Browse the repository at this point in the history
If we just subtracted 1 and are checking if the result is -1. We can use the carry flag from the ADD instead of an explicit CMP. I'm using the same checks for the add users as EmitTest.

Fixes one case from PR44412

Differential Revision: https://reviews.llvm.org/D72019
  • Loading branch information
topperc committed Dec 31, 2019
1 parent 4ae3120 commit 1cc8a74
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 16 deletions.
41 changes: 31 additions & 10 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -20551,6 +20551,19 @@ static bool hasNonFlagsUse(SDValue Op) {
return false;
}

// Transform to an x86-specific ALU node with flags if there is a chance of
// using an RMW op or only the flags are used. Otherwise, leave
// the node alone and emit a 'cmp' or 'test' instruction.
static bool isProfitableToUseFlagOp(SDValue Op) {
for (SDNode *U : Op->uses())
if (U->getOpcode() != ISD::CopyToReg &&
U->getOpcode() != ISD::SETCC &&
U->getOpcode() != ISD::STORE)
return false;

return true;
}

/// Emit nodes that will be selected as "test Op0,Op0", or something
/// equivalent.
static SDValue EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl,
Expand Down Expand Up @@ -20614,15 +20627,8 @@ static SDValue EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl,
case ISD::SUB:
case ISD::OR:
case ISD::XOR:
// Transform to an x86-specific ALU node with flags if there is a chance of
// using an RMW op or only the flags are used. Otherwise, leave
// the node alone and emit a 'test' instruction.
for (SDNode::use_iterator UI = Op.getNode()->use_begin(),
UE = Op.getNode()->use_end(); UI != UE; ++UI)
if (UI->getOpcode() != ISD::CopyToReg &&
UI->getOpcode() != ISD::SETCC &&
UI->getOpcode() != ISD::STORE)
goto default_case;
if (!isProfitableToUseFlagOp(Op))
break;

// Otherwise use a regular EFLAGS-setting instruction.
switch (ArithOp.getOpcode()) {
Expand Down Expand Up @@ -20650,7 +20656,6 @@ static SDValue EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl,
Op->getOperand(1)).getValue(1);
}
default:
default_case:
break;
}

Expand Down Expand Up @@ -21688,6 +21693,22 @@ SDValue X86TargetLowering::emitFlagsForSetcc(SDValue Op0, SDValue Op1,
}
}

// Try to use the carry flag from the add in place of an separate CMP for:
// (seteq (add X, -1), -1). Similar for setne.
if (isAllOnesConstant(Op1) && Op0.getOpcode() == ISD::ADD &&
Op0.getOperand(1) == Op1 && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
if (isProfitableToUseFlagOp(Op0)) {
SDVTList VTs = DAG.getVTList(Op0.getValueType(), MVT::i32);

SDValue New = DAG.getNode(X86ISD::ADD, dl, VTs, Op0.getOperand(0),
Op0.getOperand(1));
DAG.ReplaceAllUsesOfValueWith(SDValue(Op0.getNode(), 0), New);
X86::CondCode CCode = CC == ISD::SETEQ ? X86::COND_AE : X86::COND_B;
X86CC = DAG.getTargetConstant(CCode, dl, MVT::i8);
return SDValue(New.getNode(), 1);
}
}

bool IsFP = Op1.getSimpleValueType().isFloatingPoint();
X86::CondCode CondCode = TranslateX86CC(CC, dl, IsFP, Op0, Op1, DAG);
if (CondCode == X86::COND_INVALID)
Expand Down
10 changes: 4 additions & 6 deletions llvm/test/CodeGen/X86/pr44412.ll
Expand Up @@ -14,9 +14,8 @@ define void @bar(i32 %0, i32 %1) nounwind {
; CHECK-NEXT: .LBB0_2: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: movl %ebx, %edi
; CHECK-NEXT: callq foo
; CHECK-NEXT: decl %ebx
; CHECK-NEXT: cmpl $-1, %ebx
; CHECK-NEXT: jne .LBB0_2
; CHECK-NEXT: addl $-1, %ebx
; CHECK-NEXT: jb .LBB0_2
; CHECK-NEXT: .LBB0_3:
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
Expand Down Expand Up @@ -47,9 +46,8 @@ define void @baz(i32 %0, i32 %1) nounwind {
; CHECK-NEXT: .LBB1_2: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: movl %ebx, %edi
; CHECK-NEXT: callq foo
; CHECK-NEXT: decl %ebx
; CHECK-NEXT: cmpl $-1, %ebx
; CHECK-NEXT: je .LBB1_2
; CHECK-NEXT: addl $-1, %ebx
; CHECK-NEXT: jae .LBB1_2
; CHECK-NEXT: .LBB1_3:
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
Expand Down

0 comments on commit 1cc8a74

Please sign in to comment.