aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorWalter Lee <walt@tilera.com>2013-03-21 02:08:26 +0000
committerWalter Lee <walt@gcc.gnu.org>2013-03-21 02:08:26 +0000
commit327a1118271129829e9ac0abd894eb29254b93eb (patch)
treea117d6b2813f6b1519daa1b6d00e0cb782998c4f /gcc
parentf7e1f1f149ba01858f0108c8c91bb14f0ef02cee (diff)
downloadgcc-327a1118271129829e9ac0abd894eb29254b93eb.zip
gcc-327a1118271129829e9ac0abd894eb29254b93eb.tar.gz
gcc-327a1118271129829e9ac0abd894eb29254b93eb.tar.bz2
Add an atomic test and set pattern on tilegx.
* config/tilegx/sync.md (atomic_test_and_set): New pattern. From-SVN: r196848
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/config/tilegx/sync.md46
2 files changed, 50 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2cd7169..5ecdc8f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2013-03-20 Walter Lee <walt@tilera.com>
+
+ * config/tilegx/sync.md (atomic_test_and_set): New pattern.
+
2013-03-20 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*movoi_internal_avx): Emit insn template
diff --git a/gcc/config/tilegx/sync.md b/gcc/config/tilegx/sync.md
index a853996..a4bea6b 100644
--- a/gcc/config/tilegx/sync.md
+++ b/gcc/config/tilegx/sync.md
@@ -162,3 +162,49 @@
tilegx_post_atomic_barrier (model);
DONE;
})
+
+
+(define_expand "atomic_test_and_set"
+ [(match_operand:QI 0 "register_operand" "") ;; bool output
+ (match_operand:QI 1 "nonautoincmem_operand" "+U") ;; memory
+ (match_operand:SI 2 "const_int_operand" "")] ;; model
+ ""
+{
+ rtx addr, aligned_addr, aligned_mem, offset, word, shmt;
+ rtx tmp0, tmp1;
+ rtx result = operands[0];
+ rtx mem = operands[1];
+ enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+
+ addr = force_reg (Pmode, XEXP (mem, 0));
+
+ aligned_addr = gen_reg_rtx (Pmode);
+ emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-8)));
+
+ aligned_mem = change_address (mem, DImode, aligned_addr);
+ set_mem_alias_set (aligned_mem, 0);
+
+ offset = gen_reg_rtx (DImode);
+ emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, addr),
+ GEN_INT (7)));
+
+ tmp0 = gen_reg_rtx (DImode);
+ emit_move_insn (tmp0, GEN_INT (1));
+
+ shmt = gen_reg_rtx (DImode);
+ emit_move_insn (shmt, gen_rtx_ASHIFT (DImode, offset, GEN_INT (3)));
+
+ word = gen_reg_rtx (DImode);
+ emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp0,
+ gen_lowpart (SImode, shmt)));
+
+ tmp1 = gen_reg_rtx (DImode);
+ tilegx_pre_atomic_barrier (model);
+ emit_insn (gen_atomic_fetch_or_baredi (tmp1, aligned_mem, word));
+ tilegx_post_atomic_barrier (model);
+
+ emit_move_insn (gen_lowpart (DImode, result),
+ gen_rtx_LSHIFTRT (DImode, tmp1,
+ gen_lowpart (SImode, shmt)));
+ DONE;
+})