1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                          ir_opt.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2004-2011 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ir_opt.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set to 1 for lots of debugging output. */
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEBUG_IROPT 0
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* What iropt does, 29 Dec 04.
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It takes an IRSB and produces a new one with the same meaning,
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined thus:
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   After execution of the new BB, all guest state and guest memory is
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same as after execution of the original.  This is true
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   regardless of how the block was exited (at the end vs side exit).
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In addition, parts of the guest state will be identical to that
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   created by execution of the original at the following observation
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   points:
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * In a dirty helper call, any parts of the guest state that the
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     helper states that it reads or modifies will be up to date.
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Also, guest memory will be up to date.  Parts of the guest state
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     not marked as being read or modified by the helper cannot be
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assumed to be up-to-date at the point where the helper is called.
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Immediately prior to any load or store, those parts of the guest
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     state marked as requiring precise exceptions will be up to date.
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Also, guest memory will be up to date.  Parts of the guest state
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     not marked as requiring precise exceptions cannot be assumed to
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     be up-to-date at the point of the load/store.
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The relative order of loads and stores (including loads/stores of
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest memory done by dirty helpers annotated as such) is not
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   changed.  However, the relative order of loads with no intervening
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stores/modifies may be changed.
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Transformation order
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ~~~~~~~~~~~~~~~~~~~~
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There are three levels of optimisation, controlled by
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_control.iropt_level.  Define first:
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Cheap transformations" are the following sequence:
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-Get removal
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-Put removal
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Constant propagation/folding
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Specialisation of clean helper functions
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Expensive transformations" are the following sequence:
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * CSE
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Folding of add/sub chains
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-GetI removal
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-PutI removal
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Then the transformations are as follows, as defined by
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_control.iropt_level:
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 0:
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 1: the following sequence:
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Cheap transformations.
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 2: the following sequence
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Cheap transformations.
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If block contains any floating or vector types, CSE.
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If block contains GetI or PutI, Expensive transformations.
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Try unrolling loops.  Three possible outcomes:
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - No effect: do nothing more.
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - Unrolled a loop, and block does not contain GetI or PutI:
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Do: * CSE
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              * Dead code removal
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - Unrolled a loop, and block contains GetI or PutI:
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Do: * Expensive transformations
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              * Cheap transformations
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Implementation notes, 29 Dec 04.
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO (important): I think rPutI removal ignores precise exceptions
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and is therefore in a sense, wrong.  In the sense that PutIs are
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assumed not to write parts of the guest state that we need to have
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   up-to-date at loads/stores.  So far on x86 guest that has not
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mattered since indeed only the x87 FP registers and tags are
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accessed using GetI/PutI, and there is no need so far for them to
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be up to date at mem exception points.  The rPutI pass should be
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fixed.
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: improve pessimistic handling of precise exceptions
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     in the tree builder.
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: check interaction of rGetI and dirty helpers.
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F64i constants are treated differently from other constants.
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   They are not regarded as atoms, and instead lifted off and
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bound to temps.  This allows them to participate in CSE, which
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is important for getting good performance for x86 guest code.
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CSE up F64 literals (already doing F64is)
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CSE: consider carefully the requirement for precise exns
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        prior to making CSE any more aggressive.  */
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Finite mappery, of a sort                               ---*/
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* General map from HWord-sized thing HWord-sized thing.  Could be by
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hashing, but it's not clear whether or not this would really be any
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   faster. */
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool*  inuse;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* key;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* val;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    size;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    used;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW;
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HashHW* newHHW ( void )
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* h = LibVEX_Alloc(sizeof(HashHW));
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->size   = 8;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->used   = 0;
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->inuse  = LibVEX_Alloc(h->size * sizeof(Bool));
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->key    = LibVEX_Alloc(h->size * sizeof(HWord));
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->val    = LibVEX_Alloc(h->size * sizeof(HWord));
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return h;
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up key in the map. */
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool lookupHHW ( HashHW* h, /*OUT*/HWord* val, HWord key )
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("lookupHHW(%llx)\n", key ); */
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < h->used; i++) {
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h->inuse[i] && h->key[i] == key) {
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (val)
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *val = h->val[i];
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add key->val to the map.  Replaces any existing binding for key. */
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addToHHW ( HashHW* h, HWord key, HWord val )
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i, j;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("addToHHW(%llx, %llx)\n", key, val); */
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Find and replace existing binding, if any. */
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < h->used; i++) {
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h->inuse[i] && h->key[i] == key) {
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h->val[i] = val;
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ensure a space is available. */
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (h->used == h->size) {
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Copy into arrays twice the size. */
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool*  inuse2 = LibVEX_Alloc(2 * h->size * sizeof(Bool));
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* key2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* val2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = j = 0; i < h->size; i++) {
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!h->inuse[i]) continue;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         inuse2[j] = True;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         key2[j] = h->key[i];
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val2[j] = h->val[i];
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j++;
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->used = j;
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->size *= 2;
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->inuse = inuse2;
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->key = key2;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->val = val2;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, add it. */
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(h->used < h->size);
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->inuse[h->used] = True;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->key[h->used] = key;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->val[h->used] = val;
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->used++;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Flattening out a BB into atomic SSA form                ---*/
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Non-critical helper, heuristic for reducing the number of tmp-tmp
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   copies made by flattening.  If in doubt return False. */
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isFlat ( IRExpr* e )
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get)
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop)
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( isIRAtom(e->Iex.Binop.arg1)
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     && isIRAtom(e->Iex.Binop.arg2) );
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load)
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return isIRAtom(e->Iex.Load.addr);
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Flatten out 'ex' so it is atomic, returning a new expression with
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same value, after having appended extra IRTemp assignments to
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the end of 'bb'. */
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* flatten_Expr ( IRSB* bb, IRExpr* ex )
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** newargs;
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(bb->tyenv, ex);
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1;
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ex->tag) {
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_GetI(ex->Iex.GetI.descr,
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.GetI.ix),
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ex->Iex.GetI.bias)));
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb,
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRStmt_WrTmp(t1, ex));
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Qop(ex->Iex.Qop.op,
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Qop.arg1),
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Qop.arg2),
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Qop.arg3),
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Qop.arg4))));
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Triop(ex->Iex.Triop.op,
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Triop.arg1),
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Triop.arg2),
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Triop.arg3))));
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Binop(ex->Iex.Binop.op,
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Binop.arg1),
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Binop.arg2))));
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Unop(ex->Iex.Unop.op,
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.Unop.arg))));
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Load(ex->Iex.Load.end,
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ex->Iex.Load.ty,
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.Load.addr))));
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         newargs = shallowCopyIRExprVec(ex->Iex.CCall.args);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; newargs[i]; i++)
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            newargs[i] = flatten_Expr(bb, newargs[i]);
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_CCall(ex->Iex.CCall.cee,
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ex->Iex.CCall.retty,
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         newargs)));
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X(flatten_Expr(bb, ex->Iex.Mux0X.cond),
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Mux0X.expr0),
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Mux0X.exprX))));
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Lift F64i constants out onto temps so they can be CSEd
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            later. */
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ex->Iex.Const.con->tag == Ico_F64i) {
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t1 = newIRTemp(bb->tyenv, ty);
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_WrTmp(t1,
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Const(ex->Iex.Const.con)));
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return IRExpr_RdTmp(t1);
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Leave all other constants alone. */
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ex;
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ex;
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ex);
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("flatten_Expr");
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Append a completely flattened form of 'st' to the end of 'bb'. */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flatten_Stmt ( IRSB* bb, IRStmt* st )
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr  *e1, *e2, *e3, *e4, *e5;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty *d,  *d2;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS   *cas, *cas2;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isIRAtom(st->Ist.Put.data)) {
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* optimisation to reduce the amount of heap wasted
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               by the flattener */
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, st);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* general case, always correct */
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e1 = flatten_Expr(bb, st->Ist.Put.data);
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.PutI.ix);
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.PutI.data);
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_PutI(st->Ist.PutI.descr,
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       e1,
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       st->Ist.PutI.bias,
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       e2));
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isFlat(st->Ist.WrTmp.data)) {
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* optimisation, to reduce the number of tmp-tmp
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               copies generated */
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, st);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* general case, always correct */
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e1 = flatten_Expr(bb, st->Ist.WrTmp.data);
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_WrTmp(st->Ist.WrTmp.tmp, e1));
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.Store.addr);
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.Store.data);
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Store(st->Ist.Store.end, e1,e2));
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas  = st->Ist.CAS.details;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1   = flatten_Expr(bb, cas->addr);
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2   = cas->expdHi ? flatten_Expr(bb, cas->expdHi) : NULL;
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e3   = flatten_Expr(bb, cas->expdLo);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e4   = cas->dataHi ? flatten_Expr(bb, cas->dataHi) : NULL;
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e5   = flatten_Expr(bb, cas->dataLo);
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS( cas->oldHi, cas->oldLo, cas->end,
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         e1, e2, e3, e4, e5 );
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_CAS(cas2));
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.LLSC.addr);
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = st->Ist.LLSC.storedata
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ? flatten_Expr(bb, st->Ist.LLSC.storedata)
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 : NULL;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_LLSC(st->Ist.LLSC.end,
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       st->Ist.LLSC.result, e1, e2));
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->args = shallowCopyIRExprVec(d2->args);
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None) {
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = flatten_Expr(bb, d2->mAddr);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(d2->mAddr == NULL);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = flatten_Expr(bb, d2->guard);
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++)
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->args[i] = flatten_Expr(bb, d2->args[i]);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Dirty(d2));
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.AbiHint.base);
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.AbiHint.nia);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len, e2));
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.Exit.guard);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Exit(e1, st->Ist.Exit.jk,
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           st->Ist.Exit.dst));
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("flatten_Stmt");
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* flatten_BB ( IRSB* in )
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   i;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB* out;
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out = emptyIRSB();
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < in->stmts_used; i++)
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (in->stmts[i])
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         flatten_Stmt( out, in->stmts[i] );
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->next     = flatten_Expr( out, in->next );
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->jumpkind = in->jumpkind;
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return out;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- In-place removal of redundant GETs                      ---*/
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan forwards, building up an environment binding (min offset, max
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset) pairs to values, which will either be temps or constants.
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 't = Get(minoff,maxoff)', look up (minoff,maxoff) in the
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env and if it matches, replace the Get with the stored value.  If
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there is no match, add a (minoff,maxoff) :-> t binding.
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Put (minoff,maxoff) = t or c', first remove in the env
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   any binding which fully or partially overlaps with (minoff,maxoff).
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Then add a new (minoff,maxoff) :-> t or c binding.  */
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract the min/max offsets from a guest state array descriptor. */
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void getArrayBounds ( IRRegArray* descr,
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UInt* minoff, UInt* maxoff )
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *minoff = descr->base;
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *maxoff = *minoff + descr->nElems*sizeofIRType(descr->elemTy) - 1;
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((*minoff & ~0xFFFF) == 0);
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((*maxoff & ~0xFFFF) == 0);
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(*minoff <= *maxoff);
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create keys, of the form ((minoffset << 16) | maxoffset). */
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt mk_key_GetPut ( Int offset, IRType ty )
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* offset should fit in 16 bits. */
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff = offset;
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt maxoff = minoff + sizeofIRType(ty) - 1;
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((minoff & ~0xFFFF) == 0);
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((maxoff & ~0xFFFF) == 0);
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (minoff << 16) | maxoff;
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt mk_key_GetIPutI ( IRRegArray* descr )
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff, maxoff;
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr, &minoff, &maxoff );
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((minoff & ~0xFFFF) == 0);
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((maxoff & ~0xFFFF) == 0);
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (minoff << 16) | maxoff;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Supposing h has keys of the form generated by mk_key_GetPut and
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mk_key_GetIPutI, invalidate any key which overlaps (k_lo
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   .. k_hi).
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void invalidateOverlaps ( HashHW* h, UInt k_lo, UInt k_hi )
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  j;
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt e_lo, e_hi;
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(k_lo <= k_hi);
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* invalidate any env entries which in any way overlap (k_lo
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. k_hi) */
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("invalidate %d .. %d\n", k_lo, k_hi ); */
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < h->used; j++) {
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!h->inuse[j])
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e_lo = (((UInt)h->key[j]) >> 16) & 0xFFFF;
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e_hi = ((UInt)h->key[j]) & 0xFFFF;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e_lo <= e_hi);
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e_hi < k_lo || k_hi < e_lo)
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* no overlap possible */
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* overlap; invalidate */
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h->inuse[j] = False;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void redundant_get_removal_BB ( IRSB* bb )
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* env = newHHW();
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j;
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord   val;
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRStmt* st = bb->stmts[i];
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Gets */
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_Get) {
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* st is 't = Get(...)'.  Look up in the environment and see
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if the Get can be replaced. */
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* get = st->Ist.WrTmp.data;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         key = (HWord)mk_key_GetPut( get->Iex.Get.offset,
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     get->Iex.Get.ty );
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (lookupHHW(env, &val, (HWord)key)) {
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* found it */
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note, we could do better here.  If the types are
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               different we don't do the substitution, since doing so
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               could lead to invalidly-typed IR.  An improvement would
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               be to stick in a reinterpret-style cast, although that
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               would make maintaining flatness more difficult. */
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* valE    = (IRExpr*)val;
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool    typesOK = toBool( typeOfIRExpr(bb->tyenv,valE)
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      == st->Ist.WrTmp.data->Iex.Get.ty );
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typesOK && DEBUG_IROPT) {
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rGET: "); ppIRExpr(get);
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("  ->  "); ppIRExpr(valE);
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typesOK)
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, valE);
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Not found, but at least we know that t and the Get(...)
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               are now associated.  So add a binding to reflect that
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fact. */
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addToHHW( env, (HWord)key,
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (HWord)(void*)(IRExpr_RdTmp(st->Ist.WrTmp.tmp)) );
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Puts: invalidate any env entries overlapped by this
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Put */
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put || st->tag == Ist_PutI) {
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt k_lo, k_hi;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag == Ist_Put) {
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetPut( st->Ist.Put.offset,
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(st->tag == Ist_PutI);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetIPutI( st->Ist.PutI.descr );
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k_lo = (key >> 16) & 0xFFFF;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k_hi = key & 0xFFFF;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidateOverlaps(env, k_lo, k_hi);
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty) {
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Deal with dirty helpers which write or modify guest state.
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Invalidate the entire env.  We could do a lot better
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            here. */
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty* d      = st->Ist.Dirty.details;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool     writes = False;
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < d->nFxState; j++) {
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->fxState[j].fx == Ifx_Modify
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || d->fxState[j].fx == Ifx_Write)
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            writes = True;
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (writes) {
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* dump the entire env (not clever, but correct ...) */
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = 0; j < env->used; j++)
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               env->inuse[j] = False;
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) vex_printf("rGET: trash env due to dirty helper\n");
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add this one to the env, if appropriate */
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put) {
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Put.data));
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( env, (HWord)key, (HWord)(st->Ist.Put.data));
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for (i = 0; i < bb->stmts_used; i++) */
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- In-place removal of redundant PUTs                      ---*/
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find any Get uses in st and invalidate any partially or fully
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlapping ranges listed in env.  Due to the flattening phase, the
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only stmt kind we expect to find a Get on is IRStmt_WrTmp. */
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_gets_Stmt (
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HashHW* env,
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRStmt* st,
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool (*preciseMemExnsFn)(Int,Int)
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     j;
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isGet;
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    memRW = False;
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the only interesting case.  Deal with Gets in the RHS
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expression. */
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e = st->Ist.WrTmp.data;
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->tag) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Get:
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = True;
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               key = mk_key_GetPut ( e->Iex.Get.offset, e->Iex.Get.ty );
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_GetI:
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = True;
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               key = mk_key_GetIPutI ( e->Iex.GetI.descr );
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Load:
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = False;
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               memRW = True;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = False;
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isGet) {
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt k_lo, k_hi;
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k_lo = (key >> 16) & 0xFFFF;
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k_hi = key & 0xFFFF;
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalidateOverlaps(env, k_lo, k_hi);
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Be very conservative for dirty helper calls; dump the entire
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         environment.  The helper might read guest state, in which
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case it needs to be flushed first.  Also, the helper might
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         access guest memory, in which case all parts of the guest
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state requiring precise exceptions needs to be flushed.  The
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         crude solution is just to flush everything; we could easily
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         enough do a lot better if needed. */
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Probably also overly-conservative, but also dump everything
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if we hit a memory bus event (fence, lock, unlock).  Ditto
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AbiHints, CASs, LLs and SCs. */
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.base));
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.nia));
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < env->used; j++)
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* all other cases are boring. */
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.addr));
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.data));
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memRW = True;
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.PutI.ix));
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.PutI.data));
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("handle_gets_Stmt");
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (memRW) {
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This statement accesses memory.  So we need to dump all parts
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the environment corresponding to guest state that may not
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be reordered with respect to memory references.  That means
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at least the stack pointer. */
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = 0; j < env->used; j++) {
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!env->inuse[j])
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (vex_control.iropt_precise_memory_exns) {
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Precise exceptions required.  Flush all guest state. */
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Just flush the minimal amount required, as computed by
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               preciseMemExnsFn. */
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HWord k_hi = env->key[j] & 0xFFFF;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (preciseMemExnsFn( k_lo, k_hi ))
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               env->inuse[j] = False;
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (memRW) */
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan backwards, building up a set of (min offset, max
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset) pairs, indicating those parts of the guest state
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for which the next event is a write.
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing a conditional exit, empty the set.
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Put (minoff,maxoff) = t or c', if (minoff,maxoff) is
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   completely within the set, remove the Put.  Otherwise, add
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (minoff,maxoff) to the set.
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Get (minoff,maxoff)', remove any part of the set
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlapping (minoff,maxoff).  The same has to happen for any events
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which implicitly read parts of the guest state: dirty helper calls
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and loads/stores.
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void redundant_put_removal_BB (
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRSB* bb,
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool (*preciseMemExnsFn)(Int,Int)
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j;
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isPut;
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* env = newHHW();
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with conditional exits. */
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Exit) {
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Since control may not get beyond this point, we must empty
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            out the set, since we can no longer claim that the next
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            event for any part of the guest state is definitely a
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            write. */
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < env->used; j++)
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Puts */
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = True;
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetPut( st->Ist.Put.offset,
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Put.data));
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = True;
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetIPutI( st->Ist.PutI.descr );
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.PutI.ix));
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.PutI.data));
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = False;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isPut && st->tag != Ist_PutI) {
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See if any single entry in env overlaps this Put.  This is
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            simplistic in that the transformation is valid if, say, two
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or more entries in the env overlap this Put, but the use of
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lookupHHW will only find a single entry which exactly
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            overlaps this Put.  This is suboptimal but safe. */
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (lookupHHW(env, NULL, (HWord)key)) {
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This Put is redundant because a later one will overwrite
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               it.  So NULL (nop) it out. */
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rPUT: "); ppIRStmt(st);
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i] = IRStmt_NoOp();
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We can't demonstrate that this Put is redundant, so add it
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to the running collection. */
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addToHHW(env, (HWord)key, 0);
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Gets.  These remove bits of the environment since
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         appearance of a Get means that the next event for that slice
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the guest state is no longer a write, but a read.  Also
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deals with implicit reads of guest state needed to maintain
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         precise exceptions. */
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      handle_gets_Stmt( env, st, preciseMemExnsFn );
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constant propagation and folding                        ---*/
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The env in this section is a map from IRTemp to IRExpr*,
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is, an array indexed by IRTemp. */
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Are both expressions simply the same IRTemp ? */
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameIRTemps ( IRExpr* e1, IRExpr* e2 )
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e1->tag == Iex_RdTmp
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e2->tag == Iex_RdTmp
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp );
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameIcoU32s ( IRExpr* e1, IRExpr* e2 )
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e1->tag == Iex_Const
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e2->tag == Iex_Const
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e1->Iex.Const.con->tag == Ico_U32
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e2->Iex.Const.con->tag == Ico_U32
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e1->Iex.Const.con->Ico.U32
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     == e2->Iex.Const.con->Ico.U32 );
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Are both expressions either the same IRTemp or IRConst-U32s ?  If
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in doubt, say No. */
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameIRTempsOrIcoU32s ( IRExpr* e1, IRExpr* e2 )
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e1->tag) {
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return sameIRTemps(e1, e2);
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return sameIcoU32s(e1, e2);
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Is this literally IRExpr_Const(IRConst_U32(0)) ? */
921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool isZeroU32 ( IRExpr* e )
922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toBool( e->tag == Iex_Const
924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->tag == Ico_U32
925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->Ico.U32 == 0);
926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Is this literally IRExpr_Const(IRConst_U64(0)) ? */
929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool isZeroU64 ( IRExpr* e )
930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toBool( e->tag == Iex_Const
932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->tag == Ico_U64
933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->Ico.U64 == 0);
934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool notBool ( Bool b )
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b == True) return False;
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b == False) return True;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("notBool");
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a zero which has the same type as the result of the given
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   primop. */
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkZeroOfPrimopResultType ( IROp op )
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8:  return IRExpr_Const(IRConst_U8(0));
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32:
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64:
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128: return IRExpr_Const(IRConst_V128(0));
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("mkZeroOfPrimopResultType: bad primop");
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a value containing all 1-bits, which has the same type as the
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result of the given primop. */
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkOnesOfPrimopResultType ( IROp op )
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_U1(toBool(1)));
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x8:
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_U64(0xFFFFFFFFFFFFFFFFULL));
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_V128(0xFFFF));
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mkOnesOfPrimopResultType: bad primop");
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Helpers for folding Clz32/64. */
976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt fold_Clz64 ( ULong value )
977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt i;
979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(value != 0ULL); /* no defined semantics for arg==0 */
980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 64; ++i) {
981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0ULL != (value & (((ULong)1) << (63 - i)))) return i;
982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(0);
984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt fold_Clz32 ( UInt value )
989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt i;
991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(value != 0); /* no defined semantics for arg==0 */
992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 32; ++i) {
993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0 != (value & (((UInt)1) << (31 - i)))) return i;
994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(0);
996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_Expr ( IRExpr* e )
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     shift;
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e2 = e; /* e2 is the result of folding e, if possible */
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* UNARY ops */
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.arg->tag == Iex_Const) {
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto8:
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0)));
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto32:
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0));
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto64:
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0));
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto8:
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFF : 0)));
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto16:
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFF : 0)));
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto32:
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFFFFFF : 0));
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto64:
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFFFFFFFFFFFFFFULL : 0));
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto32: {
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 <<= 24;
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 >>= 24;
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32((UInt)s32));
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16Sto32: {
1055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s32 <<= 16;
1057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s32 >>= 16;
1058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U32( (UInt)s32) );
1059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto64:
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto64:
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto32:
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_8Sto16: {
1074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Short s16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s16 <<= 8;
1076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s16 >>= 8;
1077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U16( (UShort)s16) );
1078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_8Uto16:
1081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U16(
1082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto32:
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to16:
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to8:
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to1:
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to1:
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U64)
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not64:
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U64)));
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not32:
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not16:
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U16))));
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not8:
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U8))));
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not1:
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to8: {
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0xFFULL;
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8( (UChar)w64 ));
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to16: {
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0xFFFFULL;
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16( (UShort)w64 ));
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to32: {
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0x00000000FFFFFFFFULL;
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64HIto32: {
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 >>= 32;
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Uto64:
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFFFFFFULL
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    & e->Iex.Unop.arg->Iex.Const.con->Ico.U32));
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16Sto64: {
1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Long s64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s64 <<= 48;
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s64 >>= 48;
1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Sto64: {
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* signed */ Long s64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 <<= 32;
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 >>= 32;
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16to8: {
1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 &= 0xFF;
1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16HIto8: {
1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 >>= 8;
1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 &= 0xFF;
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ8:
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0 !=
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ32:
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0 !=
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ64:
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ32: {
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt w32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (w32 == 0)
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32( 0 ));
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32( 0xFFFFFFFF ));
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ64: {
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (w64 == 0)
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64( 0 ));
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64( 0xFFFFFFFFFFFFFFFFULL ));
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left32: {
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int  s32 = (Int)(u32 & 0xFFFFFFFF);
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 = (s32 | (-s32));
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const( IRConst_U32( (UInt)s32 ));
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left64: {
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Long  s64 = (Long)u64;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 = (s64 | (-s64));
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const( IRConst_U64( (ULong)s64 ));
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_Clz32: {
1239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (u32 != 0)
1241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U32(fold_Clz32(u32)));
1242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_Clz64: {
1245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (u64 != 0ULL)
1247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U64(fold_Clz64(u64)));
1248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* BINARY ops */
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.arg1->tag == Iex_Const
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const) {
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cases where both args are consts */
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Or -- */
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or8:
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or16:
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U16(toUShort(
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or32:
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or64:
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Xor -- */
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor8:
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor16:
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U16(toUShort(
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor32:
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor64:
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- And -- */
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And8:
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_And16:
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U16(toUShort(
1315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And32:
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And64:
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Add -- */
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add8:
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add32:
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add64:
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Sub -- */
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub8:
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub32:
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub64:
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Max32U -- */
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Max32U: {
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt res  = u32a > u32b ? u32a : u32b;
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(res));
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Mul -- */
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Mul32:
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Mul64:
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullS32: {
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* very paranoid */
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32a = (Int)u32a;
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32b = (Int)u32b;
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  s64a = (Long)s32a;
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  s64b = (Long)s32b;
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  sres = s64a * s64b;
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong ures = (ULong)sres;
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(ures));
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Shl -- */
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl32:
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31)
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32(
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           << shift)));
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl64:
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63)
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64(
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           << shift)));
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Sar -- */
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar32: {
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*signed*/ Int s32;
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               s32   = (Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31) {
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  s32 >>=/*signed*/ shift;
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32((UInt)s32));
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar64: {
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*signed*/ Long s64;
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               s64   = (Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63) {
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  s64 >>=/*signed*/ shift;
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Shr -- */
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr32: {
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*unsigned*/ UInt u32;
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               u32   = (UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31) {
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  u32 >>=/*unsigned*/ shift;
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32(u32));
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr64: {
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*unsigned*/ ULong u64;
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               u64   = (ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63) {
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  u64 >>=/*unsigned*/ shift;
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64(u64));
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpEQ -- */
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ32:
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ64:
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpNE -- */
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE8:
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((0xFF & e->Iex.Binop.arg1->Iex.Const.con->Ico.U8)
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != (0xFF & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8)))));
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE32:
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE64:
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLEU -- */
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLE32U:
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        <= (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLE64U:
1504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        <= (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLES -- */
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLE32S:
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        <= (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLE64S:
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        <= (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLTS -- */
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLT32S:
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        < (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLT64S:
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        < (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLTU -- */
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLT32U:
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        < (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLT64U:
1540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        < (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpORD -- */
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpORD32S: {
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* very paranoid */
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32a = (Int)u32a;
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32b = (Int)u32b;
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   r = 0x2; /* EQ */
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (s32a < s32b) {
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r = 0x8; /* LT */
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else if (s32a > s32b) {
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r = 0x4; /* GT */
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(r));
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- nHLto2n -- */
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_32HLto64:
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)) << 32)
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       | ((ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ));
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_64HLto128:
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* We can't fold this, because there is no way to
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  express he result in IR, but at least pretend to
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  handle it, so as to stop getting blasted with
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  no-rule-for-this-primop messages. */
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled;
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* other cases (identities, etc) */
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Shl64/Shr64(x,0) ==> x */
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((e->Iex.Binop.op == Iop_Shl64 || e->Iex.Binop.op == Iop_Shr64)
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_Const
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 == 0) {
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg1;
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Shl32/Shr32(x,0) ==> x */
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((e->Iex.Binop.op == Iop_Shl32 || e->Iex.Binop.op == Iop_Shr32)
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_Const
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 == 0) {
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg1;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or8(x,0) ==> x */
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((e->Iex.Binop.op == Iop_Or8)
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_Const
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 == 0) {
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg1;
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or16(x,0) ==> x */
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((e->Iex.Binop.op == Iop_Or16)
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_Const
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U16 == 0) {
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg1;
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Or32/Add32/Max32U(x,0) ==> x
1614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Or32/Add32/Max32U(0,x) ==> x */
1615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (e->Iex.Binop.op == Iop_Add32
1616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             || e->Iex.Binop.op == Iop_Or32 || e->Iex.Binop.op == Iop_Max32U) {
1617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (isZeroU32(e->Iex.Binop.arg2))
1618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = e->Iex.Binop.arg1;
1619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else if (isZeroU32(e->Iex.Binop.arg1))
1620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = e->Iex.Binop.arg2;
1621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else
1622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Sub64(x,0) ==> x */
1624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (e->Iex.Binop.op == Iop_Sub64 && isZeroU64(e->Iex.Binop.arg2)) {
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg1;
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add32(t,t) ==> t << 1.  Memcheck doesn't understand that
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            x+x produces a defined least significant bit, and it seems
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            simplest just to get rid of the problem by rewriting it
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            out, since the opportunity to do so exists. */
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op == Iop_Add32
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->tag == Iex_RdTmp
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_RdTmp
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->Iex.RdTmp.tmp
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                == e->Iex.Binop.arg2->Iex.RdTmp.tmp) {
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Binop(Iop_Shl32,
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.Binop.arg1,
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(IRConst_U8(1)));
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add64(t,t) ==> t << 1;  rationale as for Add32(t,t) above. */
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op == Iop_Add64
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->tag == Iex_RdTmp
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_RdTmp
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->Iex.RdTmp.tmp
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                == e->Iex.Binop.arg2->Iex.RdTmp.tmp) {
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Binop(Iop_Shl64,
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.Binop.arg1,
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(IRConst_U8(1)));
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add8(t,t) ==> t << 1;  rationale as for Add32(t,t) above. */
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op == Iop_Add8
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->tag == Iex_RdTmp
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_RdTmp
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->Iex.RdTmp.tmp
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                == e->Iex.Binop.arg2->Iex.RdTmp.tmp) {
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Binop(Iop_Shl8,
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.Binop.arg1,
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(IRConst_U8(1)));
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* NB no Add16(t,t) case yet as no known test case exists */
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Or64/Add64(x,0) ==> x
1666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            Or64/Add64(0,x) ==> x */
1667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (e->Iex.Binop.op == Iop_Add64 || e->Iex.Binop.op == Iop_Or64) {
1668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (isZeroU64(e->Iex.Binop.arg2))
1669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = e->Iex.Binop.arg1;
1670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else if (isZeroU64(e->Iex.Binop.arg1))
1671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = e->Iex.Binop.arg2;
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And32(x,0xFFFFFFFF) ==> x */
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op == Iop_And32
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_Const
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U32 == 0xFFFFFFFF) {
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg1;
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And32(x,0) ==> 0 */
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op == Iop_And32
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->tag == Iex_Const
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg2->Iex.Const.con->Ico.U32 == 0) {
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(0));
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And32/Shl32(0,x) ==> 0 */
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((e->Iex.Binop.op == Iop_And32 || e->Iex.Binop.op == Iop_Shl32)
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->tag == Iex_Const
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 == 0) {
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(0));
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or8(0,x) ==> x */
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op == Iop_Or8
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->tag == Iex_Const
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && e->Iex.Binop.arg1->Iex.Const.con->Ico.U8 == 0) {
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = e->Iex.Binop.arg2;
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or8/16/32/64/V128(t,t) ==> t, for some IRTemp t */
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And8/16/32/64(t,t) ==> t, for some IRTemp t */
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Max32U(t,t) ==> t, for some IRTemp t */
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And64: case Iop_And32:
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And16: case Iop_And8:
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or64: case Iop_Or32:
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or16: case Iop_Or8: case Iop_OrV128:
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Max32U:
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2))
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = e->Iex.Binop.arg1;
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Xor8/16/32/64/V128(t,t) ==> 0, for some IRTemp t */
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Sub32/64(t,t) ==> 0, for some IRTemp t */
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor64: case Iop_Xor32:
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor16: case Iop_Xor8:
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_XorV128:
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub64: case Iop_Sub32:
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2))
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ64:
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8x8:
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8x16:
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2))
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Mux0X */
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* is the discriminant is a constant? */
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Mux0X.cond->tag == Iex_Const) {
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool zero;
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assured us by the IR type rules */
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(e->Iex.Mux0X.cond->Iex.Const.con->tag == Ico_U8);
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zero = toBool(0 == (0xFF & e->Iex.Mux0X.cond
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     ->Iex.Const.con->Ico.U8));
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = zero ? e->Iex.Mux0X.expr0 : e->Iex.Mux0X.exprX;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* are the arms identical? (pretty weedy test) */
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sameIRTempsOrIcoU32s(e->Iex.Mux0X.expr0,
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               e->Iex.Mux0X.exprX)) {
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = e->Iex.Mux0X.expr0;
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Show cases where we've found but not folded 'op(t,t)'. */
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 && e == e2 && e->tag == Iex_Binop
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("IDENT: ");
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e); vex_printf("\n");
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Show the overall results of folding. */
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_IROPT && e2 != e) {
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("FOLD: ");
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e); vex_printf("  ->  ");
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e2); vex_printf("\n");
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e2;
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unhandled:
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n\n");
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("fold_Expr: no rule for the above");
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_verbosity > 0) {
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("vex iropt: fold_Expr: no rule for: ");
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e);
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e2;
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Apply the subst to a simple 1-level expression -- guaranteed to be
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1-level due to previous flattening pass. */
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex )
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ex->tag) {
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[(Int)ex->Iex.RdTmp.tmp] != NULL) {
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return env[(Int)ex->Iex.RdTmp.tmp];
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* not bound in env */
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ex;
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ex;
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.GetI.ix));
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ex->Iex.GetI.descr,
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            subst_Expr(env, ex->Iex.GetI.ix),
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ex->Iex.GetI.bias
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Qop.arg1));
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Qop.arg2));
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Qop.arg3));
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Qop.arg4));
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Qop(
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Qop.op,
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Qop.arg1),
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Qop.arg2),
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Qop.arg3),
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Qop.arg4)
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Triop.arg1));
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Triop.arg2));
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Triop.arg3));
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Triop(
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Triop.op,
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Triop.arg1),
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Triop.arg2),
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Triop.arg3)
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Binop.arg1));
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Binop.arg2));
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop(
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Binop.op,
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Binop.arg1),
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Binop.arg2)
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Unop.arg));
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Unop.op,
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Unop.arg)
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Load.addr));
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Load(
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Load.end,
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Load.ty,
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Load.addr)
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall: {
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int      i;
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args2 = shallowCopyIRExprVec(ex->Iex.CCall.args);
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args2[i]; i++) {
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(args2[i]));
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args2[i] = subst_Expr(env, args2[i]);
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_CCall(
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.CCall.cee,
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.CCall.retty,
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   args2
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Mux0X.cond));
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Mux0X.expr0));
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Mux0X.exprX));
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Mux0X(
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Mux0X.cond),
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Mux0X.expr0),
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Mux0X.exprX)
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n\n"); ppIRExpr(ex);
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("subst_Expr");
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Apply the subst to stmt, then fold the result as much as possible.
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Much simplified due to stmt being previously flattened.  As a
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result of this, the stmt may wind up being turned into a no-op.
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nsubst and fold stmt\n");
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(st);
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.base));
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.nia));
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_AbiHint(
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.AbiHint.base)),
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.AbiHint.len,
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.AbiHint.nia))
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Put.data));
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Put(
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Put.offset,
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.Put.data))
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.PutI.ix));
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.PutI.data));
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_PutI(
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.PutI.descr,
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.PutI.ix)),
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.PutI.bias,
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.PutI.data))
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is the one place where an expr (st->Ist.WrTmp.data) is
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            allowed to be more than just a constant or a tmp. */
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_WrTmp(
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.WrTmp.tmp,
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.WrTmp.data))
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.addr));
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.data));
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Store(
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Store.end,
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.Store.addr)),
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.Store.data))
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS: {
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS *cas, *cas2;
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->addr));
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->expdLo));
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->dataLo));
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS(
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->oldHi, cas->oldLo, cas->end,
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, cas->addr)),
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->expdHi ? fold_Expr(subst_Expr(env, cas->expdHi)) : NULL,
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, cas->expdLo)),
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->dataHi ? fold_Expr(subst_Expr(env, cas->dataHi)) : NULL,
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, cas->dataLo))
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_CAS(cas2);
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.LLSC.addr));
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.LLSC.storedata));
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_LLSC(
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.end,
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.result,
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   fold_Expr(subst_Expr(env, st->Ist.LLSC.addr)),
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.storedata
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? fold_Expr(subst_Expr(env, st->Ist.LLSC.storedata))
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : NULL
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty: {
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int     i;
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty *d, *d2;
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->args = shallowCopyIRExprVec(d2->args);
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None) {
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d2->mAddr));
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = fold_Expr(subst_Expr(env, d2->mAddr));
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(d2->guard));
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = fold_Expr(subst_Expr(env, d2->guard));
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++) {
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d2->args[i]));
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->args[i] = fold_Expr(subst_Expr(env, d2->args[i]));
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Dirty(d2);
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
2011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return IRStmt_IMark(st->Ist.IMark.addr,
2012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.len,
2013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.delta);
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_NoOp();
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_MBE(st->Ist.MBE.event);
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit: {
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* fcond;
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fcond = fold_Expr(subst_Expr(env, st->Ist.Exit.guard));
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fcond->tag == Iex_Const) {
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Interesting.  The condition on this exit has folded down to
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a constant. */
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(fcond->Iex.Const.con->tag == Ico_U1);
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(fcond->Iex.Const.con->Ico.U1 == False
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    || fcond->Iex.Const.con->Ico.U1 == True);
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fcond->Iex.Const.con->Ico.U1 == False) {
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* exit is never going to happen, so dump the statement. */
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return IRStmt_NoOp();
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(fcond->Iex.Const.con->Ico.U1 == True);
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Hmmm.  The exit has become unconditional.  Leave it
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  as it is for now, since we'd have to truncate the BB
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  at this point, which is tricky.  Such truncation is
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  done later by the dead-code elimination pass. */
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* fall out into the reconstruct-the-exit code. */
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (vex_control.iropt_verbosity > 0)
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* really a misuse of vex_control.iropt_verbosity */
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vex_printf("vex iropt: IRStmt_Exit became unconditional\n");
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Exit(fcond, st->Ist.Exit.jk, st->Ist.Exit.dst);
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n"); ppIRStmt(st);
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("subst_and_fold_Stmt");
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cprop_BB ( IRSB* in )
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*    out;
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st2;
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      n_tmps = in->tyenv->types_used;
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** env = LibVEX_Alloc(n_tmps * sizeof(IRExpr*));
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out = emptyIRSB();
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up the env with which travels forward.  This holds a
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      substitution, mapping IRTemps to atoms, that is, IRExprs which
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are either IRTemps or IRConsts.  Thus, copy and constant
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      propagation is done.  The environment is to be applied as we
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      move along.  Keys are IRTemps.  Values are IRExpr*s.
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i] = NULL;
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each original SSA-form stmt ... */
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < in->stmts_used; i++) {
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* First apply the substitution to the current stmt.  This
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         propagates in any constants and tmp-tmp assignments
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         accumulated prior to this point.  As part of the subst_Stmt
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         call, also then fold any constant expressions resulting. */
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = in->stmts[i];
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* perhaps st2 is already a no-op? */
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_NoOp) continue;
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = subst_and_fold_Stmt( env, st2 );
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the statement has been folded into a no-op, forget it. */
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_NoOp) continue;
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now consider what the stmt looks like.  If it's of the form
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         't = const' or 't1 = t2', add it to the running environment
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and not to the output BB.  Otherwise, add it to the output
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         BB.  Note, we choose not to propagate const when const is an
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         F64i, so that F64i literals can be CSE'd later.  This helps
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x86 floating point code generation. */
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_WrTmp
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st2->Ist.WrTmp.data->tag == Iex_Const
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st2->Ist.WrTmp.data->Iex.Const.con->tag != Ico_F64i) {
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 't = const' -- add to env.
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             The pair (IRTemp, IRExpr*) is added. */
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[(Int)(st2->Ist.WrTmp.tmp)] = st2->Ist.WrTmp.data;
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_WrTmp && st2->Ist.WrTmp.data->tag == Iex_RdTmp) {
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 't1 = t2' -- add to env.
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             The pair (IRTemp, IRExpr*) is added. */
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[(Int)(st2->Ist.WrTmp.tmp)] = st2->Ist.WrTmp.data;
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not interesting, copy st2 into the output block. */
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB( out, st2 );
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->next     = subst_Expr( env, in->next );
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->jumpkind = in->jumpkind;
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return out;
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Dead code (t = E) removal                               ---*/
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* As a side effect, also removes all code following an unconditional
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   side exit. */
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The type of the HashHW map is: a map from IRTemp to nothing
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- really just operating a set or IRTemps.
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Temp ( Bool* set, IRTemp tmp )
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set[(Int)tmp] = True;
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Expr ( Bool* set, IRExpr* e )
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.GetI.ix);
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Mux0X.cond);
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Mux0X.expr0);
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Mux0X.exprX);
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, e->Iex.CCall.args[i]);
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Load.addr);
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Qop.arg1);
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Qop.arg2);
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Qop.arg3);
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Qop.arg4);
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Triop.arg1);
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Triop.arg2);
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Triop.arg3);
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Binop.arg1);
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Binop.arg2);
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Unop.arg);
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Temp(set, e->Iex.RdTmp.tmp);
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addUses_Expr");
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Stmt ( Bool* set, IRStmt* st )
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.AbiHint.base);
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.AbiHint.nia);
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.PutI.ix);
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.PutI.data);
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.WrTmp.data);
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Put.data);
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Store.addr);
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Store.data);
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->addr);
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->expdHi)
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, cas->expdHi);
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->expdLo);
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->dataHi)
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, cas->dataHi);
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->dataLo);
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.LLSC.addr);
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, st->Ist.LLSC.storedata);
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mFx != Ifx_None)
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, d->mAddr);
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, d->guard);
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i] != NULL; i++)
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, d->args[i]);
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Exit.guard);
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addUses_Stmt");
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this literally IRExpr_Const(IRConst_U1(False)) ? */
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU1 ( IRExpr* e )
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U1
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U1 == False );
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this literally IRExpr_Const(IRConst_U1(True)) ? */
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isOneU1 ( IRExpr* e )
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U1
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U1 == True );
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note, this destructively modifies the given IRSB. */
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan backwards through statements, carrying a set of IRTemps which
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are known to be used after the current point.  On encountering 't =
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E', delete the binding if it is not used.  Otherwise, add any temp
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uses to the set and keep on moving backwards.
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   As an enhancement, the first (backwards) pass searches for IR exits
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with always-taken conditions and notes the location of the earliest
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   one in the block.  If any such are found, a second pass copies the
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exit destination and jump kind to the bb-end.  Then, the exit and
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all statements following it are turned into no-ops.
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* notstatic */ void do_deadcode_BB ( IRSB* bb )
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, i_unconditional_exit;
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     n_tmps = bb->tyenv->types_used;
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool*   set = LibVEX_Alloc(n_tmps * sizeof(Bool));
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set[i] = False;
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* start off by recording IRTemp uses in the next field. */
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addUses_Expr(set, bb->next);
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First pass */
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Work backwards through the stmts */
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_unconditional_exit = -1;
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* take note of any unconditional exits */
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Exit
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isOneU1(st->Ist.Exit.guard))
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i_unconditional_exit = i;
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && set[(Int)(st->Ist.WrTmp.tmp)] == False) {
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* it's an IRTemp which never got used.  Delete it. */
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("DEAD: ");
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.Dirty.details->guard
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isZeroU1(st->Ist.Dirty.details->guard)) {
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is a dirty helper which will never get called.
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Delete it. */
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       else {
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note any IRTemp uses made by the current statement. */
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Stmt(set, st);
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Optional second pass: if any unconditional exits were found,
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete them and all following statements. */
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i_unconditional_exit != -1) {
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) vex_printf("ZAPPING ALL FORWARDS from %d\n",
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        i_unconditional_exit);
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i_unconditional_exit >= 0
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && i_unconditional_exit < bb->stmts_used);
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->next
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRExpr_Const( bb->stmts[i_unconditional_exit]->Ist.Exit.dst );
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->jumpkind
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = bb->stmts[i_unconditional_exit]->Ist.Exit.jk;
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = i_unconditional_exit; i < bb->stmts_used; i++)
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Specialisation of helper function calls, in             ---*/
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- collaboration with the front end                        ---*/
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* spec_helpers_BB(
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb,
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* (*specHelper) (HChar*, IRExpr**, IRStmt**, Int)
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ex;
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    any = False;
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || st->Ist.WrTmp.data->tag != Iex_CCall)
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ex = (*specHelper)( st->Ist.WrTmp.data->Iex.CCall.cee->name,
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          st->Ist.WrTmp.data->Iex.CCall.args,
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          &bb->stmts[0], i );
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ex)
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* the front end can't think of a suitable replacement */
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        continue;
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We got something better.  Install it in the bb. */
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      any = True;
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->stmts[i]
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRStmt_WrTmp(st->Ist.WrTmp.tmp, ex);
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) {
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("SPEC: ");
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(st->Ist.WrTmp.data);
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("  -->  ");
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ex);
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (any)
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = flatten_BB(bb);
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Determination of guest state aliasing relationships     ---*/
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are helper functions for CSE and GetI/PutI transformations.
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Determine, to the extent possible, the relationship between two
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest state accesses.  The possible outcomes are:
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Exact alias.  These two accesses denote precisely the same
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     piece of the guest state.
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Definitely no alias.  These two accesses are guaranteed not to
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     overlap any part of the guest state.
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Unknown -- if neither of the above can be established.
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If in doubt, return Unknown.  */
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum { ExactAlias, NoAlias, UnknownAlias }
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing;
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces the alias relation between an indexed guest
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state access and a non-indexed access. */
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGSAliasing getAliasingRelation_IC ( IRRegArray* descr1, IRExpr* ix1,
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    Int offset2, IRType ty2 )
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff1, maxoff1, minoff2, maxoff2;
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr1, &minoff1, &maxoff1 );
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   minoff2 = offset2;
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   maxoff2 = minoff2 + sizeofIRType(ty2) - 1;
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff1 < minoff2 || maxoff2 < minoff1)
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NoAlias;
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Could probably do better here if required.  For the moment
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      however just claim not to know anything more. */
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return UnknownAlias;
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces the alias relation between two indexed guest state
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accesses. */
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGSAliasing getAliasingRelation_II (
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRRegArray* descr1, IRExpr* ix1, Int bias1,
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRRegArray* descr2, IRExpr* ix2, Int bias2
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           )
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff1, maxoff1, minoff2, maxoff2;
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  iters;
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First try hard to show they don't alias. */
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr1, &minoff1, &maxoff1 );
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr2, &minoff2, &maxoff2 );
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff1 < minoff2 || maxoff2 < minoff1)
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NoAlias;
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So the two arrays at least partially overlap.  To get any
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      further we'll have to be sure that the descriptors are
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      identical. */
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!eqIRRegArray(descr1, descr2))
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return UnknownAlias;
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The descriptors are identical.  Now the only difference can be
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in the index expressions.  If they cannot be shown to be
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      identical, we have to say we don't know what the aliasing
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      relation will be.  Now, since the IR is flattened, the index
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expressions should be atoms -- either consts or tmps.  So that
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      makes the comparison simple. */
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isIRAtom(ix1));
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isIRAtom(ix2));
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!eqIRAtom(ix1,ix2))
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return UnknownAlias;
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, the index expressions are identical.  So now the only way
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      they can be different is in the bias.  Normalise this
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      paranoidly, to reliably establish equality/non-equality. */
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So now we know that the GetI and PutI index the same array
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      with the same base.  Are the offsets the same, modulo the
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      array size?  Do this paranoidly. */
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->nElems == descr2->nElems);
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->elemTy == descr2->elemTy);
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->base   == descr2->base);
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iters = 0;
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (bias1 < 0 || bias2 < 0) {
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bias1 += descr1->nElems;
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bias2 += descr1->nElems;
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters++;
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (iters > 10)
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("getAliasingRelation: iters");
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias1 >= 0 && bias2 >= 0);
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias1 %= descr1->nElems;
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias2 %= descr1->nElems;
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias1 >= 0 && bias1 < descr1->nElems);
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias2 >= 0 && bias2 < descr1->nElems);
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, biasP and biasG are normalised into the range
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0 .. descrP/G->nElems - 1.  And so we can establish
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      equality/non-equality. */
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bias1==bias2 ? ExactAlias : NoAlias;
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Common Subexpression Elimination                        ---*/
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expensive in time and space. */
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Uses two environments:
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a IRTemp -> IRTemp mapping
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a mapping from AvailExpr* to IRTemp
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      enum { Ut, Btt, Btc, Bct, Cf64i, Mttt, GetIt } tag;
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union {
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unop(tmp) */
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   op;
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg;
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Ut;
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(tmp,tmp) */
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   op;
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg1;
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg2;
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Btt;
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(tmp,const) */
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp    op;
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp  arg1;
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst con2;
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Btc;
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(const,tmp) */
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp    op;
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst con1;
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp  arg2;
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bct;
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* F64i-style const */
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong f64i;
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Cf64i;
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Mux0X(tmp,tmp,tmp) */
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp co;
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp e0;
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp eX;
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Mttt;
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* GetI(descr,tmp,bias)*/
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRRegArray* descr;
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp      ix;
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int         bias;
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } GetIt;
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } u;
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr;
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool eq_AvailExpr ( AvailExpr* a1, AvailExpr* a2 )
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag != a2->tag)
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (a1->tag) {
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Ut.op == a2->u.Ut.op
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Ut.arg == a2->u.Ut.arg);
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Btt.op == a2->u.Btt.op
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btt.arg1 == a2->u.Btt.arg1
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btt.arg2 == a2->u.Btt.arg2);
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Btc.op == a2->u.Btc.op
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btc.arg1 == a2->u.Btc.arg1
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && eqIRConst(&a1->u.Btc.con2, &a2->u.Btc.con2));
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Bct.op == a2->u.Bct.op
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Bct.arg2 == a2->u.Bct.arg2
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && eqIRConst(&a1->u.Bct.con1, &a2->u.Bct.con1));
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(a1->u.Cf64i.f64i == a2->u.Cf64i.f64i);
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Mttt:
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(a1->u.Mttt.co == a2->u.Mttt.co
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.Mttt.e0 == a2->u.Mttt.e0
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.Mttt.eX == a2->u.Mttt.eX);
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(eqIRRegArray(a1->u.GetIt.descr, a2->u.GetIt.descr)
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.GetIt.ix == a2->u.GetIt.ix
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.GetIt.bias == a2->u.GetIt.bias);
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("eq_AvailExpr");
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* availExpr_to_IRExpr ( AvailExpr* ae )
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ae->tag) {
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( ae->u.Ut.op, IRExpr_RdTmp(ae->u.Ut.arg) );
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Btt.op,
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btt.arg1),
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btt.arg2) );
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con = LibVEX_Alloc(sizeof(IRConst));
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *con = ae->u.Btc.con2;
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Btc.op,
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btc.arg1),
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(con) );
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con = LibVEX_Alloc(sizeof(IRConst));
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *con = ae->u.Bct.con1;
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Bct.op,
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(con),
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Bct.arg2) );
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_F64i(ae->u.Cf64i.f64i));
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Mttt:
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Mux0X(IRExpr_RdTmp(ae->u.Mttt.co),
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(ae->u.Mttt.e0),
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(ae->u.Mttt.eX));
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(ae->u.GetIt.descr,
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRExpr_RdTmp(ae->u.GetIt.ix),
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            ae->u.GetIt.bias);
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("availExpr_to_IRExpr");
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp subst_AvailExpr_Temp ( HashHW* env, IRTemp tmp )
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord res;
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* env :: IRTemp -> IRTemp */
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (lookupHHW( env, &res, (HWord)tmp ))
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (IRTemp)res;
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return tmp;
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void subst_AvailExpr ( HashHW* env, AvailExpr* ae )
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* env :: IRTemp -> IRTemp */
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ae->tag) {
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Ut.arg = subst_AvailExpr_Temp( env, ae->u.Ut.arg );
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btt.arg1 = subst_AvailExpr_Temp( env, ae->u.Btt.arg1 );
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btt.arg2 = subst_AvailExpr_Temp( env, ae->u.Btt.arg2 );
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btc.arg1 = subst_AvailExpr_Temp( env, ae->u.Btc.arg1 );
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Bct.arg2 = subst_AvailExpr_Temp( env, ae->u.Bct.arg2 );
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Mttt:
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Mttt.co = subst_AvailExpr_Temp( env, ae->u.Mttt.co );
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Mttt.e0 = subst_AvailExpr_Temp( env, ae->u.Mttt.e0 );
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Mttt.eX = subst_AvailExpr_Temp( env, ae->u.Mttt.eX );
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.GetIt.ix = subst_AvailExpr_Temp( env, ae->u.GetIt.ix );
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("subst_AvailExpr");
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AvailExpr* irExpr_to_AvailExpr ( IRExpr* e )
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* ae;
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.arg->tag == Iex_RdTmp) {
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag      = Ut;
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Ut.op  = e->Iex.Unop.op;
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Ut.arg = e->Iex.Unop.arg->Iex.RdTmp.tmp;
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1->tag == Iex_RdTmp
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_RdTmp) {
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag        = Btt;
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btt.op   = e->Iex.Binop.op;
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btt.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btt.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg1->tag == Iex_RdTmp
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg2->tag == Iex_Const) {
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag        = Btc;
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btc.op   = e->Iex.Binop.op;
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btc.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btc.con2 = *(e->Iex.Binop.arg2->Iex.Const.con);
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg1->tag == Iex_Const
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg2->tag == Iex_RdTmp) {
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag        = Bct;
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Bct.op   = e->Iex.Binop.op;
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Bct.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Bct.con1 = *(e->Iex.Binop.arg1->Iex.Const.con);
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->tag == Ico_F64i) {
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag          = Cf64i;
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Cf64i.f64i = e->Iex.Const.con->Ico.F64i;
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Mux0X.cond->tag == Iex_RdTmp
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Mux0X.expr0->tag == Iex_RdTmp
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Mux0X.exprX->tag == Iex_RdTmp) {
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag       = Mttt;
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Mttt.co = e->Iex.Mux0X.cond->Iex.RdTmp.tmp;
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Mttt.e0 = e->Iex.Mux0X.expr0->Iex.RdTmp.tmp;
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Mttt.eX = e->Iex.Mux0X.exprX->Iex.RdTmp.tmp;
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_GetI
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.GetI.ix->tag == Iex_RdTmp) {
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag           = GetIt;
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.GetIt.descr = e->Iex.GetI.descr;
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.GetIt.ix    = e->Iex.GetI.ix->Iex.RdTmp.tmp;
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.GetIt.bias  = e->Iex.GetI.bias;
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The BB is modified in-place.  Returns True if any changes were
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   made. */
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool do_cse_BB ( IRSB* bb )
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, j, paranoia;
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp     t, q;
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* eprime;
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* ae;
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       invalidate;
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       anyDone = False;
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* tenv = newHHW(); /* :: IRTemp -> IRTemp */
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* aenv = newHHW(); /* :: AvailExpr* -> IRTemp */
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sizeof(IRTemp) <= sizeof(HWord));
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) { ppIRSB(bb); vex_printf("\n\n"); }
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate forwards over the stmts.
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      On seeing "t = E", where E is one of the 5 AvailExpr forms:
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         let E' = apply tenv substitution to E
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         search aenv for E'
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if a mapping E' -> q is found,
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               replace this stmt by "t = q"
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and add binding t -> q to tenv
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add binding E' -> t to aenv
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               replace this stmt by "t = E'"
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Other statements are only interesting to the extent that they
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      might invalidate some of the expressions in aenv.  So there is
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an invalidate-bindings check for each statement seen.
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ BEGIN invalidate aenv bindings ------ */
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is critical: remove from aenv any E' -> .. bindings
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         which might be invalidated by this statement.  The only
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vulnerable kind of bindings are the GetI kind.
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Dirty call - dump (paranoia level -> 2)
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Store      - dump (ditto)
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Put, PutI  - dump unless no-overlap is proven (.. -> 1)
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Uses getAliasingRelation_IC and getAliasingRelation_II
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to do the no-overlap assessments needed for Put/PutI.
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty: case Ist_Store: case Ist_MBE:
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS: case Ist_LLSC:
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 2; break;
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put: case Ist_PutI:
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 1; break;
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp: case Ist_IMark: case Ist_AbiHint:
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp: case Ist_Exit:
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 0; break;
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("do_cse_BB(1)");
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (paranoia > 0) {
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < aenv->used; j++) {
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!aenv->inuse[j])
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ae = (AvailExpr*)aenv->key[j];
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ae->tag != GetIt)
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalidate = False;
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (paranoia >= 2) {
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               invalidate = True;
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(paranoia == 1);
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (st->tag == Ist_Put) {
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (getAliasingRelation_IC(
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.descr,
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(ae->u.GetIt.ix),
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.Put.offset,
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         typeOfIRExpr(bb->tyenv,st->Ist.Put.data)
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ) != NoAlias)
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     invalidate = True;
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (st->tag == Ist_PutI) {
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (getAliasingRelation_II(
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.descr,
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(ae->u.GetIt.ix),
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.bias,
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.PutI.descr,
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.PutI.ix,
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.PutI.bias
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ) != NoAlias)
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     invalidate = True;
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vpanic("do_cse_BB(2)");
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (invalidate) {
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               aenv->inuse[j] = False;
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               aenv->key[j]   = (HWord)NULL;  /* be sure */
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } /* for j */
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* paranoia > 0 */
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ ENV invalidate aenv bindings ------ */
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore not-interestings */
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp)
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t = st->Ist.WrTmp.tmp;
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eprime = irExpr_to_AvailExpr(st->Ist.WrTmp.data);
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore if not of AvailExpr form */
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!eprime)
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("considering: " ); ppIRStmt(st); vex_printf("\n"); */
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* apply tenv */
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subst_AvailExpr( tenv, eprime );
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* search aenv for eprime, unfortunately the hard way */
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = 0; j < aenv->used; j++)
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (aenv->inuse[j] && eq_AvailExpr(eprime, (AvailExpr*)aenv->key[j]))
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (j < aenv->used) {
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A binding E' -> q was found.  Replace stmt by "t = q" and
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            note the t->q binding in tenv. */
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* (this is the core of the CSE action) */
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         q = (IRTemp)aenv->val[j];
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_WrTmp( t, IRExpr_RdTmp(q) );
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( tenv, (HWord)t, (HWord)q );
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         anyDone = True;
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No binding was found, so instead we add E' -> t to our
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            collection of available expressions, replace this stmt
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            with "t = E'", and move on. */
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_WrTmp( t, availExpr_to_IRExpr(eprime) );
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( aenv, (HWord)eprime, (HWord)t );
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRSB(bb);
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sanityCheckIRSB(bb, Ity_I32);
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n\n");
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return anyDone;
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Add32/Sub32 chain collapsing                            ---*/
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----- Helper functions for Add32/Sub32 chain collapsing ----- */
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this expression "Add32(tmp,const)" or "Sub32(tmp,const)" ?  If
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   yes, set *tmp and *i32 appropriately.  *i32 is set as if the
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   root node is Add32, not Sub32. */
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isAdd32OrSub32 ( IRExpr* e, IRTemp* tmp, Int* i32 )
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag != Iex_Binop)
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.op != Iop_Add32 && e->Iex.Binop.op != Iop_Sub32)
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.arg1->tag != Iex_RdTmp)
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.arg2->tag != Iex_Const)
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *tmp = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i32 = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32);
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.op == Iop_Sub32)
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *i32 = -*i32;
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if tmp can be expressed as tmp2 +32 const, for some
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   other tmp2.  Scan backwards from the specified start point -- an
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisation. */
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool collapseChain ( IRSB* bb, Int startHere,
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp tmp,
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp* tmp2, Int* i32 )
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     j, ii;
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  vv;
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* the (var, con) pair contain the current 'representation' for
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'tmp'.  We start with 'tmp + 0'.  */
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp var = tmp;
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    con = 0;
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan backwards to see if tmp can be replaced by some other tmp
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     +/- a constant. */
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = startHere; j >= 0; j--) {
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[j];
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp)
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->Ist.WrTmp.tmp != var)
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = st->Ist.WrTmp.data;
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isAdd32OrSub32(e, &vv, &ii))
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      var = vv;
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con += ii;
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (j == -1)
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no earlier binding for var .. ill-formed IR */
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("collapseChain");
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* so, did we find anything interesting? */
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (var == tmp)
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; /* no .. */
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *tmp2 = var;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i32  = con;
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------- Main function for Add32/Sub32 chain collapsing ------ */
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void collapse_AddSub_chains_BB ( IRSB* bb )
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt *st;
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp var, var2;
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, con, con2;
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Try to collapse 't1 = Add32/Sub32(t2, con)'. */
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isAdd32OrSub32(st->Ist.WrTmp.data, &var, &con)) {
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* So e1 is of the form Add32(var,con) or Sub32(var,-con).
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Find out if var can be expressed as var2 + con2. */
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (collapseChain(bb, i-1, var, &var2, &con2)) {
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("replacing1 ");
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRStmt(st);
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf(" with ");
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            con2 += con;
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i]
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = IRStmt_WrTmp(
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    st->Ist.WrTmp.tmp,
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (con2 >= 0)
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? IRExpr_Binop(Iop_Add32,
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_RdTmp(var2),
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Const(IRConst_U32(con2)))
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : IRExpr_Binop(Iop_Sub32,
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_RdTmp(var2),
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Const(IRConst_U32(-con2)))
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRStmt(bb->stmts[i]);
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Try to collapse 't1 = GetI[t2, con]'. */
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_GetI
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && collapseChain(bb, i-1, st->Ist.WrTmp.data->Iex.GetI.ix
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ->Iex.RdTmp.tmp, &var2, &con2)) {
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("replacing3 ");
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" with ");
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con2 += st->Ist.WrTmp.data->Iex.GetI.bias;
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i]
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_WrTmp(
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.WrTmp.tmp,
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_GetI(st->Ist.WrTmp.data->Iex.GetI.descr,
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(var2),
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             con2));
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(bb->stmts[i]);
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perhaps st is PutI[t, con] ? */
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_PutI
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.PutI.ix->tag == Iex_RdTmp
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && collapseChain(bb, i-1, st->Ist.PutI.ix->Iex.RdTmp.tmp,
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &var2, &con2)) {
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("replacing2 ");
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" with ");
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con2 += st->Ist.PutI.bias;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i]
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           = IRStmt_PutI(st->Ist.PutI.descr,
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(var2),
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         con2,
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.PutI.data);
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(bb->stmts[i]);
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for */
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PutI/GetI transformations                               ---*/
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given the parts (descr, tmp, bias) for a GetI, scan backwards from
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the given starting point to find, if any, a PutI which writes
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exactly the same piece of guest state, and so return the expression
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that the PutI writes.  This is the core of PutI-GetI forwarding. */
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* findPutI ( IRSB* bb, Int startHere,
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRRegArray* descrG, IRExpr* ixG, Int biasG )
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        j;
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing relation;
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\nfindPutI ");
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRRegArray(descrG);
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" ");
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(ixG);
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" %d\n", biasG);
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan backwards in bb from startHere to find a suitable PutI
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binding for (descrG, ixG, biasG), if any. */
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = startHere; j >= 0; j--) {
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[j];
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put) {
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Non-indexed Put.  This can't give a binding, but we do
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            need to check it doesn't invalidate the search by
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            overlapping any part of the indexed guest state. */
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_IC(
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 descrG, ixG,
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.Put.offset,
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == NoAlias) {
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we're OK; keep going */
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relation == UnknownAlias || relation == ExactAlias */
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* If this assertion fails, we've found a Put which writes
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               an area of guest state which is read by a GetI.  Which
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               is unlikely (although not per se wrong). */
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(relation != ExactAlias);
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This Put potentially writes guest state that the GetI
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reads; we must fail. */
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_PutI) {
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation = getAliasingRelation_II(
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       descrG, ixG, biasG,
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       st->Ist.PutI.descr,
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       st->Ist.PutI.ix,
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       st->Ist.PutI.bias
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    );
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == NoAlias) {
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This PutI definitely doesn't overlap.  Ignore it and
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               keep going. */
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue; /* the for j loop */
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == UnknownAlias) {
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We don't know if this PutI writes to the same guest
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state that the GetI, or not.  So we have to give up. */
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Otherwise, we've found what we're looking for.  */
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(relation == ExactAlias);
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return st->Ist.PutI.data;
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* if (st->tag == Ist_PutI) */
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty) {
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Be conservative.  If the dirty call has any guest effects at
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            all, give up.  We could do better -- only give up if there
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            are any guest writes/modifies. */
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.Dirty.details->nFxState > 0)
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for */
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No valid replacement was found. */
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assuming pi is a PutI stmt, is s2 identical to it (in the sense
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that it writes exactly the same piece of guest state) ?  Safe
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   answer: False. */
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool identicalPutIs ( IRStmt* pi, IRStmt* s2 )
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pi->tag == Ist_PutI);
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s2->tag != Ist_PutI)
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getAliasingRelation_II(
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             pi->Ist.PutI.descr, pi->Ist.PutI.ix, pi->Ist.PutI.bias,
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             s2->Ist.PutI.descr, s2->Ist.PutI.ix, s2->Ist.PutI.bias
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          )
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          == ExactAlias
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assuming pi is a PutI stmt, is s2 a Get/GetI/Put/PutI which might
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlap it?  Safe answer: True.  Note, we could do a lot better
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   than this if needed. */
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool guestAccessWhichMightOverlapPutI (
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTypeEnv* tyenv, IRStmt* pi, IRStmt* s2
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     )
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing relation;
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       minoffP, maxoffP;
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pi->tag == Ist_PutI);
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds(pi->Ist.PutI.descr, &minoffP, &maxoffP);
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (s2->tag) {
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* just be paranoid ... these should be rare. */
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is unbelievably lame, but it's probably not
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            significant from a performance point of view.  Really, a
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CAS is a load-store op, so it should be safe to say False.
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            However .. */
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If the dirty call has any guest effects at all, give up.
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Probably could do better. */
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.Dirty.details->nFxState > 0)
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Put.data));
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_IC(
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pi->Ist.PutI.descr, pi->Ist.PutI.ix,
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 s2->Ist.Put.offset,
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(tyenv,s2->Ist.Put.data)
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto have_relation;
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.PutI.ix));
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.PutI.data));
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_II(
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pi->Ist.PutI.descr, pi->Ist.PutI.ix, pi->Ist.PutI.bias,
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 s2->Ist.PutI.descr, s2->Ist.PutI.ix, s2->Ist.PutI.bias
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto have_relation;
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.WrTmp.data->tag == Iex_GetI) {
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relation
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = getAliasingRelation_II(
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pi->Ist.PutI.descr, pi->Ist.PutI.ix,
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        pi->Ist.PutI.bias,
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.descr,
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.ix,
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.bias
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto have_relation;
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.WrTmp.data->tag == Iex_Get) {
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relation
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = getAliasingRelation_IC(
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pi->Ist.PutI.descr, pi->Ist.PutI.ix,
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.Get.offset,
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.Get.ty
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto have_relation;
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Store.addr));
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Store.data));
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(s2); vex_printf("\n");
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("guestAccessWhichMightOverlapPutI");
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  have_relation:
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (relation == NoAlias)
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True; /* ExactAlias or UnknownAlias */
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------- PutI/GetI transformations main functions --------- */
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remove redundant GetIs, to the extent that they can be detected.
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb is modified in-place. */
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_redundant_GetI_elimination ( IRSB* bb )
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_GetI
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp) {
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr = st->Ist.WrTmp.data->Iex.GetI.descr;
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr*     ix    = st->Ist.WrTmp.data->Iex.GetI.ix;
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int         bias  = st->Ist.WrTmp.data->Iex.GetI.bias;
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr*     replacement = findPutI(bb, i-1, descr, ix, bias);
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (replacement
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && isIRAtom(replacement)
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* Make sure we're doing a type-safe transformation! */
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && typeOfIRExpr(bb->tyenv, replacement) == descr->elemTy) {
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rGI:  ");
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(st->Ist.WrTmp.data);
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf(" -> ");
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(replacement);
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, replacement);
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remove redundant PutIs, to the extent which they can be detected.
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb is modified in-place. */
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_redundant_PutI_elimination ( IRSB* bb )
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, j;
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   delete;
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt *st, *stj;
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_PutI)
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, search forwards from here to see if we can find another
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PutI which makes this one redundant, and dodging various
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         hazards.  Search forwards:
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If conditional exit, give up (because anything after that
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           does not postdominate this put).
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Get which might overlap, give up (because this PutI
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           not necessarily dead).
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which is identical, stop with success.
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which might overlap, but is not identical, give up.
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a dirty helper call which might write guest state, give up.
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which definitely doesn't overlap, or any other
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           kind of stmt, continue.
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete = False;
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = i+1; j < bb->stmts_used; j++) {
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stj = bb->stmts[j];
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stj->tag == Ist_NoOp)
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (identicalPutIs(st, stj)) {
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* success! */
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete = True;
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stj->tag == Ist_Exit)
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up */
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag == Ist_Dirty)
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up; could do better here */
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (guestAccessWhichMightOverlapPutI(bb->tyenv, st, stj))
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up */
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (delete) {
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("rPI:  ");
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Loop unrolling                                          ---*/
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust all tmp values (names) in e by delta.  e is destructively
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified. */
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deltaIRExpr ( IRExpr* e, Int delta )
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e->Iex.RdTmp.tmp += delta;
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.GetI.ix, delta);
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Qop.arg1, delta);
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Qop.arg2, delta);
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Qop.arg3, delta);
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Qop.arg4, delta);
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Triop.arg1, delta);
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Triop.arg2, delta);
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Triop.arg3, delta);
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Binop.arg1, delta);
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Binop.arg2, delta);
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Unop.arg, delta);
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Load.addr, delta);
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(e->Iex.CCall.args[i], delta);
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Mux0X.cond, delta);
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Mux0X.expr0, delta);
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Mux0X.exprX, delta);
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("deltaIRExpr");
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust all tmp values (names) in st by delta.  st is destructively
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified. */
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deltaIRStmt ( IRStmt* st, Int delta )
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.AbiHint.base, delta);
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.AbiHint.nia, delta);
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Put.data, delta);
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.PutI.ix, delta);
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.PutI.data, delta);
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.WrTmp.tmp += delta;
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.WrTmp.data, delta);
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Exit.guard, delta);
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Store.addr, delta);
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Store.data, delta);
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->oldHi != IRTemp_INVALID)
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            st->Ist.CAS.details->oldHi += delta;
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.CAS.details->oldLo += delta;
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->addr, delta);
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->expdHi)
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.CAS.details->expdHi, delta);
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->expdLo, delta);
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->dataHi)
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.CAS.details->dataHi, delta);
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->dataLo, delta);
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.LLSC.result += delta;
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.LLSC.addr, delta);
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.LLSC.storedata, delta);
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(d->guard, delta);
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i]; i++)
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(d->args[i], delta);
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->tmp != IRTemp_INVALID)
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d->tmp += delta;
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mAddr)
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(d->mAddr, delta);
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("deltaIRStmt");
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If possible, return a loop-unrolled version of bb0.  The original
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is changed.  If not possible, return NULL.  */
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The two schemas considered are:
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     X: BODY; goto X
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     which unrolls to (eg)  X: BODY;BODY; goto X
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       X: BODY; if (c) goto X; goto Y
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which trivially transforms to
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       X: BODY; if (!c) goto Y; goto X;
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so it falls in the scope of the first case.
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X and Y must be literal (guest) addresses.
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int calc_unroll_factor( IRSB* bb )
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int n_stmts, i;
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_stmts = 0;
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb->stmts[i]->tag != Ist_NoOp)
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_stmts++;
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/8) {
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 8 x unrolling (%d sts -> %d sts)\n",
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 8* n_stmts);
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 8;
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/4) {
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 4 x unrolling (%d sts -> %d sts)\n",
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 4* n_stmts);
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 4;
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/2) {
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 2 x unrolling (%d sts -> %d sts)\n",
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 2* n_stmts);
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 2;
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_verbosity > 0)
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("vex iropt: not unrolling (%d sts)\n", n_stmts);
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 1;
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* maybe_loop_unroll_BB ( IRSB* bb0, Addr64 my_addr )
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j, jmax, n_vars;
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     xxx_known;
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64   xxx_value, yyy_value;
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  udst;
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB     *bb1, *bb2;
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      unroll_factor;
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_unroll_thresh <= 0)
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First off, figure out if we can unroll this loop.  Do this
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      without modifying bb0. */
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bb0->jumpkind != Ijk_Boring)
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_known = False;
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_value = 0;
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Extract the next-guest address.  If it isn't a literal, we
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to give up. */
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = bb0->next;
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (udst->tag == Iex_Const
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (udst->Iex.Const.con->tag == Ico_U32
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || udst->Iex.Const.con->tag == Ico_U64)) {
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The BB ends in a jump to a literal location. */
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xxx_known = True;
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xxx_value = udst->Iex.Const.con->tag == Ico_U64
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ?  udst->Iex.Const.con->Ico.U64
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : (Addr64)(udst->Iex.Const.con->Ico.U32);
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!xxx_known)
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we know the BB ends to a jump to a literal location.  If
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it's a jump to itself (viz, idiom #1), move directly to the
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrolling stage, first cloning the bb so the original isn't
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      modified. */
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xxx_value == my_addr) {
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unroll_factor = calc_unroll_factor( bb0 );
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (unroll_factor < 2)
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return NULL;
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb1 = deepCopyIRSB( bb0 );
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb0 = NULL;
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst = NULL; /* is now invalid */
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto do_unroll;
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Search for the second idiomatic form:
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        X: BODY; if (c) goto X; goto Y
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      We know Y, but need to establish that the last stmt
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is 'if (c) goto X'.
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   yyy_value = xxx_value;
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb0->stmts_used-1; i >= 0; i--)
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb0->stmts[i])
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i < 0)
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL; /* block with no stmts.  Strange. */
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = bb0->stmts[i];
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (st->tag != Ist_Exit)
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (st->Ist.Exit.jk != Ijk_Boring)
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = st->Ist.Exit.dst;
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_value = con->tag == Ico_U64
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ? st->Ist.Exit.dst->Ico.U64
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  : (Addr64)(st->Ist.Exit.dst->Ico.U32);
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this assertion fails, we have some kind of type error. */
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == udst->Iex.Const.con->tag);
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xxx_value != my_addr)
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We didn't find either idiom.  Give up. */
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, we found idiom #2.  Copy the BB, switch around the xxx and
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      yyy values (which makes it look like idiom #1), and go into
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrolling proper.  This means finding (again) the last stmt, in
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the copied BB. */
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unroll_factor = calc_unroll_factor( bb0 );
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (unroll_factor < 2)
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb1 = deepCopyIRSB( bb0 );
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb0 = NULL;
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = NULL; /* is now invalid */
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb1->stmts_used-1; i >= 0; i--)
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb1->stmts[i])
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The next bunch of assertions should be true since we already
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      found and checked the last stmt in the original bb. */
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i >= 0);
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = bb1->stmts[i];
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(st->tag == Ist_Exit);
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = st->Ist.Exit.dst;
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = bb1->next;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(udst->tag == Iex_Const);
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(udst->Iex.Const.con->tag == Ico_U32
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || udst->Iex.Const.con->tag == Ico_U64);
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == udst->Iex.Const.con->tag);
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* switch the xxx and yyy fields around */
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (con->tag == Ico_U64) {
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst->Iex.Const.con->Ico.U64 = xxx_value;
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con->Ico.U64 = yyy_value;
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst->Iex.Const.con->Ico.U32 = (UInt)xxx_value;
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con->Ico.U32 = (UInt)yyy_value;
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* negate the test condition */
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st->Ist.Exit.guard
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = IRExpr_Unop(Iop_Not1,deepCopyIRExpr(st->Ist.Exit.guard));
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- The unroller proper.  Both idioms are by now --- */
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- now converted to idiom 1. --- */
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_unroll:
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(unroll_factor == 2
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || unroll_factor == 4
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || unroll_factor == 8);
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   jmax = unroll_factor==8 ? 3 : (unroll_factor==4 ? 2 : 1);
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 1; j <= jmax; j++) {
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_vars = bb1->tyenv->types_used;
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb2 = deepCopyIRSB(bb1);
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_vars; i++)
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void)newIRTemp(bb1->tyenv, bb2->tyenv->types[i]);
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < bb2->stmts_used; i++) {
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* deltaIRStmt destructively modifies the stmt, but
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that's OK since bb2 is a complete fresh copy of bb1. */
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRStmt(bb2->stmts[i], n_vars);
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb1, bb2->stmts[i]);
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_IROPT) {
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\nUNROLLED (%llx)\n", my_addr);
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb1);
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flattening; sigh.  The unroller succeeds in breaking flatness
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by negating the test condition.  This should be fixed properly.
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      For the moment use this shotgun approach.  */
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return flatten_BB(bb1);
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The tree builder                                        ---*/
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This isn't part of IR optimisation.  Really it's a pass done prior
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to instruction selection, which improves the code that the
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction selector can produce. */
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- The 'tmp' environment is the central data structure here --- */
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The number of outstanding bindings we're prepared to track.
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The number of times the env becomes full and we have to dump
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the oldest binding (hence reducing code quality) falls very
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rapidly as the env size increases.  8 gives reasonable performance
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   under most circumstances. */
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define A_NENV 10
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bindee == NULL   ===  slot is not in use
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bindee != NULL   ===  slot is in use
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  binder;
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* bindee;
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    doesLoad;
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    doesGet;
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ATmpInfo;
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused))
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppAEnv ( ATmpInfo* env )
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%d  tmp %d  val ", i, (Int)env[i].binder);
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[i].bindee)
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(env[i].bindee);
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("(null)");
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Tree-traversal fns --- */
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Traverse an expr, and detect if any part of it reads memory or does
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a Get.  Be careful ... this really controls how much the
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tree-builder can reorder the code, so getting it right is critical.
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setHints_Expr (Bool* doesLoad, Bool* doesGet, IRExpr* e )
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setHints_Expr(doesLoad, doesGet, e->Iex.CCall.args[i]);
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Mux0X.cond);
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Mux0X.expr0);
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Mux0X.exprX);
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.arg1);
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.arg2);
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.arg3);
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.arg4);
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Triop.arg1);
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Triop.arg2);
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Triop.arg3);
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Binop.arg1);
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Binop.arg2);
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Unop.arg);
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesLoad = True;
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Load.addr);
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesGet = True;
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesGet = True;
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.GetI.ix);
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("setHints_Expr");
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a binding to the front of the env and slide all the rest
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   backwards.  It should be the case that the last slot is free. */
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addToEnvFront ( ATmpInfo* env, IRTemp binder, IRExpr* bindee )
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env[A_NENV-1].bindee == NULL);
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = A_NENV-1; i >= 1; i--)
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i] = env[i-1];
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].binder   = binder;
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].bindee   = bindee;
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].doesLoad = False; /* filled in later */
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].doesGet  = False; /* filled in later */
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given uses :: array of UShort, indexed by IRTemp
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Add the use-occurrences of temps in this expression
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the env.
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void aoccCount_Expr ( UShort* uses, IRExpr* e )
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp: /* the only interesting case */
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uses[e->Iex.RdTmp.tmp]++;
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Mux0X.cond);
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Mux0X.expr0);
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Mux0X.exprX);
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Qop.arg1);
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Qop.arg2);
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Qop.arg3);
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Qop.arg4);
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Triop.arg1);
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Triop.arg2);
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Triop.arg3);
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Binop.arg1);
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Binop.arg2);
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Unop.arg);
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Load.addr);
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, e->Iex.CCall.args[i]);
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.GetI.ix);
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("aoccCount_Expr");
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given uses :: array of UShort, indexed by IRTemp
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Add the use-occurrences of temps in this statement
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the env.
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void aoccCount_Stmt ( UShort* uses, IRStmt* st )
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.AbiHint.base);
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.AbiHint.nia);
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.WrTmp.data);
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Put.data);
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.PutI.ix);
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.PutI.data);
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Store.addr);
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Store.data);
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->addr);
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->expdHi)
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, cas->expdHi);
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->expdLo);
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->dataHi)
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, cas->dataHi);
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->dataLo);
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.LLSC.addr);
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, st->Ist.LLSC.storedata);
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mFx != Ifx_None)
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, d->mAddr);
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, d->guard);
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i]; i++)
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, d->args[i]);
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Exit.guard);
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("aoccCount_Stmt");
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up a binding for tmp in the env.  If found, return the bound
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, and set the env's binding to NULL so it is marked as
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used.  If not found, return NULL. */
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* atbSubst_Temp ( ATmpInfo* env, IRTemp tmp )
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[i].binder == tmp && env[i].bindee != NULL) {
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* bindee = env[i].bindee;
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[i].bindee = NULL;
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return bindee;
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Traverse e, looking for temps.  For each observed temp, see if env
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   contains a binding for the temp, and if so return the bound value.
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The env has the property that any binding it holds is
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'single-shot', so once a binding is used, it is marked as no longer
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   available, by setting its .bindee field to NULL. */
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool is_Unop ( IRExpr* e, IROp op ) {
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Unop && e->Iex.Unop.op == op;
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool is_Binop ( IRExpr* e, IROp op ) {
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Binop && e->Iex.Binop.op == op;
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_IRExpr_Binop ( IROp op, IRExpr* a1, IRExpr* a2 )
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_Or32:
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Or32( CmpwNEZ32(x), CmpwNEZ32(y) ) --> CmpwNEZ32( Or32( x, y ) )  */
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(a1, Iop_CmpwNEZ32) && is_Unop(a2, Iop_CmpwNEZ32))
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32,
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Binop( Iop_Or32, a1->Iex.Unop.arg,
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     a2->Iex.Unop.arg ) );
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Iop_CmpNE32:
4066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Since X has type Ity_I1 we can simplify:
4067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         CmpNE32(1Uto32(X),0)) ==> X */
4068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(a1, Iop_1Uto32) && isZeroU32(a2))
4069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return a1->Iex.Unop.arg;
4070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
4071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no reduction rule applies */
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop( op, a1, a2 );
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_IRExpr_Unop ( IROp op, IRExpr* aa )
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpwNEZ64:
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64( Or64 ( CmpwNEZ64(x), y ) ) --> CmpwNEZ64( Or64( x, y ) ) */
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Binop(aa, Iop_Or64)
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Binop.arg1, Iop_CmpwNEZ64))
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Iop_CmpwNEZ64,
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Binop(Iop_Or64,
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg1->Iex.Unop.arg,
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg2));
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64( Or64 ( x, CmpwNEZ64(y) ) ) --> CmpwNEZ64( Or64( x, y ) ) */
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Binop(aa, Iop_Or64)
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Binop.arg2, Iop_CmpwNEZ64))
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Iop_CmpwNEZ64,
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Binop(Iop_Or64,
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg1,
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg2->Iex.Unop.arg));
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpNEZ64:
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpNEZ64( Left64(x) ) --> CmpNEZ64(x) */
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left64))
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_CmpNEZ64, aa->Iex.Unop.arg);
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpwNEZ32:
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ32( CmpwNEZ32 ( x ) ) --> CmpwNEZ32 ( x ) */
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ32))
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32, aa->Iex.Unop.arg );
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpNEZ32:
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpNEZ32( Left32(x) ) --> CmpNEZ32(x) */
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left32))
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_CmpNEZ32, aa->Iex.Unop.arg);
4114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* CmpNEZ32( 1Uto32(X) ) --> X */
4115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(aa, Iop_1Uto32))
4116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return aa->Iex.Unop.arg;
4117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
4118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Iop_CmpNEZ8:
4119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* CmpNEZ8( 1Uto8(X) ) --> X */
4120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(aa, Iop_1Uto8))
4121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return aa->Iex.Unop.arg;
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_Left32:
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Left32( Left32(x) ) --> Left32(x) */
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left32))
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_Left32, aa->Iex.Unop.arg );
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_32to1:
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32to1( 1Uto32 ( x ) ) --> x */
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_1Uto32))
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32to1( CmpwNEZ32 ( x )) --> CmpNEZ32(x) */
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ32))
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpNEZ32, aa->Iex.Unop.arg );
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_64to1:
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to1( 1Uto64 ( x ) ) --> x */
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_1Uto64))
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to1( CmpwNEZ64 ( x )) --> CmpNEZ64(x) */
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ64))
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpNEZ64, aa->Iex.Unop.arg );
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_64to32:
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to32( 32Uto64 ( x )) --> x */
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_32Uto64))
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to32( 8Uto64 ( x )) --> 8Uto32(x) */
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_8Uto64))
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_8Uto32, aa->Iex.Unop.arg);
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_32Uto64:
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64( 8Uto32( x )) --> 8Uto64(x) */
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_8Uto32))
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_8Uto64, aa->Iex.Unop.arg);
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64( 16Uto32( x )) --> 16Uto64(x) */
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_16Uto32))
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_16Uto64, aa->Iex.Unop.arg);
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_1Sto32:
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Sto32( CmpNEZ8( 32to8( 1Uto32( CmpNEZ32( x ))))) -> CmpwNEZ32(x) */
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpNEZ8)
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg, Iop_32to8)
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg, Iop_1Uto32)
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg->Iex.Unop.arg,
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_CmpNEZ32)) {
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32,
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             aa->Iex.Unop.arg->Iex.Unop.arg
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ->Iex.Unop.arg->Iex.Unop.arg);
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no reduction rule applies */
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop( op, aa );
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* atbSubst_Expr ( ATmpInfo* env, IRExpr* e )
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  e2;
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args2;
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         args2 = shallowCopyIRExprVec(e->Iex.CCall.args);
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args2[i]; i++)
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args2[i] = atbSubst_Expr(env,args2[i]);
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_CCall(
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.CCall.cee,
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.CCall.retty,
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   args2
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = atbSubst_Temp(env, e->Iex.RdTmp.tmp);
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e2 ? e2 : e;
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Mux0X(
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Mux0X.cond),
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Mux0X.expr0),
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Mux0X.exprX)
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Qop(
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Qop.op,
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Qop.arg1),
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Qop.arg2),
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Qop.arg3),
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Qop.arg4)
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Triop(
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Triop.op,
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Triop.arg1),
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Triop.arg2),
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Triop.arg3)
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Binop(
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.op,
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Binop.arg1),
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Binop.arg2)
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Unop.op,
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Unop.arg)
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Load(
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Load.end,
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Load.ty,
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Load.addr)
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.descr,
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.GetI.ix),
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.bias
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e;
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("atbSubst_Expr");
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same deal as atbSubst_Expr, except for stmts. */
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty *d, *d2;
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS   *cas, *cas2;
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_AbiHint(
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.AbiHint.base),
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.AbiHint.len,
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.AbiHint.nia)
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Store(
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Store.end,
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Store.addr),
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Store.data)
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_WrTmp(
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.WrTmp.tmp,
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.WrTmp.data)
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Put(
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Put.offset,
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Put.data)
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_PutI(
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.PutI.descr,
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.PutI.ix),
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.PutI.bias,
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.PutI.data)
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Exit(
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Exit.guard),
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Exit.jk,
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Exit.dst
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return IRStmt_IMark(st->Ist.IMark.addr,
4302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.len,
4303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.delta);
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_NoOp();
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_MBE(st->Ist.MBE.event);
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas  = st->Ist.CAS.details;
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS(
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->oldHi, cas->oldLo, cas->end,
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->addr),
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->expdHi ? atbSubst_Expr(env, cas->expdHi) : NULL,
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->expdLo),
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->dataHi ? atbSubst_Expr(env, cas->dataHi) : NULL,
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->dataLo)
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_CAS(cas2);
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_LLSC(
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.end,
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.result,
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.LLSC.addr),
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.storedata
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? atbSubst_Expr(env, st->Ist.LLSC.storedata) : NULL
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d  = st->Ist.Dirty.details;
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None)
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = atbSubst_Expr(env, d2->mAddr);
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = atbSubst_Expr(env, d2->guard);
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++)
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->args[i] = atbSubst_Expr(env, d2->args[i]);
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Dirty(d2);
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("atbSubst_Stmt");
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* notstatic */ void ado_treebuild_BB ( IRSB* bb )
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j, k, m;
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     stmtPuts, stmtStores, invalidateMe;
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st2;
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ATmpInfo env[A_NENV];
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       n_tmps = bb->tyenv->types_used;
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort*   uses   = LibVEX_Alloc(n_tmps * sizeof(UShort));
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Phase 1.  Scan forwards in bb, counting use occurrences of each
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      temp.  Also count occurrences in the bb->next field. */
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uses[i] = 0;
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aoccCount_Stmt( uses, st );
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   aoccCount_Expr(uses, bb->next );
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++) {
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uses[i] == 0)
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        continue;
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRTemp( (IRTemp)i );
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("  used %d\n", (Int)uses[i] );
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Phase 2.  Scan forwards in bb.  For each statement in turn:
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         If the env is full, emit the end element.  This guarantees
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         there is at least one free slot in the following.
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         On seeing 't = E', occ(t)==1,
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let E'=env(E)
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete this stmt
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add t -> E' to the front of the env
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Examine E' and set the hints for E' appropriately
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (doesLoad? doesGet?)
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         On seeing any other stmt,
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let stmt' = env(stmt)
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove from env any 't=E' binds invalidated by stmt
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                emit the invalidated stmts
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit stmt'
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compact any holes in env
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              by sliding entries towards the front
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Finally, apply env to bb->next.
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i].bindee = NULL;
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i].binder = IRTemp_INVALID;
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The stmts in bb are being reordered, and we are guaranteed to
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      end up with no more than the number we started with.  Use i to
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be the cursor of the current stmt examined and j <= i to be that
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for the current stmt being written.
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ensure there's at least one space in the env, by emitting
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the oldest binding if necessary. */
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[A_NENV-1].bindee != NULL) {
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[j] = IRStmt_WrTmp( env[A_NENV-1].binder,
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      env[A_NENV-1].bindee );
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j++;
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(j <= i);
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[A_NENV-1].bindee = NULL;
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Consider current stmt. */
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp && uses[st->Ist.WrTmp.tmp] <= 1) {
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr *e, *e2;
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* optional extra: dump dead bindings as we find them.
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Removes the need for a prior dead-code removal pass. */
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (uses[st->Ist.WrTmp.tmp] == 0) {
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (0) vex_printf("DEAD binding\n");
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(uses[st->Ist.WrTmp.tmp] == 1);
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ok, we have 't = E', occ(t)==1.  Do the abovementioned
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            actions. */
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e  = st->Ist.WrTmp.data;
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = atbSubst_Expr(env, e);
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToEnvFront(env, st->Ist.WrTmp.tmp, e2);
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(&env[0].doesLoad, &env[0].doesGet, e2);
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* don't advance j, as we are deleting this stmt and instead
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            holding it temporarily in the env. */
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we get here for any other kind of statement. */
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 'use up' any bindings required by the current statement. */
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = atbSubst_Stmt(env, st);
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, before this stmt, dump any bindings in env that it
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidates.  These need to be dumped in the order in which
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         they originally entered env -- that means from oldest to
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         youngest. */
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* stmtPuts/stmtStores characterise what the stmt under
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consideration does, or might do (sidely safe @ True). */
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmtPuts
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toBool( st->tag == Ist_Put
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_PutI
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_Dirty );
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be True if this stmt writes memory or might do (==> we don't
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         want to reorder other loads or stores relative to it).  Also,
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         both LL and SC fall under this classification, since we
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         really ought to be conservative and not reorder any other
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memory transactions relative to them. */
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmtStores
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toBool( st->tag == Ist_Store
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_Dirty
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_LLSC );
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = A_NENV-1; k >= 0; k--) {
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[k].bindee == NULL)
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compare the actions of this stmt with the actions of
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binding 'k', to see if they invalidate the binding. */
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidateMe
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = toBool(
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a store invalidates loaded data */
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (env[k].doesLoad && stmtStores)
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a put invalidates get'd data */
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || (env[k].doesGet && stmtPuts)
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a put invalidates loaded data.  Note, we could do
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 much better here in the sense that we only need to
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 invalidate trees containing loads if the Put in
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 question is marked as requiring precise
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 exceptions. */
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || (env[k].doesLoad && stmtPuts)
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* probably overly conservative: a memory bus event
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 invalidates absolutely everything, so that all
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 computation prior to it is forced to complete before
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 proceeding with the event (fence,lock,unlock). */
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || st->tag == Ist_MBE
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* also be (probably overly) paranoid re AbiHints */
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || st->tag == Ist_AbiHint
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (invalidateMe) {
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[j] = IRStmt_WrTmp( env[k].binder, env[k].bindee );
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            j++;
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(j <= i);
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env[k].bindee = NULL;
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Slide in-use entries in env up to the front */
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      m = 0;
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = 0; k < A_NENV; k++) {
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[k].bindee != NULL) {
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env[m] = env[k];
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            m++;
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (m = m; m < A_NENV; m++) {
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[m].bindee = NULL;
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* finally, emit the substituted statement */
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->stmts[j] = st2;
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("**2  "); ppIRStmt(bb->stmts[j]); vex_printf("\n"); */
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      j++;
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(j <= i+1);
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for each stmt in the original bb ... */
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally ... substitute the ->next field as much as possible, and
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dump any left-over bindings.  Hmm.  Perhaps there should be no
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      left over bindings?  Or any left-over bindings are
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by definition dead? */
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->next = atbSubst_Expr(env, bb->next);
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->stmts_used = j;
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- iropt main                                              ---*/
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool iropt_verbose = False; /* True; */
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a simple cleanup pass on bb.  This is: redundant Get removal,
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant Put removal, constant propagation, dead code removal,
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clean helper specialisation, and dead code removal (again).
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cheap_transformations (
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb,
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* (*specHelper) (HChar*, IRExpr**, IRStmt**, Int),
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool (*preciseMemExnsFn)(Int,Int)
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant_get_removal_BB ( bb );
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= REDUNDANT GET\n\n" );
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant_put_removal_BB ( bb, preciseMemExnsFn );
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= REDUNDANT PUT\n\n" );
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = cprop_BB ( bb );
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= CPROPD\n\n" );
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB ( bb );
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= DEAD\n\n" );
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = spec_helpers_BB ( bb, specHelper );
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB ( bb );
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= SPECd \n\n" );
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do some more expensive transformations on bb, which are aimed at
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimising as much as possible in the presence of GetI and PutI.  */
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* expensive_transformations( IRSB* bb )
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (void)do_cse_BB( bb );
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   collapse_AddSub_chains_BB( bb );
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_redundant_GetI_elimination( bb );
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_redundant_PutI_elimination( bb );
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB( bb );
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan a flattened BB to look for signs that more expensive
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisations might be useful:
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - find out if there are any GetIs and PutIs
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - find out if there are any floating or vector-typed temporaries
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void considerExpensives ( /*OUT*/Bool* hasGetIorPutI,
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/Bool* hasVorFtemps,
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRSB* bb )
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j;
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *hasGetIorPutI = False;
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *hasVorFtemps  = False;
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_AbiHint:
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.AbiHint.base));
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.AbiHint.nia));
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *hasGetIorPutI = True;
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp:
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.WrTmp.data->tag == Iex_GetI)
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *hasGetIorPutI = True;
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp)) {
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I1: case Ity_I8: case Ity_I16:
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I32: case Ity_I64: case Ity_I128:
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
4643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case Ity_F32: case Ity_F64: case Ity_F128: case Ity_V128:
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *hasVorFtemps = True;
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  goto bad;
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Put.data));
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Store:
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Store.addr));
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Store.data));
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS:
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cas = st->Ist.CAS.details;
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->addr));
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->expdLo));
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->dataLo));
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC:
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.LLSC.addr));
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.LLSC.storedata)
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(st->Ist.LLSC.storedata));
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty:
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d = st->Ist.Dirty.details;
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d->guard));
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = 0; d->args[j]; j++)
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(d->args[j]));
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->mFx != Ifx_None)
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(d->mAddr));
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp:
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_IMark:
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_MBE:
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Exit:
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Exit.guard));
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bad:
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("considerExpensives");
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- The main iropt entry point. ---------------- */
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* exported from this file */
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Rules of the game:
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - IRExpr/IRStmt trees should be treated as immutable, as they
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     may get shared.  So never change a field of such a tree node;
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     instead construct and return a new one if needed.
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* do_iropt_BB(
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb0,
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* (*specHelper) (HChar*, IRExpr**, IRStmt**, Int),
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool (*preciseMemExnsFn)(Int,Int),
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr64 guest_addr,
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VexArch guest_arch
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_total     = 0;
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_expensive = 0;
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool hasGetIorPutI, hasVorFtemps;
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB *bb, *bb2;
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_total++;
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First flatten the block out, since all other
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      phases assume flat code. */
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = flatten_BB ( bb0 );
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= FLAT\n\n" );
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If at level 0, stop now. */
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_level <= 0) return bb;
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now do a preliminary cleanup pass, and figure out if we also
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need to do 'expensive' optimisations.  Expensive optimisations
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are deemed necessary if the block contains any GetIs or PutIs.
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If needed, do expensive transformations and then another cheap
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cleanup pass. */
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guest_arch == VexArchARM) {
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Translating Thumb2 code produces a lot of chaff.  We have to
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         work extra hard to get rid of it. */
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = cprop_BB(bb);
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = spec_helpers_BB ( bb, specHelper );
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      redundant_put_removal_BB ( bb, preciseMemExnsFn );
4748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      do_cse_BB( bb );
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_deadcode_BB( bb );
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_level > 1) {
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Peer at what we have, to decide how much more effort to throw
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at it. */
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      considerExpensives( &hasGetIorPutI, &hasVorFtemps, bb );
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (hasVorFtemps && !hasGetIorPutI) {
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If any evidence of FP or Vector activity, CSE, as that
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tends to mop up all manner of lardy code to do with
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rounding modes.  Don't bother if hasGetIorPutI since that
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case leads into the expensive transformations, which do
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CSE anyway. */
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void)do_cse_BB( bb );
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_deadcode_BB( bb );
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (hasGetIorPutI) {
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool cses;
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_expensive++;
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT)
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive);
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = expensive_transformations( bb );
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Potentially common up GetIs */
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cses = do_cse_BB( bb );
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cses)
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now have a go at unrolling simple (single-BB) loops.  If
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         successful, clean up the results as much as possible. */
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb2 = maybe_loop_unroll_BB( bb, guest_addr );
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb2) {
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn );
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (hasGetIorPutI) {
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = expensive_transformations( bb );
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* at least do CSE and dead code removal */
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_cse_BB( bb );
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_deadcode_BB( bb );
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) vex_printf("vex iropt: unrolled a loop\n");
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                            ir_opt.c ---*/
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4807