summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2016-03-24 15:38:38 +0000
committerTim Northover <tnorthover@apple.com>2016-03-24 15:38:38 +0000
commit4498eff9bbbb79b963c97c8cdcaee46796629428 (patch)
treedc3468500053b1eab5e30dd290908643a3d99a31
parent9babad25e59551b72701903db3aead24e820dd01 (diff)
downloadbcm5719-llvm-4498eff9bbbb79b963c97c8cdcaee46796629428.tar.gz
bcm5719-llvm-4498eff9bbbb79b963c97c8cdcaee46796629428.zip
CodeGen: extend RHS when splitting ATOMIC_CMP_SWAP_WITH_SUCCESS.
If the operation's type has been promoted during type legalization, we need to account for the fact that the high bits of the comparison operand are likely unspecified. The LHS is usually zero-extended, but MIPS sign extends it, so we have to be slightly careful. Patch by Simon Dardis. llvm-svn: 264296
-rw-r--r--llvm/include/llvm/Target/TargetLowering.h5
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp21
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.h4
-rw-r--r--llvm/test/CodeGen/Mips/atomic.ll54
4 files changed, 79 insertions, 5 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h
index 099b22f9435..f7d763b0de3 100644
--- a/llvm/include/llvm/Target/TargetLowering.h
+++ b/llvm/include/llvm/Target/TargetLowering.h
@@ -1172,6 +1172,11 @@ public:
return nullptr;
}
+ /// Returns true if the platform's atomic operations are sign extended.
+ virtual bool hasSignExtendedAtomicOps() const {
+ return false;
+ }
+
/// Returns true if we should normalize
/// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and
/// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) if it is likely
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 40a3bdd4e51..c24999b06dd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3118,10 +3118,25 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
cast<AtomicSDNode>(Node)->getFailureOrdering(),
cast<AtomicSDNode>(Node)->getSynchScope());
- SDValue Success = DAG.getSetCC(SDLoc(Node), Node->getValueType(1),
- Res, Node->getOperand(2), ISD::SETEQ);
+ SDValue LHS = Res;
+ SDValue RHS = Node->getOperand(1);
+
+ EVT AtomicType = cast<AtomicSDNode>(Node)->getMemoryVT();
+ EVT OuterType = Node->getValueType(0);
+ if (TLI.hasSignExtendedAtomicOps()) {
+ 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));
+ RHS = DAG.getNode(ISD::ZERO_EXTEND, dl, OuterType, Node->getOperand(2));
+ }
+
+ SDValue Success =
+ DAG.getSetCC(dl, Node->getValueType(1), LHS, RHS, ISD::SETEQ);
- Results.push_back(Res.getValue(0));
+ Results.push_back(LHS.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 f1b31243623..31ae235ab45 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -238,6 +238,10 @@ namespace llvm {
bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override;
+ bool hasSignExtendedAtomicOps() const override {
+ return true;
+ }
+
void LowerOperationWrapper(SDNode *N,
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG) const override;
diff --git a/llvm/test/CodeGen/Mips/atomic.ll b/llvm/test/CodeGen/Mips/atomic.ll
index a0cbe0ecb13..1cde5468f05 100644
--- a/llvm/test/CodeGen/Mips/atomic.ll
+++ b/llvm/test/CodeGen/Mips/atomic.ll
@@ -357,10 +357,17 @@ entry:
; NO-SEB-SEH: sll $[[R18:[0-9]+]], $[[R17]], 24
; NO-SEB-SEH: sra $[[R19:[0-9]+]], $[[R18]], 24
+; FIXME: -march=mips produces a redundant sign extension here...
+; NO-SEB-SEH: sll $[[R20:[0-9]+]], $5, 24
+; NO-SEB-SEH: sra $[[R20]], $[[R20]], 24
+
; HAS-SEB-SEH: seb $[[R19:[0-9]+]], $[[R17]]
-; ALL: xor $[[R20:[0-9]+]], $[[R19]], $5
-; ALL: sltiu $2, $[[R20]], 1
+; FIXME: ...Leading to this split check.
+; NO-SEB-SEH: xor $[[R21:[0-9]+]], $[[R19]], $[[R20]]
+; HAS-SEB-SEH: xor $[[R21:[0-9]+]], $[[R19]], $5
+
+; ALL: sltiu $2, $[[R21]], 1
}
; Check one i16 so that we cover the seh sign extend
@@ -407,6 +414,49 @@ entry:
; MIPS32R2: seh $2, $[[R16]]
}
+; Test that the i16 return value from cmpxchg is recognised as signed,
+; so that setCC doesn't end up comparing an unsigned value to a signed
+; value.
+; The rest of the functions here are testing the atomic expansion, so
+; we just match the end of the function.
+define {i16, i1} @foo(i16* %addr, i16 %l, i16 %r, i16 %new) {
+ %desired = add i16 %l, %r
+ %res = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst seq_cst
+ ret {i16, i1} %res
+
+; ALL-LABEL: foo
+; MIPSR6: addu $[[R2:[0-9]+]], $[[R1:[0-9]+]], $[[R0:[0-9]+]]
+; NOT-MICROMIPS: addu $[[R2:[0-9]+]], $[[R1:[0-9]+]], $[[R0:[0-9]+]]
+; MICROMIPS: addu16 $[[R2:[0-9]+]], $[[R1:[0-9]+]], $[[R0:[0-9]+]]
+
+; ALL: sync
+
+; ALL: andi $[[R3:[0-9]+]], $[[R2]], 65535
+; ALL: $[[BB0:[A-Z_0-9]+]]:
+; ALL: ll $[[R4:[0-9]+]], 0($[[R5:[0-9]+]])
+; ALL: and $[[R6:[0-9]+]], $[[R4]], $
+; ALL: and $[[R7:[0-9]+]], $[[R4]], $
+; ALL: or $[[R8:[0-9]+]], $[[R7]], $
+; ALL: sc $[[R8]], 0($[[R5]])
+; NOT-MICROMIPS: beqz $[[R8]], $[[BB0]]
+; MICROMIPS: beqzc $[[R8]], $[[BB0]]
+; MIPSR6: beqzc $[[R8]], $[[BB0]]
+
+; ALL: srlv $[[R9:[0-9]+]], $[[R6]], $
+
+; NO-SEB-SEH: sll $[[R10:[0-9]+]], $[[R9]], 16
+; NO-SEB-SEH: sra $[[R11:[0-9]+]], $[[R10]], 16
+
+; NO-SEB-SEH: sll $[[R12:[0-9]+]], $[[R2]], 16
+; NO-SEB-SEH: sra $[[R13:[0-9]+]], $[[R12]], 16
+
+; HAS-SEB-SEH: seh $[[R11:[0-9]+]], $[[R9]]
+; HAS-SEB-SEH: seh $[[R13:[0-9]+]], $[[R2]]
+
+; ALL: xor $[[R12:[0-9]+]], $[[R11]], $[[R13]]
+; ALL: sltiu $3, $[[R12]], 1
+; ALL: sync
+}
@countsint = common global i32 0, align 4
OpenPOWER on IntegriCloud