diff options
-rw-r--r-- | llvm/include/llvm/Target/TargetLowering.h | 5 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.h | 4 | ||||
-rw-r--r-- | llvm/test/CodeGen/Mips/atomic.ll | 54 |
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 |