mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-26 23:32:58 +00:00
Improve an integer select optimization in two ways:
1. generalize (select (x == 0), -1, 0) -> (sign_bit (x - 1)) to: (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y 2. Handle the identical pattern that happens with !=: (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y cmov is often high latency and can't fold immediates or memory operands. For example for (x == 0) ? -1 : 1, before we got: < testb %sil, %sil < movl $-1, %ecx < movl $1, %eax < cmovel %ecx, %eax now we get: > cmpb $1, %sil > sbbl %eax, %eax > orl $1, %eax git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120929 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bced6a1b8f
commit
a2b5600e61
@ -7208,10 +7208,17 @@ static bool isX86LogicalCmp(SDValue Op) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isZero(SDValue V) {
|
||||||
|
ConstantSDNode *C = dyn_cast<ConstantSDNode>(V);
|
||||||
|
return C && C->isNullValue();
|
||||||
|
}
|
||||||
|
|
||||||
SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
||||||
bool addTest = true;
|
bool addTest = true;
|
||||||
SDValue Cond = Op.getOperand(0);
|
SDValue Cond = Op.getOperand(0);
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
SDValue Op1 = Op.getOperand(1);
|
||||||
|
SDValue Op2 = Op.getOperand(2);
|
||||||
|
DebugLoc DL = Op.getDebugLoc();
|
||||||
SDValue CC;
|
SDValue CC;
|
||||||
|
|
||||||
if (Cond.getOpcode() == ISD::SETCC) {
|
if (Cond.getOpcode() == ISD::SETCC) {
|
||||||
@ -7220,30 +7227,35 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
Cond = NewCond;
|
Cond = NewCond;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (select (x == 0), -1, 0) -> (sign_bit (x - 1))
|
// (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y
|
||||||
SDValue Op1 = Op.getOperand(1);
|
// (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y
|
||||||
SDValue Op2 = Op.getOperand(2);
|
|
||||||
if (Cond.getOpcode() == X86ISD::SETCC &&
|
if (Cond.getOpcode() == X86ISD::SETCC &&
|
||||||
cast<ConstantSDNode>(Cond.getOperand(0))->getZExtValue() == X86::COND_E) {
|
Cond.getOperand(1).getOpcode() == X86ISD::CMP) {
|
||||||
SDValue Cmp = Cond.getOperand(1);
|
SDValue Cmp = Cond.getOperand(1);
|
||||||
if (Cmp.getOpcode() == X86ISD::CMP) {
|
|
||||||
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(Op1);
|
unsigned CondCode =cast<ConstantSDNode>(Cond.getOperand(0))->getZExtValue();
|
||||||
|
|
||||||
|
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(Op1);
|
||||||
|
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(Op2);
|
||||||
|
if ((N1C && N1C->isAllOnesValue() && CondCode == X86::COND_E) ||
|
||||||
|
(N2C && N2C->isAllOnesValue() && CondCode == X86::COND_NE)) {
|
||||||
|
SDValue Y = CondCode == X86::COND_NE ? Op1 : Op2;
|
||||||
|
|
||||||
|
SDValue CmpOp0 = Cmp.getOperand(0);
|
||||||
|
Cmp = DAG.getNode(X86ISD::CMP, DL, MVT::i32,
|
||||||
|
CmpOp0, DAG.getConstant(1, CmpOp0.getValueType()));
|
||||||
|
|
||||||
|
SDValue Res =
|
||||||
|
DAG.getNode(X86ISD::SETCC_CARRY, DL, Op.getValueType(),
|
||||||
|
DAG.getConstant(X86::COND_B, MVT::i8), Cmp);
|
||||||
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(Op2);
|
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(Op2);
|
||||||
ConstantSDNode *RHSC =
|
if (N2C == 0 || !N2C->isNullValue())
|
||||||
dyn_cast<ConstantSDNode>(Cmp.getOperand(1).getNode());
|
Res = DAG.getNode(ISD::OR, DL, Res.getValueType(), Res, Y);
|
||||||
if (N1C && N1C->isAllOnesValue() &&
|
return Res;
|
||||||
N2C && N2C->isNullValue() &&
|
|
||||||
RHSC && RHSC->isNullValue()) {
|
|
||||||
SDValue CmpOp0 = Cmp.getOperand(0);
|
|
||||||
Cmp = DAG.getNode(X86ISD::CMP, dl, MVT::i32,
|
|
||||||
CmpOp0, DAG.getConstant(1, CmpOp0.getValueType()));
|
|
||||||
return DAG.getNode(X86ISD::SETCC_CARRY, dl, Op.getValueType(),
|
|
||||||
DAG.getConstant(X86::COND_B, MVT::i8), Cmp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look pass (and (setcc_carry (cmp ...)), 1).
|
// Look past (and (setcc_carry (cmp ...)), 1).
|
||||||
if (Cond.getOpcode() == ISD::AND &&
|
if (Cond.getOpcode() == ISD::AND &&
|
||||||
Cond.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY) {
|
Cond.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY) {
|
||||||
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Cond.getOperand(1));
|
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Cond.getOperand(1));
|
||||||
@ -7281,7 +7293,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
// We know the result of AND is compared against zero. Try to match
|
// We know the result of AND is compared against zero. Try to match
|
||||||
// it to BT.
|
// it to BT.
|
||||||
if (Cond.getOpcode() == ISD::AND && Cond.hasOneUse()) {
|
if (Cond.getOpcode() == ISD::AND && Cond.hasOneUse()) {
|
||||||
SDValue NewSetCC = LowerToBT(Cond, ISD::SETNE, dl, DAG);
|
SDValue NewSetCC = LowerToBT(Cond, ISD::SETNE, DL, DAG);
|
||||||
if (NewSetCC.getNode()) {
|
if (NewSetCC.getNode()) {
|
||||||
CC = NewSetCC.getOperand(0);
|
CC = NewSetCC.getOperand(0);
|
||||||
Cond = NewSetCC.getOperand(1);
|
Cond = NewSetCC.getOperand(1);
|
||||||
@ -7299,7 +7311,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
// condition is true.
|
// condition is true.
|
||||||
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
|
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
|
||||||
SDValue Ops[] = { Op2, Op1, CC, Cond };
|
SDValue Ops[] = { Op2, Op1, CC, Cond };
|
||||||
return DAG.getNode(X86ISD::CMOV, dl, VTs, Ops, array_lengthof(Ops));
|
return DAG.getNode(X86ISD::CMOV, DL, VTs, Ops, array_lengthof(Ops));
|
||||||
}
|
}
|
||||||
|
|
||||||
// isAndOrOfSingleUseSetCCs - Return true if node is an ISD::AND or
|
// isAndOrOfSingleUseSetCCs - Return true if node is an ISD::AND or
|
||||||
|
@ -86,6 +86,7 @@ define x86_fp80 @test7(i32 %tmp8) nounwind {
|
|||||||
%tmp9 = icmp sgt i32 %tmp8, -1 ; <i1> [#uses=1]
|
%tmp9 = icmp sgt i32 %tmp8, -1 ; <i1> [#uses=1]
|
||||||
%retval = select i1 %tmp9, x86_fp80 0xK4005B400000000000000, x86_fp80 0xK40078700000000000000
|
%retval = select i1 %tmp9, x86_fp80 0xK4005B400000000000000, x86_fp80 0xK40078700000000000000
|
||||||
ret x86_fp80 %retval
|
ret x86_fp80 %retval
|
||||||
|
; CHECK: test7:
|
||||||
; CHECK: leaq
|
; CHECK: leaq
|
||||||
; CHECK: fldt (%r{{.}}x,%r{{.}}x)
|
; CHECK: fldt (%r{{.}}x,%r{{.}}x)
|
||||||
}
|
}
|
||||||
@ -96,4 +97,61 @@ define void @test8(i1 %c, <6 x i32>* %dst.addr, <6 x i32> %src1,<6 x i32> %src2)
|
|||||||
%val = sub <6 x i32> %x, < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
|
%val = sub <6 x i32> %x, < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
|
||||||
store <6 x i32> %val, <6 x i32>* %dst.addr
|
store <6 x i32> %val, <6 x i32>* %dst.addr
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
|
; CHECK: test8:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
;; Test integer select between values and constants.
|
||||||
|
|
||||||
|
define i64 @test9(i64 %x, i64 %y) nounwind readnone ssp noredzone {
|
||||||
|
%cmp = icmp ne i64 %x, 0
|
||||||
|
%cond = select i1 %cmp, i64 %y, i64 -1
|
||||||
|
ret i64 %cond
|
||||||
|
; CHECK: test9:
|
||||||
|
; CHECK: cmpq $1, %rdi
|
||||||
|
; CHECK: sbbq %rax, %rax
|
||||||
|
; CHECK: orq %rsi, %rax
|
||||||
|
; CHECK: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
;; Same as test9
|
||||||
|
define i64 @test9a(i64 %x, i64 %y) nounwind readnone ssp noredzone {
|
||||||
|
%cmp = icmp eq i64 %x, 0
|
||||||
|
%cond = select i1 %cmp, i64 -1, i64 %y
|
||||||
|
ret i64 %cond
|
||||||
|
; CHECK: test9a:
|
||||||
|
; CHECK: cmpq $1, %rdi
|
||||||
|
; CHECK: sbbq %rax, %rax
|
||||||
|
; CHECK: orq %rsi, %rax
|
||||||
|
; CHECK: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @test9b(i64 %x, i64 %y) nounwind readnone ssp noredzone {
|
||||||
|
%cmp = icmp eq i64 %x, 0
|
||||||
|
%A = sext i1 %cmp to i64
|
||||||
|
%cond = or i64 %y, %A
|
||||||
|
ret i64 %cond
|
||||||
|
; CHECK: test9b:
|
||||||
|
; CHECK: cmpq $1, %rdi
|
||||||
|
; CHECK: sbbq %rax, %rax
|
||||||
|
; CHECK: orq %rsi, %rax
|
||||||
|
; CHECK: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
;; Select between -1 and 1.
|
||||||
|
define i64 @test10(i64 %x, i64 %y) nounwind readnone ssp noredzone {
|
||||||
|
%cmp = icmp eq i64 %x, 0
|
||||||
|
%cond = select i1 %cmp, i64 -1, i64 1
|
||||||
|
ret i64 %cond
|
||||||
|
; CHECK: test10:
|
||||||
|
; CHECK: cmpq $1, %rdi
|
||||||
|
; CHECK: sbbq %rax, %rax
|
||||||
|
; CHECK: orq $1, %rax
|
||||||
|
; CHECK: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user