mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-03 19:15:30 +00:00
[X86] Emit more efficient >= comparisons against 0
We don't do a great job with >= 0 comparisons against zero when the result is used as an i8. Given something like: void f(long long LL, bool *B) { *B = LL >= 0; } We used to generate: shrq $63, %rdi xorb $1, %dil movb %dil, (%rsi) Now we generate: testq %rdi, %rdi setns (%rsi) Differential Revision: http://reviews.llvm.org/D12136 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245498 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6e53cbdf5f
commit
26047ead4b
@ -24074,13 +24074,61 @@ static SDValue performIntegerAbsCombine(SDNode *N, SelectionDAG &DAG) {
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// PerformXorCombine - Attempts to turn XOR nodes into BLSMSK nodes
|
||||
// Try to turn tests against the signbit in the form of:
|
||||
// XOR(TRUNCATE(SRL(X, size(X)-1)), 1)
|
||||
// into:
|
||||
// SETGT(X, -1)
|
||||
static SDValue foldXorTruncShiftIntoCmp(SDNode *N, SelectionDAG &DAG) {
|
||||
// This is only worth doing if the output type is i8.
|
||||
if (N->getValueType(0) != MVT::i8)
|
||||
return SDValue();
|
||||
|
||||
SDValue N0 = N->getOperand(0);
|
||||
SDValue N1 = N->getOperand(1);
|
||||
|
||||
// We should be performing an xor against a truncated shift.
|
||||
if (N0.getOpcode() != ISD::TRUNCATE || !N0.hasOneUse())
|
||||
return SDValue();
|
||||
|
||||
// Make sure we are performing an xor against one.
|
||||
if (!isa<ConstantSDNode>(N1) || !cast<ConstantSDNode>(N1)->isOne())
|
||||
return SDValue();
|
||||
|
||||
// SetCC on x86 zero extends so only act on this if it's a logical shift.
|
||||
SDValue Shift = N0.getOperand(0);
|
||||
if (Shift.getOpcode() != ISD::SRL || !Shift.hasOneUse())
|
||||
return SDValue();
|
||||
|
||||
// Make sure we are truncating from one of i16, i32 or i64.
|
||||
EVT ShiftTy = Shift.getValueType();
|
||||
if (ShiftTy != MVT::i16 && ShiftTy != MVT::i32 && ShiftTy != MVT::i64)
|
||||
return SDValue();
|
||||
|
||||
// Make sure the shift amount extracts the sign bit.
|
||||
if (!isa<ConstantSDNode>(Shift.getOperand(1)) ||
|
||||
Shift.getConstantOperandVal(1) != ShiftTy.getSizeInBits() - 1)
|
||||
return SDValue();
|
||||
|
||||
// Create a greater-than comparison against -1.
|
||||
// N.B. Using SETGE against 0 works but we want a canonical looking
|
||||
// comparison, using SETGT matches up with what TranslateX86CC.
|
||||
SDLoc DL(N);
|
||||
SDValue ShiftOp = Shift.getOperand(0);
|
||||
EVT ShiftOpTy = ShiftOp.getValueType();
|
||||
SDValue Cond = DAG.getSetCC(DL, MVT::i8, ShiftOp,
|
||||
DAG.getConstant(-1, DL, ShiftOpTy), ISD::SETGT);
|
||||
return Cond;
|
||||
}
|
||||
|
||||
static SDValue PerformXorCombine(SDNode *N, SelectionDAG &DAG,
|
||||
TargetLowering::DAGCombinerInfo &DCI,
|
||||
const X86Subtarget *Subtarget) {
|
||||
if (DCI.isBeforeLegalizeOps())
|
||||
return SDValue();
|
||||
|
||||
if (SDValue RV = foldXorTruncShiftIntoCmp(N, DAG))
|
||||
return RV;
|
||||
|
||||
if (Subtarget->hasCMov())
|
||||
if (SDValue RV = performIntegerAbsCombine(N, DAG))
|
||||
return RV;
|
||||
|
@ -211,3 +211,47 @@ define zeroext i1 @test15(i32 %bf.load, i32 %n) {
|
||||
; CHECK: shrl $16, %edi
|
||||
; CHECK: cmpl %esi, %edi
|
||||
}
|
||||
|
||||
define i8 @test16(i16 signext %L) {
|
||||
%lshr = lshr i16 %L, 15
|
||||
%trunc = trunc i16 %lshr to i8
|
||||
%not = xor i8 %trunc, 1
|
||||
ret i8 %not
|
||||
|
||||
; CHECK-LABEL: test16:
|
||||
; CHECK: testw %di, %di
|
||||
; CHECK: setns %al
|
||||
}
|
||||
|
||||
define i8 @test17(i32 %L) {
|
||||
%lshr = lshr i32 %L, 31
|
||||
%trunc = trunc i32 %lshr to i8
|
||||
%not = xor i8 %trunc, 1
|
||||
ret i8 %not
|
||||
|
||||
; CHECK-LABEL: test17:
|
||||
; CHECK: testl %edi, %edi
|
||||
; CHECK: setns %al
|
||||
}
|
||||
|
||||
define i8 @test18(i64 %L) {
|
||||
%lshr = lshr i64 %L, 63
|
||||
%trunc = trunc i64 %lshr to i8
|
||||
%not = xor i8 %trunc, 1
|
||||
ret i8 %not
|
||||
|
||||
; CHECK-LABEL: test18:
|
||||
; CHECK: testq %rdi, %rdi
|
||||
; CHECK: setns %al
|
||||
}
|
||||
|
||||
define zeroext i1 @test19(i32 %L) {
|
||||
%lshr = lshr i32 %L, 31
|
||||
%trunc = trunc i32 %lshr to i1
|
||||
%not = xor i1 %trunc, 1
|
||||
ret i1 %not
|
||||
|
||||
; CHECK-LABEL: test19:
|
||||
; CHECK: testl %edi, %edi
|
||||
; CHECK: setns %al
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user