summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff')
-rw-r--r--contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff231
1 files changed, 231 insertions, 0 deletions
diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff
new file mode 100644
index 0000000..041e263
--- /dev/null
+++ b/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff
@@ -0,0 +1,231 @@
+Pull in r198286 from upstream llvm trunk (by Venkatraman Govindaraju):
+
+ [Sparc] Handle atomic loads/stores in sparc backend.
+
+Introduced here: http://svn.freebsd.org/changeset/base/262261
+
+Index: lib/Target/Sparc/SparcInstrInfo.td
+===================================================================
+--- lib/Target/Sparc/SparcInstrInfo.td
++++ lib/Target/Sparc/SparcInstrInfo.td
+@@ -975,6 +975,33 @@ let rs1 = 0 in
+ def : Pat<(ctpop i32:$src),
+ (POPCrr (SRLri $src, 0))>;
+
++// Atomic swap.
++let hasSideEffects =1, rd = 0, rs1 = 0b01111, rs2 = 0 in
++ def STBAR : F3_1<2, 0b101000, (outs), (ins), "stbar", []>;
++
++let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in
++ def MEMBARi : F3_2<2, 0b101000, (outs), (ins i32imm:$simm13),
++ "membar $simm13", []>;
++
++let Constraints = "$val = $rd" in {
++ def SWAPrr : F3_1<3, 0b001111,
++ (outs IntRegs:$rd), (ins IntRegs:$val, MEMrr:$addr),
++ "swap [$addr], $rd",
++ [(set i32:$rd, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>;
++ def SWAPri : F3_2<3, 0b001111,
++ (outs IntRegs:$rd), (ins IntRegs:$val, MEMri:$addr),
++ "swap [$addr], $rd",
++ [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
++}
++
++let Predicates = [HasV9], Constraints = "$swap = $rd" in
++ def CASrr: F3_1<3, 0b111100,
++ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
++ IntRegs:$swap),
++ "cas [$rs1], $rs2, $rd",
++ [(set i32:$rd,
++ (atomic_cmp_swap iPTR:$rs1, i32:$rs2, i32:$swap))]>;
++
+ //===----------------------------------------------------------------------===//
+ // Non-Instruction Patterns
+ //===----------------------------------------------------------------------===//
+@@ -1036,4 +1063,17 @@ def : Pat<(i32 (zextloadi1 ADDRri:$src)), (LDUBri
+ def : Pat<(store (i32 0), ADDRrr:$dst), (STrr ADDRrr:$dst, (i32 G0))>;
+ def : Pat<(store (i32 0), ADDRri:$dst), (STri ADDRri:$dst, (i32 G0))>;
+
++// store bar for all atomic_fence in V8.
++let Predicates = [HasNoV9] in
++ def : Pat<(atomic_fence imm, imm), (STBAR)>;
++
++// atomic_load_32 addr -> load addr
++def : Pat<(i32 (atomic_load ADDRrr:$src)), (LDrr ADDRrr:$src)>;
++def : Pat<(i32 (atomic_load ADDRri:$src)), (LDri ADDRri:$src)>;
++
++// atomic_store_32 val, addr -> store val, addr
++def : Pat<(atomic_store ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>;
++def : Pat<(atomic_store ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>;
++
++
+ include "SparcInstr64Bit.td"
+Index: lib/Target/Sparc/SparcISelLowering.cpp
+===================================================================
+--- lib/Target/Sparc/SparcISelLowering.cpp
++++ lib/Target/Sparc/SparcISelLowering.cpp
+@@ -1472,10 +1472,30 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
+ }
+
+- // FIXME: There are instructions available for ATOMIC_FENCE
+- // on SparcV8 and later.
+- setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
++ // ATOMICs.
++ // FIXME: We insert fences for each atomics and generate sub-optimal code
++ // for PSO/TSO. Also, implement other atomicrmw operations.
+
++ setInsertFencesForAtomic(true);
++
++ setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal);
++ setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32,
++ (Subtarget->isV9() ? Legal: Expand));
++
++
++ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal);
++
++ // Custom Lower Atomic LOAD/STORE
++ setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
++ setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
++
++ if (Subtarget->is64Bit()) {
++ setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
++ setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand);
++ setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
++ setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
++ }
++
+ if (!Subtarget->isV9()) {
+ // SparcV8 does not have FNEGD and FABSD.
+ setOperationAction(ISD::FNEG, MVT::f64, Custom);
+@@ -2723,6 +2743,16 @@ static SDValue LowerUMULO_SMULO(SDValue Op, Select
+ return DAG.getMergeValues(Ops, 2, dl);
+ }
+
++static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
++ // Monotonic load/stores are legal.
++ if (cast<AtomicSDNode>(Op)->getOrdering() <= Monotonic)
++ return Op;
++
++ // Otherwise, expand with a fence.
++ return SDValue();
++}
++
++
+ SDValue SparcTargetLowering::
+ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
+
+@@ -2778,6 +2808,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
+ case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
+ case ISD::UMULO:
+ case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this);
++ case ISD::ATOMIC_LOAD:
++ case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG);
+ }
+ }
+
+Index: lib/Target/Sparc/SparcInstr64Bit.td
+===================================================================
+--- lib/Target/Sparc/SparcInstr64Bit.td
++++ lib/Target/Sparc/SparcInstr64Bit.td
+@@ -415,6 +415,32 @@ def SETHIXi : F2_1<0b100,
+ "sethi $imm22, $rd",
+ [(set i64:$rd, SETHIimm:$imm22)]>;
+ }
++
++// ATOMICS.
++let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
++ def CASXrr: F3_1<3, 0b111110,
++ (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
++ I64Regs:$swap),
++ "casx [$rs1], $rs2, $rd",
++ [(set i64:$rd,
++ (atomic_cmp_swap i64:$rs1, i64:$rs2, i64:$swap))]>;
++
++} // Predicates = [Is64Bit], Constraints = ...
++
++let Predicates = [Is64Bit] in {
++
++def : Pat<(atomic_fence imm, imm), (MEMBARi 0xf)>;
++
++// atomic_load_64 addr -> load addr
++def : Pat<(i64 (atomic_load ADDRrr:$src)), (LDXrr ADDRrr:$src)>;
++def : Pat<(i64 (atomic_load ADDRri:$src)), (LDXri ADDRri:$src)>;
++
++// atomic_store_64 val, addr -> store val, addr
++def : Pat<(atomic_store ADDRrr:$dst, i64:$val), (STXrr ADDRrr:$dst, $val)>;
++def : Pat<(atomic_store ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>;
++
++} // Predicates = [Is64Bit]
++
+ // Global addresses, constant pool entries
+ let Predicates = [Is64Bit] in {
+
+Index: test/CodeGen/SPARC/atomics.ll
+===================================================================
+--- test/CodeGen/SPARC/atomics.ll
++++ test/CodeGen/SPARC/atomics.ll
+@@ -0,0 +1,63 @@
++; RUN: llc < %s -march=sparcv9 | FileCheck %s
++
++; CHECK-LABEL: test_atomic_i32
++; CHECK: ld [%o0]
++; CHECK: membar
++; CHECK: ld [%o1]
++; CHECK: membar
++; CHECK: membar
++; CHECK: st {{.+}}, [%o2]
++define i32 @test_atomic_i32(i32* %ptr1, i32* %ptr2, i32* %ptr3) {
++entry:
++ %0 = load atomic i32* %ptr1 acquire, align 8
++ %1 = load atomic i32* %ptr2 acquire, align 8
++ %2 = add i32 %0, %1
++ store atomic i32 %2, i32* %ptr3 release, align 8
++ ret i32 %2
++}
++
++; CHECK-LABEL: test_atomic_i64
++; CHECK: ldx [%o0]
++; CHECK: membar
++; CHECK: ldx [%o1]
++; CHECK: membar
++; CHECK: membar
++; CHECK: stx {{.+}}, [%o2]
++define i64 @test_atomic_i64(i64* %ptr1, i64* %ptr2, i64* %ptr3) {
++entry:
++ %0 = load atomic i64* %ptr1 acquire, align 8
++ %1 = load atomic i64* %ptr2 acquire, align 8
++ %2 = add i64 %0, %1
++ store atomic i64 %2, i64* %ptr3 release, align 8
++ ret i64 %2
++}
++
++; CHECK-LABEL: test_cmpxchg_i32
++; CHECK: or %g0, 123, [[R:%[gilo][0-7]]]
++; CHECK: cas [%o1], %o0, [[R]]
++
++define i32 @test_cmpxchg_i32(i32 %a, i32* %ptr) {
++entry:
++ %b = cmpxchg i32* %ptr, i32 %a, i32 123 monotonic
++ ret i32 %b
++}
++
++; CHECK-LABEL: test_cmpxchg_i64
++; CHECK: or %g0, 123, [[R:%[gilo][0-7]]]
++; CHECK: casx [%o1], %o0, [[R]]
++
++define i64 @test_cmpxchg_i64(i64 %a, i64* %ptr) {
++entry:
++ %b = cmpxchg i64* %ptr, i64 %a, i64 123 monotonic
++ ret i64 %b
++}
++
++; CHECK-LABEL: test_swap_i32
++; CHECK: or %g0, 42, [[R:%[gilo][0-7]]]
++; CHECK: swap [%o1], [[R]]
++
++define i32 @test_swap_i32(i32 %a, i32* %ptr) {
++entry:
++ %b = atomicrmw xchg i32* %ptr, i32 42 monotonic
++ ret i32 %b
++}
OpenPOWER on IntegriCloud