aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lenharth <alenhar2@cs.uiuc.edu>2008-03-01 21:52:34 +0000
committerAndrew Lenharth <alenhar2@cs.uiuc.edu>2008-03-01 21:52:34 +0000
commit7dfe23f07fa1482f30c658938ea87936c76bbc93 (patch)
treed6215ef751ec116a283291bb2d307f80bd3b3f15
parent2c3eced4d5e96fe170c2bdb8b5090966ed15b484 (diff)
downloadexternal_llvm-7dfe23f07fa1482f30c658938ea87936c76bbc93.zip
external_llvm-7dfe23f07fa1482f30c658938ea87936c76bbc93.tar.gz
external_llvm-7dfe23f07fa1482f30c658938ea87936c76bbc93.tar.bz2
all but CAS working on x86
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47798 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp27
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp28
-rw-r--r--lib/Target/X86/X86ISelLowering.h4
-rw-r--r--lib/Target/X86/X86InstrInfo.td57
4 files changed, 70 insertions, 46 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index bd9e230..c28c2f9 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 8acf779..4cb9491 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<AtomicSDNode>(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 5e8a32f..345aa01 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 87a001a..a109dc6 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
//===----------------------------------------------------------------------===//