Add a simple pattern for matching 'bt'.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61426 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-12-25 05:34:37 +00:00
parent f1e9fd5676
commit e55484eb45
2 changed files with 66 additions and 10 deletions

View File

@ -5017,16 +5017,48 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) {
SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer"); assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer");
SDValue Cond;
SDValue Op0 = Op.getOperand(0); SDValue Op0 = Op.getOperand(0);
SDValue Op1 = Op.getOperand(1); SDValue Op1 = Op.getOperand(1);
SDValue CC = Op.getOperand(2); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
bool isFP = Op.getOperand(1).getValueType().isFloatingPoint();
// Lower (X & (1 << N)) == 0 to BT.
// Lower ((X >>u N) & 1) != 0 to BT.
// Lower ((X >>s N) & 1) != 0 to BT.
// FIXME: Is i386 or later or available only on some chips?
if (Op0.getOpcode() == ISD::AND && Op1.getOpcode() == ISD::Constant &&
Op0.getOperand(1).getOpcode() == ISD::Constant &&
(CC == ISD::SETEQ || CC == ISD::SETNE)) {
ConstantSDNode *AndRHS = cast<ConstantSDNode>(Op0.getOperand(1));
ConstantSDNode *CmpRHS = cast<ConstantSDNode>(Op1);
SDValue AndLHS = Op0.getOperand(0);
if (CmpRHS->getZExtValue() == 0 && AndRHS->getZExtValue() == 1 &&
AndLHS.getOpcode() == ISD::SRL) {
SDValue LHS = AndLHS.getOperand(0);
SDValue RHS = AndLHS.getOperand(1);
unsigned X86CC = TranslateX86CC(cast<CondCodeSDNode>(CC)->get(), isFP, // If LHS is i8, promote it to i16 with any_extend. There is no i8 BT
Op0, Op1, DAG); // instruction. Since the shift amount is in-range-or-undefined, we know
// that doing a bittest on the i16 value is ok. We extend to i32 because
// the encoding for the i16 version is larger than the i32 version.
if (LHS.getValueType() == MVT::i8)
LHS = DAG.getNode(ISD::ANY_EXTEND, MVT::i32, LHS);
// If the operand types disagree, extend the shift amount to match. Since
// BT ignores high bits (like shifts) we can use anyextend.
if (LHS.getValueType() != RHS.getValueType())
RHS = DAG.getNode(ISD::ANY_EXTEND, LHS.getValueType(), RHS);
SDValue BT = DAG.getNode(X86ISD::BT, MVT::i32, LHS, RHS);
unsigned Cond = CC == ISD::SETEQ ? X86::COND_NC : X86::COND_C;
return DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(Cond, MVT::i8), BT);
}
}
bool isFP = Op.getOperand(1).getValueType().isFloatingPoint();
unsigned X86CC = TranslateX86CC(CC, isFP, Op0, Op1, DAG);
Cond = DAG.getNode(X86ISD::CMP, MVT::i32, Op0, Op1); SDValue Cond = DAG.getNode(X86ISD::CMP, MVT::i32, Op0, Op1);
return DAG.getNode(X86ISD::SETCC, MVT::i8, return DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(X86CC, MVT::i8), Cond); DAG.getConstant(X86CC, MVT::i8), Cond);
} }
@ -5219,12 +5251,15 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
if (Cond.getOpcode() == ISD::SETCC) if (Cond.getOpcode() == ISD::SETCC)
Cond = LowerSETCC(Cond, DAG); Cond = LowerSETCC(Cond, DAG);
#if 0
// FIXME: LowerXALUO doesn't handle these!!
else if (Cond.getOpcode() == X86ISD::ADD || else if (Cond.getOpcode() == X86ISD::ADD ||
Cond.getOpcode() == X86ISD::SUB || Cond.getOpcode() == X86ISD::SUB ||
Cond.getOpcode() == X86ISD::SMUL || Cond.getOpcode() == X86ISD::SMUL ||
Cond.getOpcode() == X86ISD::UMUL) Cond.getOpcode() == X86ISD::UMUL)
Cond = LowerXALUO(Cond, DAG); Cond = LowerXALUO(Cond, DAG);
#endif
// If condition flag is set by a X86ISD::CMP, then use it as the condition // If condition flag is set by a X86ISD::CMP, then use it as the condition
// setting operand in place of the X86ISD::SETCC. // setting operand in place of the X86ISD::SETCC.
if (Cond.getOpcode() == X86ISD::SETCC) { if (Cond.getOpcode() == X86ISD::SETCC) {
@ -5232,7 +5267,8 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
SDValue Cmp = Cond.getOperand(1); SDValue Cmp = Cond.getOperand(1);
unsigned Opc = Cmp.getOpcode(); unsigned Opc = Cmp.getOpcode();
if (isX86LogicalCmp(Opc)) { // FIXME: WHY THE SPECIAL CASING OF LogicalCmp??
if (isX86LogicalCmp(Opc) || Opc == X86ISD::BT) {
Cond = Cmp; Cond = Cmp;
addTest = false; addTest = false;
} else { } else {
@ -5240,8 +5276,8 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
default: break; default: break;
case X86::COND_O: case X86::COND_O:
case X86::COND_C: case X86::COND_C:
// These can only come from an arithmetic instruction with overflow, e.g. // These can only come from an arithmetic instruction with overflow,
// SADDO, UADDO. // e.g. SADDO, UADDO.
Cond = Cond.getNode()->getOperand(1); Cond = Cond.getNode()->getOperand(1);
addTest = false; addTest = false;
break; break;

20
test/CodeGen/X86/bt.ll Normal file
View File

@ -0,0 +1,20 @@
; RUN: llvm-as < %s | llc | grep btl
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin8"
define void @test2(i32 %x, i32 %n) nounwind {
entry:
%tmp29 = lshr i32 %x, %n ; <i32> [#uses=1]
%tmp3 = and i32 %tmp29, 1 ; <i32> [#uses=1]
%tmp4 = icmp eq i32 %tmp3, 0 ; <i1> [#uses=1]
br i1 %tmp4, label %bb, label %UnifiedReturnBlock
bb: ; preds = %entry
call void @foo()
ret void
UnifiedReturnBlock: ; preds = %entry
ret void
}
declare void @foo()