Must-alias analysis
Hi all, how is the must-alias information represented in mainline? Is there something like DEF-USE chains for virtual operands? How can I access this kind of information and where should I look for some examples how to use it? Thank you very much! Regards, Martin
build_fold_addr_expr breaks verify_stmt
Dear GCC-Developers, I am currently experiencing two problems (which seem related). (1) I wrote a pass that works after the gimplification is completed and amongst other things does the following: It passes the address of a variable to a function. To pass the address I use the build_fold_addr_expr which takes the address and seems to work quite well. The problem now occurs when the variable is used after the function call. Since the variable is used in a binary expression, the compiler complains about the following: error: invalid operand to binary operator m file.c: internal compiler error: verify_stmts failed I assume that the error occurs because one of the GIMPLE assumptions (that every global variable is assigned to a local one) is violated. This happens because the call to build_fold_addr_expr takes the address of the variable and the variable escapes the local scope. Are there any means to work around this issue? (2) I would like to capture the value of a variable in a temporary and restore it under certain conditions. Adding the temporaries and inserting the assignments both ways (to save and restore the values) works fine. Unfortunately, none of the temporary variables survives the SSA optimisations. Is there something (maybe similar to the VDEF for memory locations) that prevents optimisation of variables? (I tried to set VDEFs on the variables directly but this breaks the SSA properties). Thank you very much for your suggestions! Regards, Martin
prevent optimisation of variables on SSA
Hi all, I currently introduce a temporary variable on SSA form but it does not survive the SSA optimisation passes. (Not even the simple ones triggered with -O1). Since the temporary variable is considered to be a gimple register it is not possible to set a VUSE or VDEF for it. (I tried and it breaks the SSA properties). Are there any mechanisms to work around this restriction and set the VDEF/VUSE anyway or is there a way to tell the SSA optimisers not to touch this variable (or SSA_NAME)? Thank you very much for sharing your thoughts! Regards, Martin
Re: prevent optimisation of variables on SSA
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: 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 (); else goto (); # SUCC: 4 (false) 3 (true) # BLOCK 3 # PRED: 2 (true) :; __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 (); else goto ; # SUCC: 4 (true) 5 (false) # BLOCK 4 # PRED: 2 (false) 3 (true) # txn_save_b.21_26 = PHI # txn_save_a.20_21 = PHI # txn_save_m.19_16 = PHI :; __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 __builtin_stm_start (txn_handle.12_4, jmp_buf.13_5, &0); 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
Re: prevent optimisation of variables on SSA
Hi Richard, thank you very much for your suggestions, it seems to be working well. Now, the temporary variables survive the SSA optimisations. 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. Well, if you are inserting this abnormal control flow after going into SSA then you need to make sure all SSA variables affected are marked as SSA_NAME_OCCURS_IN_ABNORMAL_PHI and make sure that SSA names from a single base variable not have overlapping life-ranges. Currently, the control flow and some function calls for setting up a transaction are introduced on GIMPLE. Thus, when the program is rewritten into SSA the function calls to stm_* force the merging of overlapping live ranges of single base variables: I tried it with Diegos nice example and introduced the call to stm_new in the following: int foo(int a, int b, int c) { void * txn_handle; a = b; if (c < a) { b = b + a; c = c + a; } txn_handle = stm_new (); return b + c; } Usually, b has two overlapping live ranges where the stm_new was introduced and going into SSA shows the following: foo (a, b, c) { void * txn_handle; int D.1184; int D.1183; # BLOCK 2 # PRED: ENTRY (fallthru) a_4 = b_3(D); if (c_5(D) < a_4) goto ; else goto ; # SUCC: 3 (true) 4 (false) # BLOCK 3 # PRED: 2 (true) b_6 = b_3(D) + a_4; c_7 = c_5(D) + a_4; # SUCC: 4 (fallthru) # BLOCK 4 # PRED: 2 (false) 3 (fallthru) # b_2 = PHI # c_1 = PHI D.1183_8 = stm_new (); txn_handle_9 = (void *) D.1183_8; D.1184_10 = b_2 + c_1; return D.1184_10; # SUCC: EXIT } The PHI-node to merge the two live ranges is introduced before the call to stm_new(). I believe this solves my problem because the checkpointing would be done afterwards and there only b_2 remains to checkpoint. Do you agree? Which means what you are doing is not really going to be easy in SSA form and you should rather try to do it before going into SSA. And I would suggest you use the exception handling machinery of GCC to do it and not insert setjmp/longjmp calls yourself or try to track the complete program state. You are right to propose to use the exception handling machinery to do the handling of setjmp/longjmp. But I see two issues with this approach: first, I am not experienced in programming GCC and don't know how to use this machinery. Second, the longjmp is executed by the library and, thus, not part of the implementation in GCC. I am not sure if this affects the EH mechanisms but I can imagine it could. Regards, Martin