Author: evancheng Date: Fri Dec 14 02:30:15 2007 New Revision: 45029 URL: http://llvm.org/viewvc/llvm-project?rev=45029&view=rev Log: Fix ctlz and cttz. llvm definition requires them to return number of bits in of the src type when value is zero.
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/test/CodeGen/X86/clz.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=45029&r1=45028&r2=45029&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Dec 14 02:30:15 2007 @@ -5352,15 +5352,26 @@ Op = Op.getOperand(0); if (VT == MVT::i8) { + // Zero extend to i32 since there is not an i8 bsr. OpVT = MVT::i32; Op = DAG.getNode(ISD::ZERO_EXTEND, OpVT, Op); } - if (VT == MVT::i32 || VT == MVT::i64) - return DAG.getNode(ISD::XOR, OpVT, DAG.getNode(X86ISD::BSR, OpVT, Op), - DAG.getConstant(NumBits-1, OpVT)); - Op = DAG.getNode(ISD::SUB, OpVT, DAG.getConstant(NumBits-1, OpVT), - DAG.getNode(X86ISD::BSR, OpVT, Op)); + // Issue a bsr (scan bits in reverse) which also sets EFLAGS. + SDVTList VTs = DAG.getVTList(OpVT, MVT::i32); + Op = DAG.getNode(X86ISD::BSR, VTs, Op); + + // If src is zero (i.e. bsr sets ZF), returns NumBits. + SmallVector<SDOperand, 4> Ops; + Ops.push_back(Op); + Ops.push_back(DAG.getConstant(NumBits+NumBits-1, OpVT)); + Ops.push_back(DAG.getConstant(X86::COND_E, MVT::i8)); + Ops.push_back(Op.getValue(1)); + Op = DAG.getNode(X86ISD::CMOV, OpVT, &Ops[0], 4); + + // Finally xor with NumBits-1. + Op = DAG.getNode(ISD::XOR, OpVT, Op, DAG.getConstant(NumBits-1, OpVT)); + if (VT == MVT::i8) Op = DAG.getNode(ISD::TRUNCATE, MVT::i8, Op); return Op; @@ -5369,13 +5380,26 @@ SDOperand X86TargetLowering::LowerCTTZ(SDOperand Op, SelectionDAG &DAG) { MVT::ValueType VT = Op.getValueType(); MVT::ValueType OpVT = VT; + unsigned NumBits = MVT::getSizeInBits(VT); Op = Op.getOperand(0); if (VT == MVT::i8) { OpVT = MVT::i32; Op = DAG.getNode(ISD::ZERO_EXTEND, OpVT, Op); } - Op = DAG.getNode(X86ISD::BSF, OpVT, Op); + + // Issue a bsf (scan bits forward) which also sets EFLAGS. + SDVTList VTs = DAG.getVTList(OpVT, MVT::i32); + Op = DAG.getNode(X86ISD::BSF, VTs, Op); + + // If src is zero (i.e. bsf sets ZF), returns NumBits. + SmallVector<SDOperand, 4> Ops; + Ops.push_back(Op); + Ops.push_back(DAG.getConstant(NumBits, OpVT)); + Ops.push_back(DAG.getConstant(X86::COND_E, MVT::i8)); + Ops.push_back(Op.getValue(1)); + Op = DAG.getNode(X86ISD::CMOV, OpVT, &Ops[0], 4); + if (VT == MVT::i8) Op = DAG.getNode(ISD::TRUNCATE, MVT::i8, Op); return Op; Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=45029&r1=45028&r2=45029&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Fri Dec 14 02:30:15 2007 @@ -451,29 +451,33 @@ let Defs = [EFLAGS] in { def BSF16rr : I<0xBC, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), "bsf{w}\t{$src, $dst||$dst, $src}", - [(set GR16:$dst, (X86bsf GR16:$src))]>, TB; + [(set GR16:$dst, (X86bsf GR16:$src)), (implicit EFLAGS)]>, TB; def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), "bsf{w}\t{$src, $dst||$dst, $src}", - [(set GR16:$dst, (X86bsf (loadi16 addr:$src)))]>, TB; + [(set GR16:$dst, (X86bsf (loadi16 addr:$src))), + (implicit EFLAGS)]>, TB; def BSF32rr : I<0xBC, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), "bsf{l}\t{$src, $dst||$dst, $src}", - [(set GR32:$dst, (X86bsf GR32:$src))]>, TB; + [(set GR32:$dst, (X86bsf GR32:$src)), (implicit EFLAGS)]>, TB; def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), "bsf{l}\t{$src, $dst||$dst, $src}", - [(set GR32:$dst, (X86bsf (loadi32 addr:$src)))]>, TB; + [(set GR32:$dst, (X86bsf (loadi32 addr:$src))), + (implicit EFLAGS)]>, TB; def BSR16rr : I<0xBD, AddRegFrm, (outs GR16:$dst), (ins GR16:$src), "bsr{w}\t{$src, $dst||$dst, $src}", - [(set GR16:$dst, (X86bsr GR16:$src))]>, TB; + [(set GR16:$dst, (X86bsr GR16:$src)), (implicit EFLAGS)]>, TB; def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src), "bsr{w}\t{$src, $dst||$dst, $src}", - [(set GR16:$dst, (X86bsr (loadi16 addr:$src)))]>, TB; + [(set GR16:$dst, (X86bsr (loadi16 addr:$src))), + (implicit EFLAGS)]>, TB; def BSR32rr : I<0xBD, AddRegFrm, (outs GR32:$dst), (ins GR32:$src), "bsr{l}\t{$src, $dst||$dst, $src}", - [(set GR32:$dst, (X86bsr GR32:$src))]>, TB; + [(set GR32:$dst, (X86bsr GR32:$src)), (implicit EFLAGS)]>, TB; def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), "bsr{l}\t{$src, $dst||$dst, $src}", - [(set GR32:$dst, (X86bsr (loadi32 addr:$src)))]>, TB; + [(set GR32:$dst, (X86bsr (loadi32 addr:$src))), + (implicit EFLAGS)]>, TB; } // Defs = [EFLAGS] def LEA16r : I<0x8D, MRMSrcMem, Modified: llvm/trunk/test/CodeGen/X86/clz.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/clz.ll?rev=45029&r1=45028&r2=45029&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/clz.ll (original) +++ llvm/trunk/test/CodeGen/X86/clz.ll Fri Dec 14 02:30:15 2007 @@ -1,5 +1,6 @@ -; RUN: llvm-as < %s | llc -march=x86 | grep bsr +; RUN: llvm-as < %s | llc -march=x86 | grep bsr | count 2 ; RUN: llvm-as < %s | llc -march=x86 | grep bsf +; RUN: llvm-as < %s | llc -march=x86 | grep cmov | count 3 define i32 @t1(i32 %x) nounwind { %tmp = tail call i32 @llvm.ctlz.i32( i32 %x ) @@ -14,3 +15,12 @@ } declare i32 @llvm.cttz.i32(i32) nounwind readnone + +define i16 @t3(i16 %x, i16 %y) nounwind { +entry: + %tmp1 = add i16 %x, %y + %tmp2 = tail call i16 @llvm.ctlz.i16( i16 %tmp1 ) ; <i16> [#uses=1] + ret i16 %tmp2 +} + +declare i16 @llvm.ctlz.i16(i16) nounwind readnone _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits