[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:
David Majnemer 2015-08-19 20:51:40 +00:00
parent 6e53cbdf5f
commit 26047ead4b
2 changed files with 93 additions and 1 deletions

View File

@ -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;

View File

@ -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
}