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,
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()) {
Op->getOperand(1)).getValue(1);
}
default:
- default_case:
break;
}
}
}
+ // 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)
; 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
; 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