diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 7573ff4..a651f49 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -167,6 +167,8 @@ struct GTY ((chain_next ("%h.next"))) loop {
 
   /* Head of the cyclic list of the exits of the loop.  */
   struct loop_exit *exits;
+
+  bool has_transaction;
 };
 
 /* Flags for state of loop structure.  */
diff --git a/gcc/common.opt b/gcc/common.opt
index 273482f..ee7ea59 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1197,6 +1197,10 @@ fgnu-tm
 Common Report Var(flag_tm)
 Enable support for GNU transactional memory
 
+funroll2
+Common Report Var(flag_unroll2)
+Unroll loops that have transactions
+
 floop-flatten
 Common Report Var(flag_loop_flatten) Optimization
 Enable Loop Flattening transformation
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index 9184a14..7654d69 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -390,3 +390,72 @@ struct rtl_opt_pass pass_rtl_doloop =
   TODO_verify_rtl_sharing               /* todo_flags_finish */
  }
 };
+
+bool try_unroll_loop_completely2 (struct loop *loop);
+void mark_transactional_loops (void);
+unsigned int f (void);
+
+unsigned int
+f (void)
+{
+  loop_iterator li;
+  struct loop *loop;
+
+  mark_transactional_loops();
+
+  FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
+    {
+      if (loop->has_transaction)
+        {
+          try_unroll_loop_completely2(loop);
+      
+          if (dump_file) fprintf (dump_file, "HOLA %p\n", (void*)loop);
+        }
+    }
+
+  return 0;
+}
+
+struct gimple_opt_pass pass_unroll2 =
+{
+ {
+  GIMPLE_PASS,
+  "unroll2",                            /* name */
+  NULL,                                 /* gate */
+  f,                                    /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_NONE,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_update_ssa,                      /* todo_flags_finish */
+ }
+};
+
+static bool
+gate_all_unroll2 (void)
+{
+  return flag_unroll2;
+}
+
+struct gimple_opt_pass pass_all_unroll2 =
+{
+ {
+  GIMPLE_PASS,
+  "all_unroll2",                        /* name */
+  gate_all_unroll2,                     /* gate */
+  NULL,                                 /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_NONE,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_update_ssa,                      /* todo_flags_finish */
+ }
+};
diff --git a/gcc/passes.c b/gcc/passes.c
index 6e58d8b..44aa646 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1210,6 +1210,16 @@ init_optimization_passes (void)
       NEXT_PASS (pass_rebuild_cgraph_edges);
       NEXT_PASS (pass_inline_parameters);
       NEXT_PASS (pass_early_inline);
+
+      NEXT_PASS (pass_all_unroll2);
+	{
+	  struct opt_pass **p = &pass_all_unroll2.pass.sub;
+          NEXT_PASS (pass_tree_loop_init);
+          NEXT_PASS (pass_lim);
+          NEXT_PASS (pass_unroll2);
+          NEXT_PASS (pass_tree_loop_done);
+        }
+      
       NEXT_PASS (pass_all_early_optimizations);
 	{
 	  struct opt_pass **p = &pass_all_early_optimizations.pass.sub;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 6f1fd6a..18521a6 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -350,6 +350,8 @@ struct register_pass_info
 
 extern void tree_lowering_passes (tree decl);
 
+extern struct gimple_opt_pass pass_unroll2;
+extern struct gimple_opt_pass pass_all_unroll2;
 extern struct gimple_opt_pass pass_mudflap_1;
 extern struct gimple_opt_pass pass_mudflap_2;
 extern struct gimple_opt_pass pass_lower_cf;
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index 187f53c..42fe4d5 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -424,6 +424,54 @@ try_unroll_loop_completely (struct loop *loop,
   return true;
 }
 
+void
+mark_transactional_loops (void) {
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      if (bb->flags & BB_IN_TRANSACTION)
+        {
+          if (bb->loop_father)
+           {
+             bb->loop_father->has_transaction = true;
+
+             if (dump_file)
+               {
+                 fprintf (dump_file, "HOLA in transaction: loop: %p\n", bb->loop_father);
+               }
+           }
+        }
+    }
+}
+
+void
+try_unroll_loop_completely2 (struct loop *loop)
+{
+  unsigned HOST_WIDE_INT n_unroll;
+
+  n_unroll = 1;
+
+  if (n_unroll)
+    {
+      sbitmap wont_exit;
+
+      initialize_original_copy_tables ();
+      wont_exit = sbitmap_alloc (n_unroll + 1);
+      sbitmap_ones (wont_exit);
+      RESET_BIT (wont_exit, 0);
+
+      gimple_duplicate_loop_to_header_edge (loop, loop_latch_edge (loop),
+				            n_unroll, wont_exit,
+					    NULL, NULL,
+					    DLTHE_FLAG_UPDATE_FREQ);
+      free (wont_exit);
+      free_original_copy_tables ();
+    }
+
+  update_ssa (TODO_update_ssa);
+}
+
 /* Adds a canonical induction variable to LOOP if suitable.
    CREATE_IV is true if we may create a new iv.  UL determines
    which loops we are allowed to completely unroll.  If TRY_EVAL is true, we try
