text: /* **********************************************************
   * Copyright (c) 2002-2008 VMware, Inc.  All rights reserved.
   * **********************************************************/
  
  /*
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * * Redistributions of source code must retain the above copyright notice,
   *   this list of conditions and the following disclaimer.
   *
   * * Redistributions in binary form must reproduce the above copyright notice,
   *   this list of conditions and the following disclaimer in the documentation
   *   and/or other materials provided with the distribution.
   *
   * * Neither the name of VMware, Inc. nor the names of its contributors may be
   *   used to endorse or promote products derived from this software without
   *   specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
   * DAMAGE.
   */
  
  /* Copyright (c) 2003-2007 Determina Corp. */
  /* Copyright (c) 2002-2003 Massachusetts Institute of Technology */
  
  #ifdef LOAD_TO_CONST
  #ifndef __LOADTOCONST_H_
  #define __LOADTOCONST_H_
  
  #define NUM_VALUES_FOR_SPECULATION 40
  #define SAMPLE_PERCENT (9/10)
  
  
  #define MAX_TRACES_WAITING_FOR_LTC 20
  #include "instr.h"
  
  struct ltc_mem_ref_data{
      opnd_t opnd;
      int vals[NUM_VALUES_FOR_SPECULATION];
      int addresses[NUM_VALUES_FOR_SPECULATION];
  };
  struct ltc_data{
      struct ltc_mem_ref_data *mem_refs;
      int num_mem_addresses;
      int num_mem_samples;
      bool ltc_already_optimized;
  };
  
  #ifdef LTC_STATS
  extern int safe_taken,opt_taken,addrs_analyzed,addrs_made_const,traces_analyzed,addrs_seen;
  #endif
  
  void analyze_memrefs(dcontext_t *dcontext, app_pc tag, instrlist_t *trace);
  
  
  int check_mem_refs(app_pc tag, int errno, reg_t eflags,
                     reg_t reg_edi, reg_t reg_esi, reg_t reg_ebp, reg_t reg_esp,
                     reg_t reg_ebx, reg_t reg_edx, reg_t reg_ecx, reg_t reg_eax);
  int get_mem_address(dcontext_t *dcontext,opnd_t mem_access,int regs[8]);
  int get_mem_val(dcontext_t *dcontext,opnd_t mem_access,int address);
  void ltc_trace(dcontext_t *dcontext, fragment_t *, instrlist_t *trace);
  void remove_mem_ref_check(dcontext_t *dcontext,instrlist_t *trace);
  
  #ifdef SIDELINE
  void LTC_examine_traces(void);
  void LTC_fragment_delete(fragment_t *frag);
  #endif
  
  void LTC_online_optimize_and_replace(dcontext_t *dcontext, app_pc tag,fragment_t *curfrag);
  void do_single_LTC(dcontext_t *dcontext,instrlist_t *trace, opnd_t mem_access, opnd_t value);
  bool should_replace_load(dcontext_t *dcontext,struct ltc_mem_ref_data data);
  opnd_t value_to_replace(struct ltc_mem_ref_data);
  bool instr_replace_reg_with_const_in_src(dcontext_t *dcontext,instr_t *in,int reg,int val);
  bool instr_replace_reg_with_const_in_dst(dcontext_t *dcontext,instr_t *in,int reg,int val);
  instrlist_t *save_eflags_list(dcontext_t *dcontext,fragment_t *frag);
  instrlist_t *restore_eflags_list(dcontext_t *dcontext,fragment_t *frag);
  void change_cbr_due_to_reversed_cmp(instr_t *in);
  bool pc_reads_flags_before_writes(dcontext_t *dcontext,app_pc target);
  
  instr_t *fix_cmp_containing_constant(dcontext_t *dcontext,instrlist_t *trace,instr_t *in,
                                     opnd_t orig_op1,opnd_t orig_op2);
  
  void replace_self_loop_with_opnd(dcontext_t *dcontext, app_pc tag,
                                   instrlist_t *ilist, opnd_t desiredtarget);
  #define TRANSPOSE true
  #define NO_TRANSPOSE false
  bool safe_to_transpose_cmp(dcontext_t *dcontext,instr_t *testinstr);
  bool safe_to_delete_cmp(dcontext_t *dcontext,instr_t *testinstr);
  bool safe_to_modify_cmp(dcontext_t *dcontext,instr_t *testinstr, bool transpose);
  bool becomes_ubr_from_cmp(instr_t *in,int op1, int op2);
  bool opnd_replace_reg_with_val(opnd_t *opnd, int old_reg, int val);
  void constant_propagate(dcontext_t *dcontext, instrlist_t *trace,app_pc tag);
  void pop_instr_off_list(dcontext_t *dcontext,instrlist_t *trace,int opcode);
  void instr_optimize_constant(dcontext_t *dcontext, instr_t *in);
  bool instr_flag_write_necessary(dcontext_t *dcontext, instr_t *in);
  
  void instr_replace_inplace(dcontext_t *dcontext, instr_t *in, instr_t *);
  void instr_arithmatic_simplify(dcontext_t *dcontext, instr_t *in);
  void instrlist_remove_nops(dcontext_t *dcontext,instrlist_t *trace);
  bool instrlist_depends_on_reg(dcontext_t *dcontext, instrlist_t *trace, int reg);
  void instr_add_to_exitexec_list(dcontext_t *,instr_t *in,instr_t *exitinstr);
  void instrlist_setup_pseudo_exitstubs(dcontext_t *dcontext,instrlist_t *trace);
  #endif
  #endif
  
  