Hi,
I will try to explain in more detail:
I am trying to implement support for transactions in GCC. In particular
for a Software Transactional Memory library called tinySTM. Since
transactions have the nice property that they can abort and execute
again, we need some kind of checkpointing at the beginning of a
transaction. The checkpointing is done two fold: on one hand setjmp is
used to capture the register state on the other hand temporary variables
are introduced by GCC to capture the value of live-in variables to the
transaction and play the values back to the original variables in case
of an abort. In terms of IR code a begin of a transaction is translated
into this:
<snip>
txn_handle.12_4 = __builtin_stm_new ();
jmp_buf.13_5 = __builtin_stm_get_env (txn_handle.12_4);
ssj_value.14_6 = _setjmp (jmp_buf.13_5);
if (ssj_value.14_6 == 0)
goto <bb 3> (<L1>);
else
goto <bb 4> (<L2>);
# SUCC: 4 (false) 3 (true)
# BLOCK 3
# PRED: 2 (true)
<L1>:;
__builtin_printf ("SAVE_BB\n");
txn_save_m.19_15 = m_1;
txn_save_a.20_20 = a_2;
txn_save_b.21_25 = b_3;
fake_var.18_13 = __builtin_stm_dummy ("RECOVER_BB\n");
if (fake_var.18_13)
goto <bb 4> (<L2>);
else
goto <bb 5>;
# SUCC: 4 (true) 5 (false)
# BLOCK 4
# PRED: 2 (false) 3 (true)
# txn_save_b.21_26 = PHI <txn_save_b.21_24(2), txn_save_b.21_25(3)>
# txn_save_a.20_21 = PHI <txn_save_a.20_19(2), txn_save_a.20_20(3)>
# txn_save_m.19_16 = PHI <txn_save_m.19_14(2), txn_save_m.19_15(3)>
<L2>:;
__builtin_printf ("RECOVER_BB\n");
m_17 = txn_save_m.19_16;
a_22 = txn_save_a.20_21;
b_27 = txn_save_b.21_26;
# SUCC: 5 (fallthru)
# BLOCK 5
# PRED: 4 (fallthru) 3 (false)
# m_18 = PHI <m_17(4), m_1(3)>
__builtin_stm_start (txn_handle.12_4, jmp_buf.13_5, &0);
<snip here comes the begin of a transaction>
the first part is acquiring a handle for the transactions from the STM,
then a jump buffer is created by the STM and the setjmp is executed.
Since the longjmp executed by the STM (in case of an abort) returns to
this location, we simply evaluate the return value of the setjmp call
and know what to execute. In case of returning from the call to setjmp
we want to capture the values of the live-in variables, which are a,b
and m in this example. In case we returned from a longjmp we want to
restore the values from the temporary variables (txn_save_a/b/m) to the
original variables (a/b/m).
My problem with the SSA optimisations is that (after the SSA
final_cleanup pass) in this example the initialisation of the variables
a and b is moved into the SAVE_BB and RESTORE_BB basic blocks - both
look like this:
a = 5;
b = 10;
and the txn_save_* variables are optimised "away". Is there any way to
prevent this kind of optimisations on SSA form for a particular group of
variables? Here I would like to see the txn_save_* variables behave as a
container for the values of the real variables and be sure that these
variables are not touched by any optimisations.
Thank you very much for your ideas!
Regards,
Martin