diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index d8c60df4f42..37920ae9141 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -361,6 +361,26 @@ namespace RTLIB { SYNC_FETCH_AND_NAND_4, SYNC_FETCH_AND_NAND_8, SYNC_FETCH_AND_NAND_16, + SYNC_FETCH_AND_MAX_1, + SYNC_FETCH_AND_MAX_2, + SYNC_FETCH_AND_MAX_4, + SYNC_FETCH_AND_MAX_8, + SYNC_FETCH_AND_MAX_16, + SYNC_FETCH_AND_UMAX_1, + SYNC_FETCH_AND_UMAX_2, + SYNC_FETCH_AND_UMAX_4, + SYNC_FETCH_AND_UMAX_8, + SYNC_FETCH_AND_UMAX_16, + SYNC_FETCH_AND_MIN_1, + SYNC_FETCH_AND_MIN_2, + SYNC_FETCH_AND_MIN_4, + SYNC_FETCH_AND_MIN_8, + SYNC_FETCH_AND_MIN_16, + SYNC_FETCH_AND_UMIN_1, + SYNC_FETCH_AND_UMIN_2, + SYNC_FETCH_AND_UMIN_4, + SYNC_FETCH_AND_UMIN_8, + SYNC_FETCH_AND_UMIN_16, // Stack Protector Fail. STACKPROTECTOR_CHECK_FAIL, diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index aa8caedff51..1f112e9f6c5 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2734,6 +2734,46 @@ std::pair SelectionDAGLegalize::ExpandAtomic(SDNode *Node) { case MVT::i128:LC = RTLIB::SYNC_FETCH_AND_NAND_16;break; } break; + case ISD::ATOMIC_LOAD_MAX: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_MAX_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_MAX_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_MAX_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_MAX_8; break; + case MVT::i128:LC = RTLIB::SYNC_FETCH_AND_MAX_16;break; + } + break; + case ISD::ATOMIC_LOAD_UMAX: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_UMAX_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_UMAX_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_UMAX_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_UMAX_8; break; + case MVT::i128:LC = RTLIB::SYNC_FETCH_AND_UMAX_16;break; + } + break; + case ISD::ATOMIC_LOAD_MIN: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_MIN_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_MIN_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_MIN_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_MIN_8; break; + case MVT::i128:LC = RTLIB::SYNC_FETCH_AND_MIN_16;break; + } + break; + case ISD::ATOMIC_LOAD_UMIN: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_UMIN_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_UMIN_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_UMIN_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_UMIN_8; break; + case MVT::i128:LC = RTLIB::SYNC_FETCH_AND_UMIN_16;break; + } + break; } return ExpandChainLibCall(LC, Node, false); diff --git a/lib/CodeGen/TargetLoweringBase.cpp b/lib/CodeGen/TargetLoweringBase.cpp index bfed53e07e3..63743b6c923 100644 --- a/lib/CodeGen/TargetLoweringBase.cpp +++ b/lib/CodeGen/TargetLoweringBase.cpp @@ -354,6 +354,26 @@ static void InitLibcallNames(const char **Names, const TargetMachine &TM) { Names[RTLIB::SYNC_FETCH_AND_NAND_4] = "__sync_fetch_and_nand_4"; Names[RTLIB::SYNC_FETCH_AND_NAND_8] = "__sync_fetch_and_nand_8"; Names[RTLIB::SYNC_FETCH_AND_NAND_16] = "__sync_fetch_and_nand_16"; + Names[RTLIB::SYNC_FETCH_AND_MAX_1] = "__sync_fetch_and_max_1"; + Names[RTLIB::SYNC_FETCH_AND_MAX_2] = "__sync_fetch_and_max_2"; + Names[RTLIB::SYNC_FETCH_AND_MAX_4] = "__sync_fetch_and_max_4"; + Names[RTLIB::SYNC_FETCH_AND_MAX_8] = "__sync_fetch_and_max_8"; + Names[RTLIB::SYNC_FETCH_AND_MAX_16] = "__sync_fetch_and_max_16"; + Names[RTLIB::SYNC_FETCH_AND_UMAX_1] = "__sync_fetch_and_umax_1"; + Names[RTLIB::SYNC_FETCH_AND_UMAX_2] = "__sync_fetch_and_umax_2"; + Names[RTLIB::SYNC_FETCH_AND_UMAX_4] = "__sync_fetch_and_umax_4"; + Names[RTLIB::SYNC_FETCH_AND_UMAX_8] = "__sync_fetch_and_umax_8"; + Names[RTLIB::SYNC_FETCH_AND_UMAX_16] = "__sync_fetch_and_umax_16"; + Names[RTLIB::SYNC_FETCH_AND_MIN_1] = "__sync_fetch_and_min_1"; + Names[RTLIB::SYNC_FETCH_AND_MIN_2] = "__sync_fetch_and_min_2"; + Names[RTLIB::SYNC_FETCH_AND_MIN_4] = "__sync_fetch_and_min_4"; + Names[RTLIB::SYNC_FETCH_AND_MIN_8] = "__sync_fetch_and_min_8"; + Names[RTLIB::SYNC_FETCH_AND_MIN_16] = "__sync_fetch_and_min_16"; + Names[RTLIB::SYNC_FETCH_AND_UMIN_1] = "__sync_fetch_and_umin_1"; + Names[RTLIB::SYNC_FETCH_AND_UMIN_2] = "__sync_fetch_and_umin_2"; + Names[RTLIB::SYNC_FETCH_AND_UMIN_4] = "__sync_fetch_and_umin_4"; + Names[RTLIB::SYNC_FETCH_AND_UMIN_8] = "__sync_fetch_and_umin_8"; + Names[RTLIB::SYNC_FETCH_AND_UMIN_16] = "__sync_fetch_and_umin_16"; if (Triple(TM.getTargetTriple()).getEnvironment() == Triple::GNU) { Names[RTLIB::SINCOS_F32] = "sincosf"; diff --git a/test/CodeGen/ARM/atomic-op.ll b/test/CodeGen/ARM/atomic-op.ll index 6e6b36377fd..fb45b8da8f0 100644 --- a/test/CodeGen/ARM/atomic-op.ll +++ b/test/CodeGen/ARM/atomic-op.ll @@ -1,5 +1,6 @@ ; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s ; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-T1 define void @func(i32 %argc, i8** %argv) nounwind { entry: @@ -24,78 +25,93 @@ entry: ; CHECK: ldrex ; CHECK: add ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_add_4 %0 = atomicrmw add i32* %val1, i32 %tmp monotonic store i32 %0, i32* %old ; CHECK: ldrex ; CHECK: sub ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_sub_4 %1 = atomicrmw sub i32* %val2, i32 30 monotonic store i32 %1, i32* %old ; CHECK: ldrex ; CHECK: add ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_add_4 %2 = atomicrmw add i32* %val2, i32 1 monotonic store i32 %2, i32* %old ; CHECK: ldrex ; CHECK: sub ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_sub_4 %3 = atomicrmw sub i32* %val2, i32 1 monotonic store i32 %3, i32* %old ; CHECK: ldrex ; CHECK: and ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_and_4 %4 = atomicrmw and i32* %andt, i32 4080 monotonic store i32 %4, i32* %old ; CHECK: ldrex ; CHECK: or ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_or_4 %5 = atomicrmw or i32* %ort, i32 4080 monotonic store i32 %5, i32* %old ; CHECK: ldrex ; CHECK: eor ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_xor_4 %6 = atomicrmw xor i32* %xort, i32 4080 monotonic store i32 %6, i32* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_min_4 %7 = atomicrmw min i32* %val2, i32 16 monotonic store i32 %7, i32* %old %neg = sub i32 0, 1 ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_min_4 %8 = atomicrmw min i32* %val2, i32 %neg monotonic store i32 %8, i32* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_max_4 %9 = atomicrmw max i32* %val2, i32 1 monotonic store i32 %9, i32* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_max_4 %10 = atomicrmw max i32* %val2, i32 0 monotonic store i32 %10, i32* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umin_4 %11 = atomicrmw umin i32* %val2, i32 16 monotonic store i32 %11, i32* %old %uneg = sub i32 0, 1 ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umin_4 %12 = atomicrmw umin i32* %val2, i32 %uneg monotonic store i32 %12, i32* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umax_4 %13 = atomicrmw umax i32* %val2, i32 1 monotonic store i32 %13, i32* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umax_4 %14 = atomicrmw umax i32* %val2, i32 0 monotonic store i32 %14, i32* %old @@ -110,22 +126,26 @@ entry: ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umin_2 %0 = atomicrmw umin i16* %val, i16 16 monotonic store i16 %0, i16* %old %uneg = sub i16 0, 1 ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umin_2 %1 = atomicrmw umin i16* %val, i16 %uneg monotonic store i16 %1, i16* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umax_2 %2 = atomicrmw umax i16* %val, i16 1 monotonic store i16 %2, i16* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umax_2 %3 = atomicrmw umax i16* %val, i16 0 monotonic store i16 %3, i16* %old ret void @@ -139,22 +159,26 @@ entry: ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umin_1 %0 = atomicrmw umin i8* %val, i8 16 monotonic store i8 %0, i8* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umin_1 %uneg = sub i8 0, 1 %1 = atomicrmw umin i8* %val, i8 %uneg monotonic store i8 %1, i8* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umax_1 %2 = atomicrmw umax i8* %val, i8 1 monotonic store i8 %2, i8* %old ; CHECK: ldrex ; CHECK: cmp ; CHECK: strex + ; CHECK-T1: blx ___sync_fetch_and_umax_1 %3 = atomicrmw umax i8* %val, i8 0 monotonic store i8 %3, i8* %old ret void