mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
Add some x86 specific dagcombines for conditional increments.
(add Y, (sete X, 0)) -> cmp X, 1; adc 0, Y (add Y, (setne X, 0)) -> cmp X, 1; sbb -1, Y (sub (sete X, 0), Y) -> cmp X, 1; sbb 0, Y (sub (setne X, 0), Y) -> cmp X, 1; adc -1, Y for unsigned foo(unsigned a, unsigned b) { if (a == 0) b++; return b; } we now get: foo: cmpl $1, %edi movl %esi, %eax adcl $0, %eax ret instead of: foo: testl %edi, %edi sete %al movzbl %al, %eax addl %esi, %eax ret llvm-svn: 122364
This commit is contained in:
parent
fd119319ea
commit
369872edfc
@ -969,6 +969,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
||||
setTargetDAGCombine(ISD::SRL);
|
||||
setTargetDAGCombine(ISD::OR);
|
||||
setTargetDAGCombine(ISD::AND);
|
||||
setTargetDAGCombine(ISD::ADD);
|
||||
setTargetDAGCombine(ISD::SUB);
|
||||
setTargetDAGCombine(ISD::STORE);
|
||||
setTargetDAGCombine(ISD::ZERO_EXTEND);
|
||||
if (Subtarget->is64Bit())
|
||||
@ -11513,6 +11515,44 @@ static SDValue PerformADCCombine(SDNode *N, SelectionDAG &DAG,
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// fold (add Y, (sete X, 0)) -> adc 0, Y
|
||||
// (add Y, (setne X, 0)) -> sbb -1, Y
|
||||
// (sub (sete X, 0), Y) -> sbb 0, Y
|
||||
// (sub (setne X, 0), Y) -> adc -1, Y
|
||||
static SDValue OptimizeConditonalInDecrement(SDNode *N, SelectionDAG &DAG) {
|
||||
DebugLoc DL = N->getDebugLoc();
|
||||
|
||||
// Look through ZExts.
|
||||
SDValue Ext = N->getOperand(N->getOpcode() == ISD::SUB ? 1 : 0);
|
||||
if (Ext.getOpcode() != ISD::ZERO_EXTEND || !Ext.hasOneUse())
|
||||
return SDValue();
|
||||
|
||||
SDValue SetCC = Ext.getOperand(0);
|
||||
if (SetCC.getOpcode() != X86ISD::SETCC || !SetCC.hasOneUse())
|
||||
return SDValue();
|
||||
|
||||
X86::CondCode CC = (X86::CondCode)SetCC.getConstantOperandVal(0);
|
||||
if (CC != X86::COND_E && CC != X86::COND_NE)
|
||||
return SDValue();
|
||||
|
||||
SDValue Cmp = SetCC.getOperand(1);
|
||||
if (Cmp.getOpcode() != X86ISD::CMP || !Cmp.hasOneUse() ||
|
||||
!X86::isZeroNode(Cmp.getOperand(1)))
|
||||
return SDValue();
|
||||
|
||||
SDValue CmpOp0 = Cmp.getOperand(0);
|
||||
SDValue NewCmp = DAG.getNode(X86ISD::CMP, DL, MVT::i32, CmpOp0,
|
||||
DAG.getConstant(1, CmpOp0.getValueType()));
|
||||
|
||||
SDValue OtherVal = N->getOperand(N->getOpcode() == ISD::SUB ? 0 : 1);
|
||||
if (CC == X86::COND_NE)
|
||||
return DAG.getNode(N->getOpcode() == ISD::SUB ? X86ISD::ADC : X86ISD::SBB,
|
||||
DL, OtherVal.getValueType(), OtherVal,
|
||||
DAG.getConstant(-1ULL, OtherVal.getValueType()), NewCmp);
|
||||
return DAG.getNode(N->getOpcode() == ISD::SUB ? X86ISD::SBB : X86ISD::ADC,
|
||||
DL, OtherVal.getValueType(), OtherVal,
|
||||
DAG.getConstant(0, OtherVal.getValueType()), NewCmp);
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
|
||||
DAGCombinerInfo &DCI) const {
|
||||
@ -11523,6 +11563,8 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
|
||||
return PerformEXTRACT_VECTOR_ELTCombine(N, DAG, *this);
|
||||
case ISD::SELECT: return PerformSELECTCombine(N, DAG, Subtarget);
|
||||
case X86ISD::CMOV: return PerformCMOVCombine(N, DAG, DCI);
|
||||
case ISD::ADD:
|
||||
case ISD::SUB: return OptimizeConditonalInDecrement(N, DAG);
|
||||
case X86ISD::ADC: return PerformADCCombine(N, DAG, DCI);
|
||||
case ISD::MUL: return PerformMulCombine(N, DAG, DCI);
|
||||
case ISD::SHL:
|
||||
|
89
test/CodeGen/X86/conditional-indecrement.ll
Normal file
89
test/CodeGen/X86/conditional-indecrement.ll
Normal file
@ -0,0 +1,89 @@
|
||||
; RUN: llc -march=x86 < %s | FileCheck %s
|
||||
|
||||
define i32 @test1(i32 %a, i32 %b) nounwind readnone {
|
||||
%not.cmp = icmp ne i32 %a, 0
|
||||
%inc = zext i1 %not.cmp to i32
|
||||
%retval.0 = add i32 %inc, %b
|
||||
ret i32 %retval.0
|
||||
; CHECK: test1:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: sbbl $-1
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test2(i32 %a, i32 %b) nounwind readnone {
|
||||
%cmp = icmp eq i32 %a, 0
|
||||
%inc = zext i1 %cmp to i32
|
||||
%retval.0 = add i32 %inc, %b
|
||||
ret i32 %retval.0
|
||||
; CHECK: test2:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: adcl $0
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test3(i32 %a, i32 %b) nounwind readnone {
|
||||
%cmp = icmp eq i32 %a, 0
|
||||
%inc = zext i1 %cmp to i32
|
||||
%retval.0 = add i32 %inc, %b
|
||||
ret i32 %retval.0
|
||||
; CHECK: test3:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: adcl $0
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test4(i32 %a, i32 %b) nounwind readnone {
|
||||
%not.cmp = icmp ne i32 %a, 0
|
||||
%inc = zext i1 %not.cmp to i32
|
||||
%retval.0 = add i32 %inc, %b
|
||||
ret i32 %retval.0
|
||||
; CHECK: test4:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: sbbl $-1
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test5(i32 %a, i32 %b) nounwind readnone {
|
||||
%not.cmp = icmp ne i32 %a, 0
|
||||
%inc = zext i1 %not.cmp to i32
|
||||
%retval.0 = sub i32 %b, %inc
|
||||
ret i32 %retval.0
|
||||
; CHECK: test5:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: adcl $-1
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test6(i32 %a, i32 %b) nounwind readnone {
|
||||
%cmp = icmp eq i32 %a, 0
|
||||
%inc = zext i1 %cmp to i32
|
||||
%retval.0 = sub i32 %b, %inc
|
||||
ret i32 %retval.0
|
||||
; CHECK: test6:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: sbbl $0
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test7(i32 %a, i32 %b) nounwind readnone {
|
||||
%cmp = icmp eq i32 %a, 0
|
||||
%inc = zext i1 %cmp to i32
|
||||
%retval.0 = sub i32 %b, %inc
|
||||
ret i32 %retval.0
|
||||
; CHECK: test7:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: sbbl $0
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test8(i32 %a, i32 %b) nounwind readnone {
|
||||
%not.cmp = icmp ne i32 %a, 0
|
||||
%inc = zext i1 %not.cmp to i32
|
||||
%retval.0 = sub i32 %b, %inc
|
||||
ret i32 %retval.0
|
||||
; CHECK: test8:
|
||||
; CHECK: cmpl $1
|
||||
; CHECK: adcl $-1
|
||||
; CHECK: ret
|
||||
}
|
Loading…
Reference in New Issue
Block a user