[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