mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
X86: optimization for max-like struct
This patch will optimize the following cases on X86 (a > b) ? (a-b) : 0 (a >= b) ? (a-b) : 0 (b < a) ? (a-b) : 0 (b <= a) ? (a-b) : 0 FROM movl %edi, %ecx subl %esi, %ecx cmpl %edi, %esi movl $0, %eax cmovll %ecx, %eax TO xorl %eax, %eax subl %esi, %edi cmovll %eax, %edi movl %edi, %eax rdar: 10734411 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155919 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d07d06ceef
commit
769ea2f93f
@ -8573,6 +8573,46 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
||||
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
|
||||
|
@ -32,3 +32,45 @@ entry:
|
||||
%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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user