[llvm-commits] [llvm] r42308 - in /llvm/trunk: lib/Target/X86/X86ISelDAGToDAG.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h test/CodeGen/X86/divrem.ll

Evan Cheng evan.cheng at apple.com
Tue Sep 25 11:29:54 PDT 2007


Yay! :-)

On Sep 25, 2007, at 11:23 AM, Dan Gohman wrote:

> Author: djg
> Date: Tue Sep 25 13:23:27 2007
> New Revision: 42308
>
> URL: http://llvm.org/viewvc/llvm-project?rev=42308&view=rev
> Log:
> When both x/y and x%y are needed (x and y both scalar integer),  
> compute
> both results with a single div or idiv instruction. This uses new  
> X86ISD
> nodes for DIV and IDIV which are introduced during the legalize phase
> so that the SelectionDAG's CSE can automatically eliminate redundant
> computations.
>
> Added:
>     llvm/trunk/test/CodeGen/X86/divrem.ll
> Modified:
>     llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
>     llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>     llvm/trunk/lib/Target/X86/X86ISelLowering.h
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/ 
> X86ISelDAGToDAG.cpp?rev=42308&r1=42307&r2=42308&view=diff
>
> ====================================================================== 
> ========
> --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Tue Sep 25  
> 13:23:27 2007
> @@ -1162,12 +1162,9 @@
>        return NULL;
>      }
>
> -    case ISD::SDIV:
> -    case ISD::UDIV:
> -    case ISD::SREM:
> -    case ISD::UREM: {
> -      bool isSigned = Opcode == ISD::SDIV || Opcode == ISD::SREM;
> -      bool isDiv    = Opcode == ISD::SDIV || Opcode == ISD::UDIV;
> +    case X86ISD::DIV:
> +    case X86ISD::IDIV: {
> +      bool isSigned = Opcode == X86ISD::IDIV;
>        if (!isSigned)
>          switch (NVT) {
>          default: assert(0 && "Unsupported VT!");
> @@ -1275,31 +1272,49 @@
>            SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1,  
> InFlag), 0);
>        }
>
> -      unsigned Reg = isDiv ? LoReg : HiReg;
> -      SDOperand Result;
> -      if (Reg == X86::AH && Subtarget->is64Bit()) {
> -        // Prevent use of AH in a REX instruction by referencing  
> AX instead.
> -        // Shift it down 8 bits.
> -        Result = CurDAG->getCopyFromReg(Chain, X86::AX, MVT::i16,  
> InFlag);
> -        Chain = Result.getValue(1);
> -        Result = SDOperand(CurDAG->getTargetNode(X86::SHR16ri,  
> MVT::i16, Result,
> -                                     CurDAG->getTargetConstant(8,  
> MVT::i8)), 0);
> -        // Then truncate it down to i8.
> -        SDOperand SRIdx = CurDAG->getTargetConstant(1,  
> MVT::i32); // SubRegSet 1
> -        Result = SDOperand(CurDAG->getTargetNode(X86::EXTRACT_SUBREG,
> -                                                 MVT::i8, Result,  
> SRIdx), 0);
> -      } else {
> -        Result = CurDAG->getCopyFromReg(Chain, Reg, NVT, InFlag);
> +      // Copy the division (low) result, if it is needed.
> +      if (!N.getValue(0).use_empty()) {
> +        SDOperand Result = CurDAG->getCopyFromReg(Chain, LoReg,  
> NVT, InFlag);
>          Chain = Result.getValue(1);
> +        InFlag = Result.getValue(2);
> +        ReplaceUses(N.getValue(0), Result);
> +#ifndef NDEBUG
> +        DOUT << std::string(Indent-2, ' ') << "=> ";
> +        DEBUG(Result.Val->dump(CurDAG));
> +        DOUT << "\n";
> +#endif
> +      }
> +      // Copy the remainder (high) result, if it is needed.
> +      if (!N.getValue(1).use_empty()) {
> +        SDOperand Result;
> +        if (HiReg == X86::AH && Subtarget->is64Bit()) {
> +          // Prevent use of AH in a REX instruction by referencing  
> AX instead.
> +          // Shift it down 8 bits.
> +          Result = CurDAG->getCopyFromReg(Chain, X86::AX,  
> MVT::i16, InFlag);
> +          Chain = Result.getValue(1);
> +          InFlag = Result.getValue(2);
> +          Result = SDOperand(CurDAG->getTargetNode(X86::SHR16ri,  
> MVT::i16, Result,
> +                                       CurDAG->getTargetConstant 
> (8, MVT::i8)), 0);
> +          // Then truncate it down to i8.
> +          SDOperand SRIdx = CurDAG->getTargetConstant(1,  
> MVT::i32); // SubRegSet 1
> +          Result = SDOperand(CurDAG->getTargetNode 
> (X86::EXTRACT_SUBREG,
> +                                                   MVT::i8,  
> Result, SRIdx), 0);
> +        } else {
> +          Result = CurDAG->getCopyFromReg(Chain, HiReg, NVT, InFlag);
> +          Chain = Result.getValue(1);
> +          InFlag = Result.getValue(2);
> +        }
> +        ReplaceUses(N.getValue(1), Result);
> +#ifndef NDEBUG
> +        DOUT << std::string(Indent-2, ' ') << "=> ";
> +        DEBUG(Result.Val->dump(CurDAG));
> +        DOUT << "\n";
> +#endif
>        }
> -      ReplaceUses(N.getValue(0), Result);
>        if (foldedLoad)
>          ReplaceUses(N1.getValue(1), Chain);
>
>  #ifndef NDEBUG
> -      DOUT << std::string(Indent-2, ' ') << "=> ";
> -      DEBUG(Result.Val->dump(CurDAG));
> -      DOUT << "\n";
>        Indent -= 2;
>  #endif
>
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/ 
> X86ISelLowering.cpp?rev=42308&r1=42307&r2=42308&view=diff
>
> ====================================================================== 
> ========
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Sep 25  
> 13:23:27 2007
> @@ -155,6 +155,27 @@
>      setOperationAction(ISD::BIT_CONVERT      , MVT::i32  , Expand);
>    }
>
> +  // Divide and remainder are lowered to use div or idiv in  
> legalize in
> +  // order to expose the intermediate computations to trivial CSE.  
> This is
> +  // most noticeable when both x/y and x%y are being computed;  
> they can be
> +  // done with a single div or idiv.
> +  setOperationAction(ISD::SDIV            , MVT::i8    , Custom);
> +  setOperationAction(ISD::UDIV            , MVT::i8    , Custom);
> +  setOperationAction(ISD::SREM            , MVT::i8    , Custom);
> +  setOperationAction(ISD::UREM            , MVT::i8    , Custom);
> +  setOperationAction(ISD::SDIV            , MVT::i16   , Custom);
> +  setOperationAction(ISD::UDIV            , MVT::i16   , Custom);
> +  setOperationAction(ISD::SREM            , MVT::i16   , Custom);
> +  setOperationAction(ISD::UREM            , MVT::i16   , Custom);
> +  setOperationAction(ISD::SDIV            , MVT::i32   , Custom);
> +  setOperationAction(ISD::UDIV            , MVT::i32   , Custom);
> +  setOperationAction(ISD::SREM            , MVT::i32   , Custom);
> +  setOperationAction(ISD::UREM            , MVT::i32   , Custom);
> +  setOperationAction(ISD::SDIV            , MVT::i64   , Custom);
> +  setOperationAction(ISD::UDIV            , MVT::i64   , Custom);
> +  setOperationAction(ISD::SREM            , MVT::i64   , Custom);
> +  setOperationAction(ISD::UREM            , MVT::i64   , Custom);
> +
>    setOperationAction(ISD::BR_JT            , MVT::Other, Expand);
>    setOperationAction(ISD::BRCOND           , MVT::Other, Custom);
>    setOperationAction(ISD::BR_CC            , MVT::Other, Expand);
> @@ -3393,6 +3414,22 @@
>      return DAG.getNode(ISD::MERGE_VALUES, VTs, 2, &Ops[0], Ops.size 
> ());
>  }
>
> +SDOperand X86TargetLowering::LowerIntegerDivOrRem(SDOperand Op,  
> SelectionDAG &DAG) {
> +  unsigned Opcode = Op.getOpcode();
> +  MVT::ValueType NVT = Op.getValueType();
> +  bool isSigned = Opcode == ISD::SDIV || Opcode == ISD::SREM;
> +  bool isDiv    = Opcode == ISD::SDIV || Opcode == ISD::UDIV;
> +  unsigned Opc = isSigned ? X86ISD::IDIV : X86ISD::DIV;
> +
> +  SDOperand Ops[] = { Op.getOperand(0), Op.getOperand(1) };
> +  SDOperand DR = DAG.getNode(Opc, DAG.getVTList(NVT, NVT), Ops, 2);
> +
> +  if (isDiv)
> +    return DR;
> +
> +  return SDOperand(DR.Val, 1);
> +}
> +
>  SDOperand X86TargetLowering::LowerSINT_TO_FP(SDOperand Op,  
> SelectionDAG &DAG) {
>    assert(Op.getOperand(0).getValueType() <= MVT::i64 &&
>           Op.getOperand(0).getValueType() >= MVT::i16 &&
> @@ -4668,6 +4705,10 @@
>    case ISD::SHL_PARTS:
>    case ISD::SRA_PARTS:
>    case ISD::SRL_PARTS:          return LowerShift(Op, DAG);
> +  case ISD::SDIV:
> +  case ISD::UDIV:
> +  case ISD::SREM:
> +  case ISD::UREM:               return LowerIntegerDivOrRem(Op, DAG);
>    case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG);
>    case ISD::FP_TO_SINT:         return LowerFP_TO_SINT(Op, DAG);
>    case ISD::FABS:               return LowerFABS(Op, DAG);
> @@ -4751,6 +4792,8 @@
>    case X86ISD::TLSADDR:            return "X86ISD::TLSADDR";
>    case X86ISD::THREAD_POINTER:     return "X86ISD::THREAD_POINTER";
>    case X86ISD::EH_RETURN:          return "X86ISD::EH_RETURN";
> +  case X86ISD::DIV:                return "X86ISD::DIV";
> +  case X86ISD::IDIV:               return "X86ISD::IDIV";
>    }
>  }
>
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/ 
> X86ISelLowering.h?rev=42308&r1=42307&r2=42308&view=diff
>
> ====================================================================== 
> ========
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Tue Sep 25 13:23:27  
> 2007
> @@ -181,6 +181,10 @@
>        /// in order to obtain suitable precision.
>        FRSQRT, FRCP,
>
> +      /// DIV, IDIV - Unsigned and signed integer division and  
> reciprocal.
> +      ///
> +      DIV, IDIV,
> +
>        // Thread Local Storage
>        TLSADDR, THREAD_POINTER,
>
> @@ -420,6 +424,7 @@
>      SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
>      SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG);
>      SDOperand LowerShift(SDOperand Op, SelectionDAG &DAG);
> +    SDOperand LowerIntegerDivOrRem(SDOperand Op, SelectionDAG &DAG);
>      SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG);
>      SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG);
>      SDOperand LowerFABS(SDOperand Op, SelectionDAG &DAG);
>
> Added: llvm/trunk/test/CodeGen/X86/divrem.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ 
> X86/divrem.ll?rev=42308&view=auto
>
> ====================================================================== 
> ========
> --- llvm/trunk/test/CodeGen/X86/divrem.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/divrem.ll Tue Sep 25 13:23:27 2007
> @@ -0,0 +1,58 @@
> +; RUN: llvm-as < %s | llc -march=x86-64 | grep div | count 8
> +
> +define void @si64(i64 %x, i64 %y, i64* %p, i64* %q) {
> +	%r = sdiv i64 %x, %y
> +	%t = srem i64 %x, %y
> +	store i64 %r, i64* %p
> +	store i64 %t, i64* %q
> +	ret void
> +}
> +define void @si32(i32 %x, i32 %y, i32* %p, i32* %q) {
> +	%r = sdiv i32 %x, %y
> +	%t = srem i32 %x, %y
> +	store i32 %r, i32* %p
> +	store i32 %t, i32* %q
> +	ret void
> +}
> +define void @si16(i16 %x, i16 %y, i16* %p, i16* %q) {
> +	%r = sdiv i16 %x, %y
> +	%t = srem i16 %x, %y
> +	store i16 %r, i16* %p
> +	store i16 %t, i16* %q
> +	ret void
> +}
> +define void @si8(i8 %x, i8 %y, i8* %p, i8* %q) {
> +	%r = sdiv i8 %x, %y
> +	%t = srem i8 %x, %y
> +	store i8 %r, i8* %p
> +	store i8 %t, i8* %q
> +	ret void
> +}
> +define void @ui64(i64 %x, i64 %y, i64* %p, i64* %q) {
> +	%r = udiv i64 %x, %y
> +	%t = urem i64 %x, %y
> +	store i64 %r, i64* %p
> +	store i64 %t, i64* %q
> +	ret void
> +}
> +define void @ui32(i32 %x, i32 %y, i32* %p, i32* %q) {
> +	%r = udiv i32 %x, %y
> +	%t = urem i32 %x, %y
> +	store i32 %r, i32* %p
> +	store i32 %t, i32* %q
> +	ret void
> +}
> +define void @ui16(i16 %x, i16 %y, i16* %p, i16* %q) {
> +	%r = udiv i16 %x, %y
> +	%t = urem i16 %x, %y
> +	store i16 %r, i16* %p
> +	store i16 %t, i16* %q
> +	ret void
> +}
> +define void @ui8(i8 %x, i8 %y, i8* %p, i8* %q) {
> +	%r = udiv i8 %x, %y
> +	%t = urem i8 %x, %y
> +	store i8 %r, i8* %p
> +	store i8 %t, i8* %q
> +	ret void
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list