aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 8ad7f4b..1820b91 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -6484,6 +6484,48 @@ expand_memory_blockage (void)
expand_asm_memory_blockage ();
}
+/* Generate asm volatile("" : : : "memory") as a memory blockage, at the
+ same time clobbering the register set specified by REGS. */
+
+void
+expand_asm_reg_clobber_mem_blockage (HARD_REG_SET regs)
+{
+ rtx asm_op, clob_mem;
+
+ unsigned int num_of_regs = 0;
+ for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (regs, i))
+ num_of_regs++;
+
+ asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
+ rtvec_alloc (0), rtvec_alloc (0),
+ rtvec_alloc (0), UNKNOWN_LOCATION);
+ MEM_VOLATILE_P (asm_op) = 1;
+
+ rtvec v = rtvec_alloc (num_of_regs + 2);
+
+ clob_mem = gen_rtx_SCRATCH (VOIDmode);
+ clob_mem = gen_rtx_MEM (BLKmode, clob_mem);
+ clob_mem = gen_rtx_CLOBBER (VOIDmode, clob_mem);
+
+ RTVEC_ELT (v, 0) = asm_op;
+ RTVEC_ELT (v, 1) = clob_mem;
+
+ if (num_of_regs > 0)
+ {
+ unsigned int j = 2;
+ for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (regs, i))
+ {
+ RTVEC_ELT (v, j) = gen_rtx_CLOBBER (VOIDmode, regno_reg_rtx[i]);
+ j++;
+ }
+ gcc_assert (j == (num_of_regs + 2));
+ }
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, v));
+}
+
/* This routine will either emit the mem_thread_fence pattern or issue a
sync_synchronize to generate a fence for memory model MEMMODEL. */