forked from OSchip/llvm-project
Pattern match a setcc of boolean value with 0 as a truncate.
llvm-svn: 154322
This commit is contained in:
parent
4ec2af2fab
commit
8f62b3248e
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue