mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-01 09:18:30 +00:00
X86: Lower a select directly to a setcc_carry if possible.
int test(unsigned long a, unsigned long b) { return -(a < b); } compiles to _test: ## @test cmpq %rsi, %rdi ## encoding: [0x48,0x39,0xf7] sbbl %eax, %eax ## encoding: [0x19,0xc0] ret ## encoding: [0xc3] instead of _test: ## @test xorl %ecx, %ecx ## encoding: [0x31,0xc9] cmpq %rsi, %rdi ## encoding: [0x48,0x39,0xf7] movl $-1, %eax ## encoding: [0xb8,0xff,0xff,0xff,0xff] cmovael %ecx, %eax ## encoding: [0x0f,0x43,0xc1] ret ## encoding: [0xc3] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122451 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
10b6d33581
commit
e915ff30cd
@ -1165,58 +1165,6 @@ abs:
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Consider:
|
||||
int test(unsigned long a, unsigned long b) { return -(a < b); }
|
||||
|
||||
We currently compile this to:
|
||||
|
||||
define i32 @test(i32 %a, i32 %b) nounwind {
|
||||
%tmp3 = icmp ult i32 %a, %b ; <i1> [#uses=1]
|
||||
%tmp34 = zext i1 %tmp3 to i32 ; <i32> [#uses=1]
|
||||
%tmp5 = sub i32 0, %tmp34 ; <i32> [#uses=1]
|
||||
ret i32 %tmp5
|
||||
}
|
||||
|
||||
and
|
||||
|
||||
_test:
|
||||
movl 8(%esp), %eax
|
||||
cmpl %eax, 4(%esp)
|
||||
setb %al
|
||||
movzbl %al, %eax
|
||||
negl %eax
|
||||
ret
|
||||
|
||||
Several deficiencies here. First, we should instcombine zext+neg into sext:
|
||||
|
||||
define i32 @test2(i32 %a, i32 %b) nounwind {
|
||||
%tmp3 = icmp ult i32 %a, %b ; <i1> [#uses=1]
|
||||
%tmp34 = sext i1 %tmp3 to i32 ; <i32> [#uses=1]
|
||||
ret i32 %tmp34
|
||||
}
|
||||
|
||||
However, before we can do that, we have to fix the bad codegen that we get for
|
||||
sext from bool:
|
||||
|
||||
_test2:
|
||||
movl 8(%esp), %eax
|
||||
cmpl %eax, 4(%esp)
|
||||
setb %al
|
||||
movzbl %al, %eax
|
||||
shll $31, %eax
|
||||
sarl $31, %eax
|
||||
ret
|
||||
|
||||
This code should be at least as good as the code above. Once this is fixed, we
|
||||
can optimize this specific case even more to:
|
||||
|
||||
movl 8(%esp), %eax
|
||||
xorl %ecx, %ecx
|
||||
cmpl %eax, 4(%esp)
|
||||
sbbl %ecx, %ecx
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Take the following code (from
|
||||
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16541):
|
||||
|
||||
|
@ -7313,6 +7313,23 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
|
||||
Cond = EmitTest(Cond, X86::COND_NE, DAG);
|
||||
}
|
||||
|
||||
// a < b ? -1 : 0 -> RES = ~setcc_carry
|
||||
// a < b ? 0 : -1 -> RES = setcc_carry
|
||||
// a >= b ? -1 : 0 -> RES = setcc_carry
|
||||
// a >= b ? 0 : -1 -> RES = ~setcc_carry
|
||||
if (Cond.getOpcode() == X86ISD::CMP) {
|
||||
unsigned CondCode = cast<ConstantSDNode>(CC)->getZExtValue();
|
||||
|
||||
if ((CondCode == X86::COND_AE || CondCode == X86::COND_B) &&
|
||||
(isAllOnes(Op1) || isAllOnes(Op2)) && (isZero(Op1) || isZero(Op2))) {
|
||||
SDValue Res = DAG.getNode(X86ISD::SETCC_CARRY, DL, Op.getValueType(),
|
||||
DAG.getConstant(X86::COND_B, MVT::i8), Cond);
|
||||
if (isAllOnes(Op1) != (CondCode == X86::COND_B))
|
||||
return DAG.getNOT(DL, Res, Res.getValueType());
|
||||
return Res;
|
||||
}
|
||||
}
|
||||
|
||||
// X86ISD::CMOV means set the result (which is operand 1) to the RHS if
|
||||
// condition is true.
|
||||
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
|
||||
|
@ -197,7 +197,24 @@ entry:
|
||||
|
||||
declare { i64, i1 } @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone
|
||||
|
||||
define i32 @test13(i32 %a, i32 %b) nounwind {
|
||||
%c = icmp ult i32 %a, %b
|
||||
%d = sext i1 %c to i32
|
||||
ret i32 %d
|
||||
; CHECK: test13:
|
||||
; CHECK: cmpl
|
||||
; CHECK-NEXT: sbbl
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
define i32 @test14(i32 %a, i32 %b) nounwind {
|
||||
%c = icmp uge i32 %a, %b
|
||||
%d = sext i1 %c to i32
|
||||
ret i32 %d
|
||||
; CHECK: test14:
|
||||
; CHECK: cmpl
|
||||
; CHECK-NEXT: sbbl
|
||||
; CHECK-NEXT: notl
|
||||
; CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user