Cond = NewCond;
}
+ // Handle the following cases related to max and min:
+ // (a > b) ? (a-b) : 0
+ // (a >= b) ? (a-b) : 0
+ // (b < a) ? (a-b) : 0
+ // (b <= a) ? (a-b) : 0
+ // Comparison is removed to use EFLAGS from SUB.
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op2))
+ if (Cond.getOpcode() == X86ISD::SETCC &&
+ Cond.getOperand(1).getOpcode() == X86ISD::CMP &&
+ (Op1.getOpcode() == ISD::SUB || Op1.getOpcode() == X86ISD::SUB) &&
+ C->getAPIntValue() == 0) {
+ SDValue Cmp = Cond.getOperand(1);
+ unsigned CC = cast<ConstantSDNode>(Cond.getOperand(0))->getZExtValue();
+ if ((DAG.isEqualTo(Op1.getOperand(0), Cmp.getOperand(0)) &&
+ DAG.isEqualTo(Op1.getOperand(1), Cmp.getOperand(1)) &&
+ (CC == X86::COND_G || CC == X86::COND_GE ||
+ CC == X86::COND_A || CC == X86::COND_AE)) ||
+ (DAG.isEqualTo(Op1.getOperand(0), Cmp.getOperand(1)) &&
+ DAG.isEqualTo(Op1.getOperand(1), Cmp.getOperand(0)) &&
+ (CC == X86::COND_L || CC == X86::COND_LE ||
+ CC == X86::COND_B || CC == X86::COND_BE))) {
+
+ if (Op1.getOpcode() == ISD::SUB) {
+ SDVTList VTs = DAG.getVTList(Op1.getValueType(), MVT::i32);
+ SDValue New = DAG.getNode(X86ISD::SUB, DL, VTs,
+ Op1.getOperand(0), Op1.getOperand(1));
+ DAG.ReplaceAllUsesWith(Op1, New);
+ Op1 = New;
+ }
+
+ SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
+ unsigned NewCC = (CC == X86::COND_G || CC == X86::COND_GE ||
+ CC == X86::COND_L ||
+ CC == X86::COND_LE) ? X86::COND_GE : X86::COND_AE;
+ SDValue Ops[] = { Op2, Op1, DAG.getConstant(NewCC, MVT::i8),
+ SDValue(Op1.getNode(), 1) };
+ return DAG.getNode(X86ISD::CMOV, DL, VTs, Ops, array_lengthof(Ops));
+ }
+ }
+
// (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y
// (select (x == 0), y, -1) -> ~(sign_bit (x - 1)) | y
// (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y
%cond = select i1 %cmp, i32 %sub, i32 0
ret i32 %cond
}
+
+; rdar://10734411
+define i32 @h(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: h:
+; CHECK-NOT: cmp
+; CHECK: cmov
+ %cmp = icmp slt i32 %b, %a
+ %sub = sub nsw i32 %a, %b
+ %cond = select i1 %cmp, i32 %sub, i32 0
+ ret i32 %cond
+}
+define i32 @i(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: i:
+; CHECK-NOT: cmp
+; CHECK: cmov
+ %cmp = icmp sgt i32 %a, %b
+ %sub = sub nsw i32 %a, %b
+ %cond = select i1 %cmp, i32 %sub, i32 0
+ ret i32 %cond
+}
+define i32 @j(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: j:
+; CHECK-NOT: cmp
+; CHECK: cmov
+ %cmp = icmp ugt i32 %a, %b
+ %sub = sub i32 %a, %b
+ %cond = select i1 %cmp, i32 %sub, i32 0
+ ret i32 %cond
+}
+define i32 @k(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: k:
+; CHECK-NOT: cmp
+; CHECK: cmov
+ %cmp = icmp ult i32 %b, %a
+ %sub = sub i32 %a, %b
+ %cond = select i1 %cmp, i32 %sub, i32 0
+ ret i32 %cond
+}