From 26ed8697d4733f4ad588ef117ec4387560770ad0 Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Sat, 1 Mar 2008 21:52:34 +0000 Subject: [PATCH] all but CAS working on x86 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47798 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 27 +++++------ lib/Target/X86/X86ISelLowering.cpp | 28 ++++++++++++ lib/Target/X86/X86ISelLowering.h | 4 ++ lib/Target/X86/X86InstrInfo.td | 57 ++++++++++-------------- 4 files changed, 70 insertions(+), 46 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index bd9e2302fb6..c28c2f9236d 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1165,23 +1165,24 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { assert(((Node->getNumOperands() == 4 && Node->getOpcode() == ISD::ATOMIC_LCS) || (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_LAS) || (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_SWAP)) && - "Invalid MemBarrier node!"); + "Invalid Atomic node!"); int num = Node->getOpcode() == ISD::ATOMIC_LCS ? 4 : 3; - MVT::ValueType VT = Node->getValueType(0); - switch (TLI.getOperationAction(ISD::ATOMIC_LCS, VT)) { + SDOperand Ops[4]; + for (int x = 0; x < num; ++x) + Ops[x] = LegalizeOp(Node->getOperand(x)); + Result = DAG.UpdateNodeOperands(Result, &Ops[0], num); + + switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { default: assert(0 && "This action is not supported yet!"); - case TargetLowering::Legal: { - SDOperand Ops[4]; - for (int x = 0; x < num; ++x) - Ops[x] = LegalizeOp(Node->getOperand(x)); - Result = DAG.UpdateNodeOperands(Result, &Ops[0], num); - AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0)); - AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1)); - return Result.getValue(Op.ResNo); + case TargetLowering::Custom: + Result = TLI.LowerOperation(Result, DAG); + break; + case TargetLowering::Legal: break; } - } - break; + AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0)); + AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1)); + return Result.getValue(Op.ResNo); } case ISD::Constant: { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8acf779676e..4cb94916138 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -283,6 +283,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) if (!Subtarget->hasSSE2()) setOperationAction(ISD::MEMBARRIER , MVT::Other, Expand); + setOperationAction(ISD::ATOMIC_LCS , MVT::i8, Custom); + setOperationAction(ISD::ATOMIC_LCS , MVT::i16, Custom); + setOperationAction(ISD::ATOMIC_LCS , MVT::i32, Custom); // Use the default ISD::LOCATION, ISD::DECLARE expansion. setOperationAction(ISD::LOCATION, MVT::Other, Expand); @@ -5345,11 +5348,35 @@ SDOperand X86TargetLowering::LowerCTTZ(SDOperand Op, SelectionDAG &DAG) { return Op; } +SDOperand X86TargetLowering::LowerCAS(SDOperand Op, SelectionDAG &DAG) { + MVT::ValueType T = cast(Op.Val)->getVT(); + unsigned Reg; + unsigned size; + switch(T) { + case MVT::i8: Reg = X86::AL; size = 1; break; + case MVT::i16: Reg = X86::AX; size = 2; break; + case MVT::i32: Reg = X86::EAX; size = 4; break; + }; + SDOperand cpIn = DAG.getCopyToReg(Op.getOperand(0), Reg, + Op.getOperand(2), SDOperand()); + SDOperand Ops[] = { cpIn.getValue(0), + Op.getOperand(1), + Op.getOperand(3), + DAG.getTargetConstant(size, MVT::i8), + cpIn.getValue(1) }; + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDOperand Result = DAG.getNode(X86ISD::LCMPXCHG_DAG, Tys, Ops, 5); + SDOperand cpOut = + DAG.getCopyFromReg(Result.getValue(0), Reg, T, Result.getValue(1)); + return cpOut; +} + /// LowerOperation - Provide custom lowering hooks for some operations. /// SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Should not custom lower this!"); + case ISD::ATOMIC_LCS: return LowerCAS(Op,DAG); case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); @@ -5454,6 +5481,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN"; case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN"; case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m"; + case X86ISD::LCMPXCHG_DAG: return "x86ISD::LCMPXCHG_DAG"; } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 5e8a32f5a6e..345aa01e211 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -208,6 +208,9 @@ namespace llvm { // operand #3 optional in flag TC_RETURN, + // compare and swap + LCMPXCHG_DAG, + // Store FP control world into i16 memory FNSTCW16m }; @@ -540,6 +543,7 @@ namespace llvm { SDOperand LowerFLT_ROUNDS_(SDOperand Op, SelectionDAG &DAG); SDOperand LowerCTLZ(SDOperand Op, SelectionDAG &DAG); SDOperand LowerCTTZ(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerCAS(SDOperand Op, SelectionDAG &DAG); SDNode *ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG); SDNode *ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG); }; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 87a001af89c..a109dc64887 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -35,6 +35,9 @@ def SDTX86SetCC : SDTypeProfile<1, 2, [SDTCisVT<0, i8>, SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; +def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, + SDTCisVT<2, i8>]>; + def SDTX86Ret : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>; def SDT_X86CallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; @@ -69,6 +72,10 @@ def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; +def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, + SDNPMayLoad]>; + def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, [SDNPHasChain, SDNPOptInFlag]>; @@ -2539,28 +2546,29 @@ def EH_RETURN : I<0xC3, RawFrm, (outs), (ins GR32:$addr), // Atomic support // -//FIXME: Please check the format - -let Defs = [EAX], Uses = [EAX] in { -def CMPXCHG32 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR32:$swap), - "cmpxchgl $swap,($ptr)", []>, TB; -def LCMPXCHG32 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR32:$swap), - "lock cmpxchgl $swap,($ptr)", []>, TB, LOCK; +//FIXME: Please check the format Pseudo is certainly wrong, but the opcode and +// prefixes should be correct +let Defs = [EAX, EFLAGS], Uses = [EAX] in { +def CMPXCHG32 : I<0xB1, Pseudo, (outs), (ins i32mem:$ptr, GR32:$swap), + "cmpxchgl $swap,$ptr", []>, TB; +def LCMPXCHG32 : I<0xB1, Pseudo, (outs), (ins i32mem:$ptr, GR32:$swap), + "lock cmpxchgl $swap,$ptr", [(X86cas addr:$ptr, GR32:$swap, 4)]>, TB, LOCK; } -let Defs = [AX], Uses = [AX] in { -def CMPXCHG16 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR16:$swap), + +let Defs = [AX, EFLAGS], Uses = [AX] in { +def CMPXCHG16 : I<0xB1, Pseudo, (outs), (ins i16mem:$ptr, GR16:$swap), "cmpxchgw $swap,($ptr)", []>, TB, OpSize; -def LCMPXCHG16 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR16:$swap), - "cmpxchgw $swap,($ptr)", []>, TB, OpSize, LOCK; +def LCMPXCHG16 : I<0xB1, Pseudo, (outs), (ins i16mem:$ptr, GR16:$swap), + "lock cmpxchgw $swap,$ptr", [(X86cas addr:$ptr, GR16:$swap, 2)]>, TB, OpSize, LOCK; } -let Defs = [AL], Uses = [AL] in { -def CMPXCHG8 : I<0xB0, Pseudo, (outs), (ins GR32:$ptr, GR8:$swap), +let Defs = [AL, EFLAGS], Uses = [AL] in { +def CMPXCHG8 : I<0xB0, Pseudo, (outs), (ins i8mem:$ptr, GR8:$swap), "cmpxchgb $swap,($ptr)", []>, TB; -def LCMPXCHG8 : I<0xB0, Pseudo, (outs), (ins GR32:$ptr, GR8:$swap), - "cmpxchgb $swap,($ptr)", []>, TB, LOCK; +def LCMPXCHG8 : I<0xB0, Pseudo, (outs), (ins i8mem:$ptr, GR8:$swap), + "lock cmpxchgb $swap,$ptr", [(X86cas addr:$ptr, GR8:$swap, 1)]>, TB, LOCK; } -let Constraints = "$val = $dst" in { +let Constraints = "$val = $dst", Defs = [EFLAGS] in { def LXADD32 : I<0xC1, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val), "lock xadd $val, $ptr", [(set GR32:$dst, (atomic_las_32 addr:$ptr, GR32:$val))]>, @@ -2598,23 +2606,6 @@ def XCHG8 : I<0x86, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val), "lock xchg $val, $ptr", []>; } -//FIXME: these are a hack until the patterns using the LCMPXCHG written -let Defs = [EAX], Uses = [EAX] in -def PLCMPXCHG32 : I<0, Pseudo, (outs GR32:$dst), - (ins i32mem:$ptr, GR32:$cmp, GR32:$swap), - "movl $cmp, %eax \n lock \n cmpxchgl $swap,$ptr \n movl %eax, $dst", - [(set GR32:$dst, (atomic_lcs_32 addr:$ptr, GR32:$cmp, GR32:$swap))]>; -let Defs = [AX] in -def PLCMPXCHG16 : I<0, Pseudo, (outs GR16:$dst), - (ins i16mem:$ptr, GR16:$cmp, GR16:$swap), - "movw $cmp, %ax \n lock \n cmpxchgw $swap,$ptr \n movw %ax, $dst", - [(set GR16:$dst, (atomic_lcs_16 addr:$ptr, GR16:$cmp, GR16:$swap))]>; -let Defs = [AL] in -def PLCMPXCHG8 : I<0, Pseudo, (outs GR8:$dst), - (ins i8mem:$ptr, GR8:$cmp, GR8:$swap), - "movb $cmp, %al \n lock cmpxchgb $swap,$ptr \n movb %al, $dst", - [(set GR8:$dst, (atomic_lcs_8 addr:$ptr, GR8:$cmp, GR8:$swap))]>; - //===----------------------------------------------------------------------===// // Non-Instruction Patterns //===----------------------------------------------------------------------===// -- 2.34.1