From e55484eb4521413b31450bd680fcf3694613579f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 25 Dec 2008 05:34:37 +0000 Subject: [PATCH] Add a simple pattern for matching 'bt'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61426 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 56 ++++++++++++++++++++++++------ test/CodeGen/X86/bt.ll | 20 +++++++++++ 2 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 test/CodeGen/X86/bt.ll diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6113f87aa2c..515adf40842 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -5017,16 +5017,48 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) { SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer"); - SDValue Cond; SDValue Op0 = Op.getOperand(0); SDValue Op1 = Op.getOperand(1); - SDValue CC = Op.getOperand(2); - bool isFP = Op.getOperand(1).getValueType().isFloatingPoint(); + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + + // 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(Op0.getOperand(1)); + ConstantSDNode *CmpRHS = cast(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); + + // If LHS is i8, promote it to i16 with any_extend. There is no i8 BT + // 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); + } + } - unsigned X86CC = TranslateX86CC(cast(CC)->get(), isFP, - Op0, Op1, DAG); + 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, DAG.getConstant(X86CC, MVT::i8), Cond); } @@ -5219,12 +5251,15 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { if (Cond.getOpcode() == ISD::SETCC) Cond = LowerSETCC(Cond, DAG); +#if 0 + // FIXME: LowerXALUO doesn't handle these!! else if (Cond.getOpcode() == X86ISD::ADD || Cond.getOpcode() == X86ISD::SUB || Cond.getOpcode() == X86ISD::SMUL || Cond.getOpcode() == X86ISD::UMUL) Cond = LowerXALUO(Cond, DAG); - +#endif + // If condition flag is set by a X86ISD::CMP, then use it as the condition // setting operand in place of the X86ISD::SETCC. if (Cond.getOpcode() == X86ISD::SETCC) { @@ -5232,7 +5267,8 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { SDValue Cmp = Cond.getOperand(1); unsigned Opc = Cmp.getOpcode(); - if (isX86LogicalCmp(Opc)) { + // FIXME: WHY THE SPECIAL CASING OF LogicalCmp?? + if (isX86LogicalCmp(Opc) || Opc == X86ISD::BT) { Cond = Cmp; addTest = false; } else { @@ -5240,8 +5276,8 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { default: break; case X86::COND_O: case X86::COND_C: - // These can only come from an arithmetic instruction with overflow, e.g. - // SADDO, UADDO. + // These can only come from an arithmetic instruction with overflow, + // e.g. SADDO, UADDO. Cond = Cond.getNode()->getOperand(1); addTest = false; break; diff --git a/test/CodeGen/X86/bt.ll b/test/CodeGen/X86/bt.ll new file mode 100644 index 00000000000..aab91e07b28 --- /dev/null +++ b/test/CodeGen/X86/bt.ll @@ -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 ; [#uses=1] + %tmp3 = and i32 %tmp29, 1 ; [#uses=1] + %tmp4 = icmp eq i32 %tmp3, 0 ; [#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() -- 2.34.1