Let targets provide hooks that compute known zero and ones for any_extend

and extload's. If they are implemented as zero-extend, or implicitly
zero-extend, then this can enable more demanded bits optimizations. e.g.

define void @foo(i16* %ptr, i32 %a) nounwind {
entry:
  %tmp1 = icmp ult i32 %a, 100
  br i1 %tmp1, label %bb1, label %bb2
bb1:
  %tmp2 = load i16* %ptr, align 2
  br label %bb2
bb2:
  %tmp3 = phi i16 [ 0, %entry ], [ %tmp2, %bb1 ]
  %cmp = icmp ult i16 %tmp3, 24
  br i1 %cmp, label %bb3, label %exit
bb3:
  call void @bar() nounwind
  br label %exit
exit:
  ret void
}

This compiles to the followings before:
        push    {lr}
        mov     r2, #0
        cmp     r1, #99
        bhi     LBB0_2
@ BB#1:                                 @ %bb1
        ldrh    r2, [r0]
LBB0_2:                                 @ %bb2
        uxth    r0, r2
        cmp     r0, #23
        bhi     LBB0_4
@ BB#3:                                 @ %bb3
        bl      _bar
LBB0_4:                                 @ %exit
        pop     {lr}
        bx      lr

The uxth is not needed since ldrh implicitly zero-extend the high bits. With
this change it's eliminated.

rdar://12771555


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169459 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2012-12-06 01:28:01 +00:00
parent 486a7ad94f
commit 8a7186dbc2
8 changed files with 137 additions and 7 deletions

View File

@ -935,6 +935,16 @@ public:
const SelectionDAG &DAG,
unsigned Depth = 0) const;
/// computeMaskedBitsForAnyExtend - Since each target implement ANY_EXTEND
/// and ExtLoad nodes specifically, let the target determine which of the bits
/// specified in Mask are known to be either zero or one and return them in
/// the KnownZero/KnownOne bitsets.
virtual void computeMaskedBitsForAnyExtend(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth = 0) const;
/// ComputeNumSignBitsForTargetNode - This method can be implemented by
/// targets that want to expose additional information about sign bits to the
/// DAG Combiner.

View File

@ -1930,6 +1930,8 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, APInt &KnownZero,
KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
} else if (const MDNode *Ranges = LD->getRanges()) {
computeMaskedBitsLoad(*Ranges, KnownZero);
} else if (ISD::isEXTLoad(Op.getNode())) {
TLI.computeMaskedBitsForAnyExtend(Op, KnownZero, KnownOne, *this, Depth);
}
return;
}
@ -1972,13 +1974,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, APInt &KnownZero,
return;
}
case ISD::ANY_EXTEND: {
EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getScalarType().getSizeInBits();
KnownZero = KnownZero.trunc(InBits);
KnownOne = KnownOne.trunc(InBits);
ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
KnownZero = KnownZero.zext(BitWidth);
KnownOne = KnownOne.zext(BitWidth);
TLI.computeMaskedBitsForAnyExtend(Op, KnownZero, KnownOne, *this, Depth);
return;
}
case ISD::TRUNCATE: {

View File

@ -1856,6 +1856,30 @@ void TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
KnownZero = KnownOne = APInt(KnownOne.getBitWidth(), 0);
}
void TargetLowering::computeMaskedBitsForAnyExtend(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth) const {
unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
if (Op.getOpcode() == ISD::ANY_EXTEND) {
EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getScalarType().getSizeInBits();
KnownZero = KnownZero.trunc(InBits);
KnownOne = KnownOne.trunc(InBits);
DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
KnownZero = KnownZero.zext(BitWidth);
KnownOne = KnownOne.zext(BitWidth);
return;
} else if (ISD::isEXTLoad(Op.getNode())) {
KnownZero = KnownOne = APInt(BitWidth, 0);
return;
}
assert(0 && "Expecting an ANY_EXTEND or extload!");
}
/// ComputeNumSignBitsForTargetNode - This method can be implemented by
/// targets that want to expose additional information about sign bits to the
/// DAG Combiner.

View File

@ -9878,6 +9878,36 @@ void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
}
}
void ARMTargetLowering::computeMaskedBitsForAnyExtend(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth) const {
unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
if (Op.getOpcode() == ISD::ANY_EXTEND) {
// Implemented as a zero_extend.
EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getScalarType().getSizeInBits();
KnownZero = KnownZero.trunc(InBits);
KnownOne = KnownOne.trunc(InBits);
DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
KnownZero = KnownZero.zext(BitWidth);
KnownOne = KnownOne.zext(BitWidth);
APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits);
KnownZero |= NewBits;
return;
} else if (ISD::isEXTLoad(Op.getNode())) {
// Implemented as zextloads.
LoadSDNode *LD = cast<LoadSDNode>(Op);
EVT VT = LD->getMemoryVT();
unsigned MemBits = VT.getScalarType().getSizeInBits();
KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
return;
}
assert(0 && "Expecting an ANY_EXTEND or extload!");
}
//===----------------------------------------------------------------------===//
// ARM Inline Assembly Support
//===----------------------------------------------------------------------===//

View File

@ -333,6 +333,11 @@ namespace llvm {
const SelectionDAG &DAG,
unsigned Depth) const;
virtual void computeMaskedBitsForAnyExtend(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth) const;
virtual bool ExpandInlineAsm(CallInst *CI) const;

View File

@ -14112,6 +14112,38 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
}
}
void X86TargetLowering::computeMaskedBitsForAnyExtend(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth) const {
unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
if (Op.getOpcode() == ISD::ANY_EXTEND) {
// Implemented as a zero_extend except for i16 -> i32
EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getScalarType().getSizeInBits();
KnownZero = KnownZero.trunc(InBits);
KnownOne = KnownOne.trunc(InBits);
DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
KnownZero = KnownZero.zext(BitWidth);
KnownOne = KnownOne.zext(BitWidth);
if (BitWidth != 32 || InBits != 16) {
APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits);
KnownZero |= NewBits;
}
return;
} else if (ISD::isEXTLoad(Op.getNode())) {
// Implemented as zextloads or implicitly zero-extended (i32 -> i64)
LoadSDNode *LD = cast<LoadSDNode>(Op);
EVT VT = LD->getMemoryVT();
unsigned MemBits = VT.getScalarType().getSizeInBits();
KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
return;
}
assert(0 && "Expecting an ANY_EXTEND or extload!");
}
unsigned X86TargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
unsigned Depth) const {
// SETCC_CARRY sets the dest to ~0 for true or 0 for false.

View File

@ -558,6 +558,12 @@ namespace llvm {
const SelectionDAG &DAG,
unsigned Depth = 0) const;
virtual void computeMaskedBitsForAnyExtend(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth) const;
// ComputeNumSignBitsForTargetNode - Determine the number of bits in the
// operation that are sign bits.
virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op,

View File

@ -0,0 +1,27 @@
; RUN: llc < %s -march=arm | FileCheck %s
; rdar://12771555
define void @foo(i16* %ptr, i32 %a) nounwind {
entry:
; CHECK: foo:
%tmp1 = icmp ult i32 %a, 100
br i1 %tmp1, label %bb1, label %bb2
bb1:
; CHECK: %bb1
; CHECK: ldrh
%tmp2 = load i16* %ptr, align 2
br label %bb2
bb2:
; CHECK-NOT: uxth
; CHECK: cmp
%tmp3 = phi i16 [ 0, %entry ], [ %tmp2, %bb1 ]
%cmp = icmp ult i16 %tmp3, 24
br i1 %cmp, label %bb3, label %exit
bb3:
call void @bar() nounwind
br label %exit
exit:
ret void
}
declare void @bar ()