Pattern match a setcc of boolean value with 0 as a truncate.

llvm-svn: 154322
This commit is contained in:
Rafael Espindola 2012-04-09 16:06:03 +00:00
parent 4ec2af2fab
commit 8f62b3248e
2 changed files with 81 additions and 10 deletions

View File

@ -4408,6 +4408,44 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
return SDValue(); return SDValue();
} }
// isTruncateOf - If N is a truncate of some other value, return true, record
// the value being truncated in Op and which of Op's bits are zero in KnownZero.
// This function computes KnownZero to avoid a duplicated call to
// ComputeMaskedBits in the caller.
static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op,
APInt &KnownZero) {
APInt KnownOne;
if (N->getOpcode() == ISD::TRUNCATE) {
Op = N->getOperand(0);
DAG.ComputeMaskedBits(Op, KnownZero, KnownOne);
return true;
}
if (N->getOpcode() != ISD::SETCC || N->getValueType(0) != MVT::i1 ||
cast<CondCodeSDNode>(N->getOperand(2))->get() != ISD::SETNE)
return false;
SDValue Op0 = N->getOperand(0);
SDValue Op1 = N->getOperand(1);
assert(Op0.getValueType() == Op1.getValueType());
ConstantSDNode *COp0 = dyn_cast<ConstantSDNode>(Op0);
ConstantSDNode *COp1 = dyn_cast<ConstantSDNode>(Op1);
if (COp0 && COp0->getZExtValue() == 0)
Op = Op1;
else if (COp1 && COp1->getZExtValue() == 0)
Op = Op0;
else
return false;
DAG.ComputeMaskedBits(Op, KnownZero, KnownOne);
if (!(KnownZero | APInt(Op.getValueSizeInBits(), 1)).isAllOnesValue())
return false;
return true;
}
SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
SDValue N0 = N->getOperand(0); SDValue N0 = N->getOperand(0);
EVT VT = N->getValueType(0); EVT VT = N->getValueType(0);
@ -4425,15 +4463,16 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
// (zext (truncate x)) -> (truncate x) // (zext (truncate x)) -> (truncate x)
// This is valid when the truncated bits of x are already zero. // This is valid when the truncated bits of x are already zero.
// FIXME: We should extend this to work for vectors too. // FIXME: We should extend this to work for vectors too.
if (N0.getOpcode() == ISD::TRUNCATE && !VT.isVector()) { SDValue Op;
SDValue Op = N0.getOperand(0); APInt KnownZero;
APInt TruncatedBits if (!VT.isVector() && isTruncateOf(DAG, N0, Op, KnownZero)) {
= APInt::getBitsSet(Op.getValueSizeInBits(), APInt TruncatedBits =
N0.getValueSizeInBits(), (Op.getValueSizeInBits() == N0.getValueSizeInBits()) ?
std::min(Op.getValueSizeInBits(), APInt(Op.getValueSizeInBits(), 0) :
VT.getSizeInBits())); APInt::getBitsSet(Op.getValueSizeInBits(),
APInt KnownZero, KnownOne; N0.getValueSizeInBits(),
DAG.ComputeMaskedBits(Op, KnownZero, KnownOne); std::min(Op.getValueSizeInBits(),
VT.getSizeInBits()));
if (TruncatedBits == (KnownZero & TruncatedBits)) { if (TruncatedBits == (KnownZero & TruncatedBits)) {
if (VT.bitsGT(Op.getValueType())) if (VT.bitsGT(Op.getValueType()))
return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, Op); return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, Op);

View File

@ -1,14 +1,46 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
define zeroext i1 @f1(i8* %x) { define zeroext i1 @f1(i8* %x) {
; CHECK: f1:
; CHECK: movb (%rdi), %al
; CHECK-NEXT: ret
entry: entry:
%0 = load i8* %x, align 1, !range !0 %0 = load i8* %x, align 1, !range !0
%tobool = trunc i8 %0 to i1 %tobool = trunc i8 %0 to i1
ret i1 %tobool ret i1 %tobool
} }
; CHECK: f1: define zeroext i1 @f2(i8* %x) {
; CHECK: f2:
; CHECK: movb (%rdi), %al ; CHECK: movb (%rdi), %al
; CHECK-NEXT: ret ; CHECK-NEXT: ret
entry:
%0 = load i8* %x, align 1, !range !0
%tobool = icmp ne i8 %0, 0
ret i1 %tobool
}
!0 = metadata !{i8 0, i8 2} !0 = metadata !{i8 0, i8 2}
; check that we don't build a "trunc" from i1 to i1, which would assert.
define zeroext i1 @f3(i1 %x) {
; CHECK: f3:
entry:
%tobool = icmp ne i1 %x, 0
ret i1 %tobool
}
; check that we don't build a trunc when other bits are needed
define zeroext i1 @f4(i32 %x) {
; CHECK: f4:
; CHECK: and
entry:
%y = and i32 %x, 32768
%z = icmp ne i32 %y, 0
ret i1 %z
}