summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorMarcin Koscielnicki <koriakin@0x04.net>2016-05-10 16:49:04 +0000
committerMarcin Koscielnicki <koriakin@0x04.net>2016-05-10 16:49:04 +0000
commitbbac890b532499c8e5b4f5c587ecc7667ddc8293 (patch)
treec81a60fff97bd37c089d372c89ac3b1557de49ad /llvm/lib
parent27d12d3d1f258d1b3caf593bb56f393a5567d40d (diff)
downloadbcm5719-llvm-bbac890b532499c8e5b4f5c587ecc7667ddc8293.tar.gz
bcm5719-llvm-bbac890b532499c8e5b4f5c587ecc7667ddc8293.zip
[PR27599] [SystemZ] [SelectionDAG] Fix extension of atomic cmpxchg result.
Currently, SelectionDAG assumes 8/16-bit cmpxchg returns either a sign extended result, or a zero extended result. SystemZ takes a third option by returning junk in the high bits (rotated contents of the other bytes in the memory word). In that case, don't use Assert*ext, and zero-extend the result ourselves if a comparison is needed. Differential Revision: http://reviews.llvm.org/D19800 llvm-svn: 269075
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp21
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.h4
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.h4
3 files changed, 23 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index a06932b0521..b8918d21fc9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2837,25 +2837,38 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
cast<AtomicSDNode>(Node)->getFailureOrdering(),
cast<AtomicSDNode>(Node)->getSynchScope());
+ SDValue ExtRes = Res;
SDValue LHS = Res;
SDValue RHS = Node->getOperand(1);
EVT AtomicType = cast<AtomicSDNode>(Node)->getMemoryVT();
EVT OuterType = Node->getValueType(0);
- if (TLI.hasSignExtendedAtomicOps()) {
+ switch (TLI.getExtendForAtomicOps()) {
+ case ISD::SIGN_EXTEND:
LHS = DAG.getNode(ISD::AssertSext, dl, OuterType, Res,
DAG.getValueType(AtomicType));
RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, OuterType,
Node->getOperand(2), DAG.getValueType(AtomicType));
- } else {
- LHS = DAG.getNode(ISD::AssertZext, dl, OuterType, Res, DAG.getValueType(AtomicType));
+ ExtRes = LHS;
+ break;
+ case ISD::ZERO_EXTEND:
+ LHS = DAG.getNode(ISD::AssertZext, dl, OuterType, Res,
+ DAG.getValueType(AtomicType));
RHS = DAG.getNode(ISD::ZERO_EXTEND, dl, OuterType, Node->getOperand(2));
+ ExtRes = LHS;
+ break;
+ case ISD::ANY_EXTEND:
+ LHS = DAG.getZeroExtendInReg(Res, dl, AtomicType);
+ RHS = DAG.getNode(ISD::ZERO_EXTEND, dl, OuterType, Node->getOperand(2));
+ break;
+ default:
+ llvm_unreachable("Invalid atomic op extension");
}
SDValue Success =
DAG.getSetCC(dl, Node->getValueType(1), LHS, RHS, ISD::SETEQ);
- Results.push_back(LHS.getValue(0));
+ Results.push_back(ExtRes.getValue(0));
Results.push_back(Success);
Results.push_back(Res.getValue(1));
break;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 31ae235ab45..a56918c0519 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -238,8 +238,8 @@ namespace llvm {
bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override;
- bool hasSignExtendedAtomicOps() const override {
- return true;
+ ISD::NodeType getExtendForAtomicOps() const override {
+ return ISD::SIGN_EXTEND;
}
void LowerOperationWrapper(SDNode *N,
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index f26e1dc0d66..bfd08543563 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -459,6 +459,10 @@ public:
SelectionDAG &DAG) const override;
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
+ ISD::NodeType getExtendForAtomicOps() const override {
+ return ISD::ANY_EXTEND;
+ }
+
bool supportSwiftError() const override {
return true;
}
OpenPOWER on IntegriCloud