[llvm-commits] [llvm] r98465 - in /llvm/trunk: lib/Target/X86/X86ISelDAGToDAG.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrInfo.td lib/Target/X86/X86RegisterInfo.cpp

Daniel Dunbar daniel at zuster.org
Sat Mar 13 20:35:24 PST 2010


This is causing failures everywhere. Please revert.

 - Daniel

On Sat, Mar 13, 2010 at 7:48 PM, Evan Cheng <evan.cheng at apple.com> wrote:
> Author: evancheng
> Date: Sat Mar 13 21:48:46 2010
> New Revision: 98465
>
> URL: http://llvm.org/viewvc/llvm-project?rev=98465&view=rev
> Log:
> Do not force indirect tailcall through fixed registers: eax, r11. Add support to allow loads to be folded to tail call instructions.
>
> Modified:
>    llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
>    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>    llvm/trunk/lib/Target/X86/X86Instr64bit.td
>    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>    llvm/trunk/lib/Target/X86/X86InstrInfo.td
>    llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
>    llvm/trunk/lib/Target/X86/X86RegisterInfo.td
>    llvm/trunk/test/CodeGen/X86/tailcall-largecode.ll
>    llvm/trunk/test/CodeGen/X86/tailcallfp2.ll
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Sat Mar 13 21:48:46 2010
> @@ -349,17 +349,17 @@
>   return true;
>  }
>
> -/// MoveBelowCallSeqStart - Replace CALLSEQ_START operand with load's chain
> -/// operand and move load below the call's chain operand.
> -static void MoveBelowCallSeqStart(SelectionDAG *CurDAG, SDValue Load,
> -                                  SDValue Call, SDValue CallSeqStart) {
> +/// MoveBelowCallOrigChain - Replace the original chain operand of the call with
> +/// load's chain operand and move load below the call's chain operand.
> +static void MoveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load,
> +                                  SDValue Call, SDValue OrigChain) {
>   SmallVector<SDValue, 8> Ops;
> -  SDValue Chain = CallSeqStart.getOperand(0);
> +  SDValue Chain = OrigChain.getOperand(0);
>   if (Chain.getNode() == Load.getNode())
>     Ops.push_back(Load.getOperand(0));
>   else {
>     assert(Chain.getOpcode() == ISD::TokenFactor &&
> -           "Unexpected CallSeqStart chain operand");
> +           "Unexpected chain operand");
>     for (unsigned i = 0, e = Chain.getNumOperands(); i != e; ++i)
>       if (Chain.getOperand(i).getNode() == Load.getNode())
>         Ops.push_back(Load.getOperand(0));
> @@ -371,9 +371,9 @@
>     Ops.clear();
>     Ops.push_back(NewChain);
>   }
> -  for (unsigned i = 1, e = CallSeqStart.getNumOperands(); i != e; ++i)
> -    Ops.push_back(CallSeqStart.getOperand(i));
> -  CurDAG->UpdateNodeOperands(CallSeqStart, &Ops[0], Ops.size());
> +  for (unsigned i = 1, e = OrigChain.getNumOperands(); i != e; ++i)
> +    Ops.push_back(OrigChain.getOperand(i));
> +  CurDAG->UpdateNodeOperands(OrigChain, &Ops[0], Ops.size());
>   CurDAG->UpdateNodeOperands(Load, Call.getOperand(0),
>                              Load.getOperand(1), Load.getOperand(2));
>   Ops.clear();
> @@ -386,7 +386,9 @@
>  /// isCalleeLoad - Return true if call address is a load and it can be
>  /// moved below CALLSEQ_START and the chains leading up to the call.
>  /// Return the CALLSEQ_START by reference as a second output.
> -static bool isCalleeLoad(SDValue Callee, SDValue &Chain) {
> +/// In the case of a tail call, there isn't a callseq node between the call
> +/// chain and the load.
> +static bool isCalleeLoad(SDValue Callee, SDValue &Chain, bool HasCallSeq) {
>   if (Callee.getNode() == Chain.getNode() || !Callee.hasOneUse())
>     return false;
>   LoadSDNode *LD = dyn_cast<LoadSDNode>(Callee.getNode());
> @@ -397,12 +399,14 @@
>     return false;
>
>   // Now let's find the callseq_start.
> -  while (Chain.getOpcode() != ISD::CALLSEQ_START) {
> +  while (HasCallSeq && Chain.getOpcode() != ISD::CALLSEQ_START) {
>     if (!Chain.hasOneUse())
>       return false;
>     Chain = Chain.getOperand(0);
>   }
> -
> +
> +  if (!Chain.getNumOperands())
> +    return false;
>   if (Chain.getOperand(0).getNode() == Callee.getNode())
>     return true;
>   if (Chain.getOperand(0).getOpcode() == ISD::TokenFactor &&
> @@ -420,7 +424,9 @@
>        E = CurDAG->allnodes_end(); I != E; ) {
>     SDNode *N = I++;  // Preincrement iterator to avoid invalidation issues.
>
> -    if (OptLevel != CodeGenOpt::None && N->getOpcode() == X86ISD::CALL) {
> +    if (OptLevel != CodeGenOpt::None &&
> +        (N->getOpcode() == X86ISD::CALL ||
> +         N->getOpcode() == X86ISD::TC_RETURN)) {
>       /// Also try moving call address load from outside callseq_start to just
>       /// before the call to allow it to be folded.
>       ///
> @@ -440,11 +446,12 @@
>       ///      \        /
>       ///       \      /
>       ///       [CALL]
> +      bool HasCallSeq = N->getOpcode() == X86ISD::CALL;
>       SDValue Chain = N->getOperand(0);
>       SDValue Load  = N->getOperand(1);
> -      if (!isCalleeLoad(Load, Chain))
> +      if (!isCalleeLoad(Load, Chain, HasCallSeq))
>         continue;
> -      MoveBelowCallSeqStart(CurDAG, Load, SDValue(N, 0), Chain);
> +      MoveBelowOrigChain(CurDAG, Load, SDValue(N, 0), Chain);
>       ++NumLoadMoved;
>       continue;
>     }
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Sat Mar 13 21:48:46 2010
> @@ -2133,18 +2133,6 @@
>                                          OpFlags);
>   }
>
> -  if (isTailCall && !WasGlobalOrExternal) {
> -    // Force the address into a (call preserved) caller-saved register since
> -    // tailcall must happen after callee-saved registers are poped.
> -    // FIXME: Give it a special register class that contains caller-saved
> -    // register instead?
> -    unsigned TCReg = Is64Bit ? X86::R11 : X86::EAX;
> -    Chain = DAG.getCopyToReg(Chain,  dl,
> -                             DAG.getRegister(TCReg, getPointerTy()),
> -                             Callee,InFlag);
> -    Callee = DAG.getRegister(TCReg, getPointerTy());
> -  }
> -
>   // Returns a chain & a flag for retval copy to use.
>   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
>   SmallVector<SDValue, 8> Ops;
> @@ -2190,14 +2178,6 @@
>         if (RVLocs[i].isRegLoc())
>           MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg());
>     }
> -
> -    assert(((Callee.getOpcode() == ISD::Register &&
> -               (cast<RegisterSDNode>(Callee)->getReg() == X86::EAX ||
> -                cast<RegisterSDNode>(Callee)->getReg() == X86::R11)) ||
> -              Callee.getOpcode() == ISD::TargetExternalSymbol ||
> -              Callee.getOpcode() == ISD::TargetGlobalAddress) &&
> -           "Expecting a global address, external symbol, or scratch register");
> -
>     return DAG.getNode(X86ISD::TC_RETURN, dl,
>                        NodeTys, &Ops[0], Ops.size());
>   }
>
> Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original)
> +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Sat Mar 13 21:48:46 2010
> @@ -33,6 +33,15 @@
>   let ParserMatchClass = ImmSExt8AsmOperand;
>  }
>
> +// Special i64mem for addresses of load folding tail calls. These are not
> +// allowed to use callee-saved registers since they must be scheduled
> +// after callee-saved register are popped.
> +def i64mem_TC : Operand<i64> {
> +  let PrintMethod = "printi64mem";
> +  let MIOperandInfo = (ops GR64_TC, i8imm, GR64_TC, i32imm, i8imm);
> +  let ParserMatchClass = X86MemAsmOperand;
> +}
> +
>  def lea64mem : Operand<i64> {
>   let PrintMethod = "printlea64mem";
>   let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm);
> @@ -177,22 +186,31 @@
>
>
>  let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -def TCRETURNdi64 : I<0, Pseudo, (outs), (ins i64imm:$dst, i32imm:$offset,
> -                                         variable_ops),
> -                 "#TC_RETURN $dst $offset",
> -                 []>;
> -
> -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -def TCRETURNri64 : I<0, Pseudo, (outs), (ins GR64:$dst, i32imm:$offset,
> -                                         variable_ops),
> -                 "#TC_RETURN $dst $offset",
> -                 []>;
> -
> +  let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
> +              FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1,
> +              MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
> +              XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
> +              XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
> +      Uses = [RSP] in {
> +  def TCRETURNdi64 : I<0, Pseudo, (outs),
> +                         (ins i64i32imm_pcrel:$dst, i32imm:$offset, variable_ops),
> +                       "#TC_RETURN $dst $offset", []>;
> +  def TCRETURNri64 : I<0, Pseudo, (outs), (ins GR64_TC:$dst, i32imm:$offset,
> +                                           variable_ops),
> +                       "#TC_RETURN $dst $offset", []>;
> +  def TCRETURNmi64 : I<0, Pseudo, (outs),
> +                       (ins i64mem_TC:$dst, i32imm:$offset, variable_ops),
> +                       "#TC_RETURN $dst $offset", []>;
> +
> +  def TAILJMPd64 : Ii32<0xE9, RawFrm, (outs),
> +                                      (ins i64i32imm_pcrel:$dst, variable_ops),
> +                   "jmp\t$dst  # TAILCALL", []>;
> +  def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins GR64_TC:$dst, variable_ops),
> +                     "jmp{q}\t{*}$dst  # TAILCALL", []>;
>
> -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -  def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins GR64:$dst, variable_ops),
> -                   "jmp{q}\t{*}$dst  # TAILCALL",
> -                   []>;
> +  def TAILJMPm64 : I<0xff, MRM4m, (outs), (ins i64mem_TC:$dst, variable_ops),
> +                     "jmp{q}\t{*}$dst  # TAILCALL", []>;
> +}
>
>  // Branches
>  let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
> @@ -340,6 +358,22 @@
>                       "mov{q}\t{$src, $dst|$dst, $src}",
>                       [(store i64immSExt32:$src, addr:$dst)]>;
>
> +/// Versions of MOV64rr, MOV64rm, and MOV64mr for i64mem_TC and GR64_TC.
> +let neverHasSideEffects = 1 in
> +def MOV64rr_TC : I<0x89, MRMDestReg, (outs GR64_TC:$dst), (ins GR64_TC:$src),
> +                "mov{q}\t{$src, $dst|$dst, $src}", []>;
> +
> +let mayLoad = 1,
> +    canFoldAsLoad = 1, isReMaterializable = 1 in
> +def MOV64rm_TC : I<0x8B, MRMSrcMem, (outs GR64_TC:$dst), (ins i64mem_TC:$src),
> +                "mov{q}\t{$src, $dst|$dst, $src}",
> +                []>;
> +
> +let mayStore = 1 in
> +def MOV64mr_TC : I<0x89, MRMDestMem, (outs), (ins i64mem_TC:$dst, GR64_TC:$src),
> +                "mov{q}\t{$src, $dst|$dst, $src}",
> +                []>;
> +
>  def MOV64o8a : RIi8<0xA0, RawFrm, (outs), (ins offset8:$src),
>                       "mov{q}\t{$src, %rax|%rax, $src}", []>;
>  def MOV64o64a : RIi32<0xA1, RawFrm, (outs), (ins offset64:$src),
> @@ -1885,14 +1919,21 @@
>           (WINCALL64pcrel32 texternalsym:$dst)>, Requires<[IsWin64]>;
>
>  // tailcall stuff
> -def : Pat<(X86tcret GR64:$dst, imm:$off),
> -          (TCRETURNri64 GR64:$dst, imm:$off)>;
> +def : Pat<(X86tcret GR64_TC:$dst, imm:$off),
> +          (TCRETURNri64 GR64_TC:$dst, imm:$off)>,
> +         Requires<[In64BitMode]>;
> +
> +def : Pat<(X86tcret (load addr:$dst), imm:$off),
> +          (TCRETURNmi64 addr:$dst, imm:$off)>,
> +         Requires<[In64BitMode]>;
>
>  def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off),
> -          (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>;
> +          (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>,
> +         Requires<[In64BitMode]>;
>
>  def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off),
> -          (TCRETURNdi64 texternalsym:$dst, imm:$off)>;
> +          (TCRETURNdi64 texternalsym:$dst, imm:$off)>,
> +         Requires<[In64BitMode]>;
>
>  // Comparisons.
>
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Sat Mar 13 21:48:46 2010
> @@ -266,6 +266,7 @@
>     { X86::MOV16rr,     X86::MOV16mr, 0, 0 },
>     { X86::MOV32ri,     X86::MOV32mi, 0, 0 },
>     { X86::MOV32rr,     X86::MOV32mr, 0, 0 },
> +    { X86::MOV32rr_TC,  X86::MOV32mr_TC, 0, 0 },
>     { X86::MOV64ri32,   X86::MOV64mi32, 0, 0 },
>     { X86::MOV64rr,     X86::MOV64mr, 0, 0 },
>     { X86::MOV8ri,      X86::MOV8mi, 0, 0 },
> @@ -301,6 +302,7 @@
>     { X86::SETPr,       X86::SETPm, 0, 0 },
>     { X86::SETSr,       X86::SETSm, 0, 0 },
>     { X86::TAILJMPr,    X86::TAILJMPm, 1, 0 },
> +    { X86::TAILJMPr64,  X86::TAILJMPm64, 1, 0 },
>     { X86::TEST16ri,    X86::TEST16mi, 1, 0 },
>     { X86::TEST32ri,    X86::TEST32mi, 1, 0 },
>     { X86::TEST64ri32,  X86::TEST64mi32, 1, 0 },
> @@ -376,6 +378,7 @@
>     { X86::Int_UCOMISSrr,   X86::Int_UCOMISSrm, 0 },
>     { X86::MOV16rr,         X86::MOV16rm, 0 },
>     { X86::MOV32rr,         X86::MOV32rm, 0 },
> +    { X86::MOV32rr_TC,      X86::MOV32rm_TC, 0 },
>     { X86::MOV64rr,         X86::MOV64rm, 0 },
>     { X86::MOV64toPQIrr,    X86::MOVQI2PQIrm, 0 },
>     { X86::MOV64toSDrr,     X86::MOV64toSDrm, 0 },
> @@ -675,6 +678,8 @@
>   case X86::MOV16rr:
>   case X86::MOV32rr:
>   case X86::MOV64rr:
> +  case X86::MOV32rr_TC:
> +  case X86::MOV64rr_TC:
>
>   // FP Stack register class copies
>   case X86::MOV_Fp3232: case X86::MOV_Fp6464: case X86::MOV_Fp8080:
> @@ -1901,6 +1906,10 @@
>       Opc = X86::MOV16rr;
>     } else if (CommonRC == &X86::GR8_NOREXRegClass) {
>       Opc = X86::MOV8rr;
> +    } else if (CommonRC == &X86::GR64_TCRegClass) {
> +      Opc = X86::MOV64rr_TC;
> +    } else if (CommonRC == &X86::GR32_TCRegClass) {
> +      Opc = X86::MOV32rr_TC;
>     } else if (CommonRC == &X86::RFP32RegClass) {
>       Opc = X86::MOV_Fp3232;
>     } else if (CommonRC == &X86::RFP64RegClass || CommonRC == &X86::RSTRegClass) {
> @@ -2038,6 +2047,10 @@
>     Opc = X86::MOV16mr;
>   } else if (RC == &X86::GR8_NOREXRegClass) {
>     Opc = X86::MOV8mr;
> +  } else if (RC == &X86::GR64_TCRegClass) {
> +    Opc = X86::MOV64mr_TC;
> +  } else if (RC == &X86::GR32_TCRegClass) {
> +    Opc = X86::MOV32mr_TC;
>   } else if (RC == &X86::RFP80RegClass) {
>     Opc = X86::ST_FpP80m;   // pops
>   } else if (RC == &X86::RFP64RegClass) {
> @@ -2131,6 +2144,10 @@
>     Opc = X86::MOV16rm;
>   } else if (RC == &X86::GR8_NOREXRegClass) {
>     Opc = X86::MOV8rm;
> +  } else if (RC == &X86::GR64_TCRegClass) {
> +    Opc = X86::MOV64rm_TC;
> +  } else if (RC == &X86::GR32_TCRegClass) {
> +    Opc = X86::MOV32rm_TC;
>   } else if (RC == &X86::RFP80RegClass) {
>     Opc = X86::LD_Fp80m;
>   } else if (RC == &X86::RFP64RegClass) {
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Sat Mar 13 21:48:46 2010
> @@ -234,6 +234,15 @@
>   let ParserMatchClass = X86MemAsmOperand;
>  }
>
> +// Special i32mem for addresses of load folding tail calls. These are not
> +// allowed to use callee-saved registers since they must be scheduled
> +// after callee-saved register are popped.
> +def i32mem_TC : Operand<i32> {
> +  let PrintMethod = "printi32mem";
> +  let MIOperandInfo = (ops GR32_TC, i8imm, GR32_TC, i32imm, i8imm);
> +  let ParserMatchClass = X86MemAsmOperand;
> +}
> +
>  def lea32mem : Operand<i32> {
>   let PrintMethod = "printlea32mem";
>   let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
> @@ -696,30 +705,33 @@
>  // Tail call stuff.
>
>  let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -def TCRETURNdi : I<0, Pseudo, (outs),
> -                   (ins i32imm:$dst, i32imm:$offset, variable_ops),
> -                 "#TC_RETURN $dst $offset",
> -                 []>;
> -
> -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -def TCRETURNri : I<0, Pseudo, (outs),
> -                   (ins GR32:$dst, i32imm:$offset, variable_ops),
> -                 "#TC_RETURN $dst $offset",
> -                 []>;
> -
> -// FIXME: The should be pseudo instructions that are lowered when going to
> -// mcinst.
> -let isCall = 1, isBranch = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -  def TAILJMPd : Ii32<0xE9, RawFrm, (outs),(ins i32imm_pcrel:$dst,variable_ops),
> +  let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
> +              MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
> +              XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
> +              XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
> +      Uses = [ESP] in {
> +  def TCRETURNdi : I<0, Pseudo, (outs),
> +                     (ins i32imm_pcrel:$dst, i32imm:$offset, variable_ops),
> +                   "#TC_RETURN $dst $offset", []>;
> +  def TCRETURNri : I<0, Pseudo, (outs),
> +                     (ins GR32_TC:$dst, i32imm:$offset, variable_ops),
> +                     "#TC_RETURN $dst $offset", []>;
> +  def TCRETURNmi : I<0, Pseudo, (outs),
> +                     (ins i32mem_TC:$dst, i32imm:$offset, variable_ops),
> +                     "#TC_RETURN $dst $offset", []>;
> +
> +  // FIXME: The should be pseudo instructions that are lowered when going to
> +  // mcinst.
> +  def TAILJMPd : Ii32<0xE9, RawFrm, (outs),
> +                                    (ins i32imm_pcrel:$dst, variable_ops),
>                  "jmp\t$dst  # TAILCALL",
>                  []>;
> -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -  def TAILJMPr : I<0xFF, MRM4r, (outs), (ins GR32:$dst, variable_ops),
> +  def TAILJMPr : I<0xFF, MRM4r, (outs), (ins GR32_TC:$dst, variable_ops),
>                    "jmp{l}\t{*}$dst  # TAILCALL",
>                  []>;
> -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
> -  def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem:$dst, variable_ops),
> -                   "jmp\t{*}$dst  # TAILCALL", []>;
> +  def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem_TC:$dst, variable_ops),
> +                   "jmp{l}\t{*}$dst  # TAILCALL", []>;
> +}
>
>  //===----------------------------------------------------------------------===//
>  //  Miscellaneous Instructions...
> @@ -1032,6 +1044,22 @@
>                 "mov{l}\t{$src, $dst|$dst, $src}",
>                 [(store GR32:$src, addr:$dst)]>;
>
> +/// Versions of MOV32rr, MOV32rm, and MOV32mr for i32mem_TC and GR32_TC.
> +let neverHasSideEffects = 1 in
> +def MOV32rr_TC : I<0x89, MRMDestReg, (outs GR32_TC:$dst), (ins GR32_TC:$src),
> +                "mov{l}\t{$src, $dst|$dst, $src}", []>;
> +
> +let mayLoad = 1,
> +    canFoldAsLoad = 1, isReMaterializable = 1 in
> +def MOV32rm_TC : I<0x8B, MRMSrcMem, (outs GR32_TC:$dst), (ins i32mem_TC:$src),
> +                "mov{l}\t{$src, $dst|$dst, $src}",
> +                []>;
> +
> +let mayStore = 1 in
> +def MOV32mr_TC : I<0x89, MRMDestMem, (outs), (ins i32mem_TC:$dst, GR32_TC:$src),
> +                "mov{l}\t{$src, $dst|$dst, $src}",
> +                []>;
> +
>  // Versions of MOV8rr, MOV8mr, and MOV8rm that use i8mem_NOREX and GR8_NOREX so
>  // that they can be used for copying and storing h registers, which can't be
>  // encoded when a REX prefix is present.
> @@ -4294,14 +4322,21 @@
>
>  // Calls
>  // tailcall stuff
> -def : Pat<(X86tcret GR32:$dst, imm:$off),
> -          (TCRETURNri GR32:$dst, imm:$off)>;
> +def : Pat<(X86tcret GR32_TC:$dst, imm:$off),
> +          (TCRETURNri GR32_TC:$dst, imm:$off)>,
> +         Requires<[In32BitMode]>;
> +
> +def : Pat<(X86tcret (load addr:$dst), imm:$off),
> +          (TCRETURNmi addr:$dst, imm:$off)>,
> +         Requires<[In32BitMode]>;
>
>  def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off),
> -          (TCRETURNdi texternalsym:$dst, imm:$off)>;
> +          (TCRETURNdi texternalsym:$dst, imm:$off)>,
> +         Requires<[In32BitMode]>;
>
>  def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off),
> -          (TCRETURNdi texternalsym:$dst, imm:$off)>;
> +          (TCRETURNdi texternalsym:$dst, imm:$off)>,
> +         Requires<[In32BitMode]>;
>
>  // Normal calls, with various flavors of addresses.
>  def : Pat<(X86call (i32 tglobaladdr:$dst)),
>
> Modified: llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp Sat Mar 13 21:48:46 2010
> @@ -1138,13 +1138,12 @@
>   case X86::RETI:
>   case X86::TCRETURNdi:
>   case X86::TCRETURNri:
> -  case X86::TCRETURNri64:
> +  case X86::TCRETURNmi:
>   case X86::TCRETURNdi64:
> +  case X86::TCRETURNri64:
> +  case X86::TCRETURNmi64:
>   case X86::EH_RETURN:
>   case X86::EH_RETURN64:
> -  case X86::TAILJMPd:
> -  case X86::TAILJMPr:
> -  case X86::TAILJMPm:
>     break;  // These are ok
>   }
>
> @@ -1229,11 +1228,14 @@
>             TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
>             StackPtr).addReg(DestAddr.getReg());
>   } else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi ||
> -             RetOpcode== X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64) {
> +             RetOpcode == X86::TCRETURNmi ||
> +             RetOpcode == X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64 ||
> +             RetOpcode == X86::TCRETURNmi64) {
> +    bool isMem = RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64;
>     // Tail call return: adjust the stack pointer and jump to callee.
>     MBBI = prior(MBB.end());
>     MachineOperand &JumpTarget = MBBI->getOperand(0);
> -    MachineOperand &StackAdjust = MBBI->getOperand(1);
> +    MachineOperand &StackAdjust = MBBI->getOperand(isMem ? 5 : 1);
>     assert(StackAdjust.isImm() && "Expecting immediate value.");
>
>     // Adjust stack pointer.
> @@ -1253,10 +1255,17 @@
>     }
>
>     // Jump to label or value in register.
> -    if (RetOpcode == X86::TCRETURNdi|| RetOpcode == X86::TCRETURNdi64) {
> -      BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPd)).
> +    if (RetOpcode == X86::TCRETURNdi || RetOpcode == X86::TCRETURNdi64) {
> +      BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNdi)
> +                                     ? X86::TAILJMPd : X86::TAILJMPd64)).
>         addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
>                          JumpTarget.getTargetFlags());
> +    } else if (RetOpcode == X86::TCRETURNmi || RetOpcode == X86::TCRETURNmi64) {
> +      MachineInstrBuilder MIB =
> +        BuildMI(MBB, MBBI, DL, TII.get((RetOpcode == X86::TCRETURNmi)
> +                                       ? X86::TAILJMPm : X86::TAILJMPm64));
> +      for (unsigned i = 0; i != 5; ++i)
> +        MIB.addOperand(MBBI->getOperand(i));
>     } else if (RetOpcode == X86::TCRETURNri64) {
>       BuildMI(MBB, MBBI, DL, TII.get(X86::TAILJMPr64), JumpTarget.getReg());
>     } else {
>
> Modified: llvm/trunk/lib/Target/X86/X86RegisterInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86RegisterInfo.td?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86RegisterInfo.td (original)
> +++ llvm/trunk/lib/Target/X86/X86RegisterInfo.td Sat Mar 13 21:48:46 2010
> @@ -535,6 +535,13 @@
>  def GR64_ABCD : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RBX]> {
>   let SubRegClassList = [GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD, GR32_ABCD];
>  }
> +def GR32_TC   : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX]> {
> +  let SubRegClassList = [GR8, GR8, GR16];
> +}
> +def GR64_TC   : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RSI, RDI,
> +                                                 R8, R9, R11]> {
> +  let SubRegClassList = [GR8, GR8, GR16, GR32_TC];
> +}
>
>  // GR8_NOREX - GR8 registers which do not require a REX prefix.
>  def GR8_NOREX : RegisterClass<"X86", [i8], 8,
>
> Modified: llvm/trunk/test/CodeGen/X86/tailcall-largecode.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcall-largecode.ll?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcall-largecode.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/tailcall-largecode.ll Sat Mar 13 21:48:46 2010
> @@ -20,7 +20,7 @@
>  ;  CHECK: subq $8, %rsp
>  ; Put the call target into R11, which won't be clobbered while restoring
>  ; callee-saved registers and won't be used for passing arguments.
> -;  CHECK: movq %rdi, %r11
> +;  CHECK: movq %rdi, %rax
>  ; Pass the stack argument.
>  ;  CHECK: movl $7, 16(%rsp)
>  ; Pass the register arguments, in the right registers.
> @@ -33,7 +33,7 @@
>  ; Adjust the stack to "return".
>  ;  CHECK: addq $8, %rsp
>  ; And tail-call to the target.
> -;  CHECK: jmpq *%r11  # TAILCALL
> +;  CHECK: jmpq *%rax  # TAILCALL
>   %res = tail call fastcc i32 %target(i32 1, i32 2, i32 3, i32 4, i32 5,
>                                       i32 6, i32 7)
>   ret i32 %res
> @@ -60,11 +60,11 @@
>  ; the jmp instruction.  Put it into R11, which won't be clobbered
>  ; while restoring callee-saved registers and won't be used for passing
>  ; arguments.
> -;  CHECK: movabsq $manyargs_callee, %r11
> +;  CHECK: movabsq $manyargs_callee, %rax
>  ; Adjust the stack to "return".
>  ;  CHECK: addq $8, %rsp
>  ; And tail-call to the target.
> -;  CHECK: jmpq *%r11  # TAILCALL
> +;  CHECK: jmpq *%rax  # TAILCALL
>   %res = tail call fastcc i32 @manyargs_callee(i32 1, i32 2, i32 3, i32 4,
>                                                i32 5, i32 6, i32 7)
>   ret i32 %res
>
> Modified: llvm/trunk/test/CodeGen/X86/tailcallfp2.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcallfp2.ll?rev=98465&r1=98464&r2=98465&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcallfp2.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/tailcallfp2.ll Sat Mar 13 21:48:46 2010
> @@ -1,4 +1,4 @@
> -; RUN: llc < %s -march=x86 -tailcallopt | grep {jmp} | grep {\\*%eax}
> +; RUN: llc < %s -march=x86 -tailcallopt | grep {jmp} | grep {\\*%edx}
>
>  declare i32 @putchar(i32)
>
>
>
> _______________________________________________
> 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