1663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* -*- mode: C; c-basic-offset: 3; -*- */
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                          ir_opt.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 OpenWorks LLP
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ir_opt.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set to 1 for lots of debugging output. */
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEBUG_IROPT 0
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Set to 1 to gather some statistics. Currently only for sameIRExprs. */
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define STATS_IROPT 0
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* What iropt does, 29 Dec 04.
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It takes an IRSB and produces a new one with the same meaning,
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined thus:
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   After execution of the new BB, all guest state and guest memory is
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same as after execution of the original.  This is true
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   regardless of how the block was exited (at the end vs side exit).
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In addition, parts of the guest state will be identical to that
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   created by execution of the original at the following observation
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   points:
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * In a dirty helper call, any parts of the guest state that the
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     helper states that it reads or modifies will be up to date.
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Also, guest memory will be up to date.  Parts of the guest state
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     not marked as being read or modified by the helper cannot be
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assumed to be up-to-date at the point where the helper is called.
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   * If iropt_register_updates == VexRegUpdUnwindregsAtMemAccess :
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Immediately prior to any load or store, those parts of the guest
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     state marked as requiring precise exceptions will be up to date.
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Also, guest memory will be up to date.  Parts of the guest state
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     not marked as requiring precise exceptions cannot be assumed to
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     be up-to-date at the point of the load/store.
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     If iropt_register_updates == VexRegUpdAllregsAtMemAccess:
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Same as minimal, but all the guest state is up to date at memory
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     exception points.
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     If iropt_register_updates == VexRegUpdAllregsAtEachInsn :
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Guest state is up to date at each instruction.
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The relative order of loads and stores (including loads/stores of
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest memory done by dirty helpers annotated as such) is not
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   changed.  However, the relative order of loads with no intervening
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stores/modifies may be changed.
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Transformation order
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ~~~~~~~~~~~~~~~~~~~~
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There are three levels of optimisation, controlled by
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_control.iropt_level.  Define first:
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Cheap transformations" are the following sequence:
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-Get removal
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-Put removal
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Constant propagation/folding
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Specialisation of clean helper functions
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Expensive transformations" are the following sequence:
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * CSE
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Folding of add/sub chains
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-GetI removal
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-PutI removal
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Then the transformations are as follows, as defined by
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_control.iropt_level:
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 0:
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 1: the following sequence:
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Cheap transformations.
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 2: the following sequence
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Cheap transformations.
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If block contains any floating or vector types, CSE.
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If block contains GetI or PutI, Expensive transformations.
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Try unrolling loops.  Three possible outcomes:
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - No effect: do nothing more.
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - Unrolled a loop, and block does not contain GetI or PutI:
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Do: * CSE
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              * Dead code removal
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - Unrolled a loop, and block contains GetI or PutI:
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Do: * Expensive transformations
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              * Cheap transformations
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Implementation notes, 29 Dec 04.
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO (important): I think rPutI removal ignores precise exceptions
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and is therefore in a sense, wrong.  In the sense that PutIs are
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assumed not to write parts of the guest state that we need to have
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   up-to-date at loads/stores.  So far on x86 guest that has not
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mattered since indeed only the x87 FP registers and tags are
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accessed using GetI/PutI, and there is no need so far for them to
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be up to date at mem exception points.  The rPutI pass should be
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fixed.
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: improve pessimistic handling of precise exceptions
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     in the tree builder.
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: check interaction of rGetI and dirty helpers.
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F64i constants are treated differently from other constants.
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   They are not regarded as atoms, and instead lifted off and
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bound to temps.  This allows them to participate in CSE, which
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is important for getting good performance for x86 guest code.
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CSE up F64 literals (already doing F64is)
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CSE: consider carefully the requirement for precise exns
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        prior to making CSE any more aggressive.  */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Finite mappery, of a sort                               ---*/
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* General map from HWord-sized thing HWord-sized thing.  Could be by
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hashing, but it's not clear whether or not this would really be any
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   faster. */
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool*  inuse;
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* key;
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* val;
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    size;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    used;
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW;
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HashHW* newHHW ( void )
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* h = LibVEX_Alloc(sizeof(HashHW));
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->size   = 8;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->used   = 0;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->inuse  = LibVEX_Alloc(h->size * sizeof(Bool));
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->key    = LibVEX_Alloc(h->size * sizeof(HWord));
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->val    = LibVEX_Alloc(h->size * sizeof(HWord));
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return h;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up key in the map. */
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool lookupHHW ( HashHW* h, /*OUT*/HWord* val, HWord key )
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("lookupHHW(%llx)\n", key ); */
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < h->used; i++) {
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h->inuse[i] && h->key[i] == key) {
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (val)
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *val = h->val[i];
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add key->val to the map.  Replaces any existing binding for key. */
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addToHHW ( HashHW* h, HWord key, HWord val )
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i, j;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("addToHHW(%llx, %llx)\n", key, val); */
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Find and replace existing binding, if any. */
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < h->used; i++) {
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h->inuse[i] && h->key[i] == key) {
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h->val[i] = val;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ensure a space is available. */
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (h->used == h->size) {
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Copy into arrays twice the size. */
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool*  inuse2 = LibVEX_Alloc(2 * h->size * sizeof(Bool));
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* key2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* val2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = j = 0; i < h->size; i++) {
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!h->inuse[i]) continue;
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         inuse2[j] = True;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         key2[j] = h->key[i];
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val2[j] = h->val[i];
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j++;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->used = j;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->size *= 2;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->inuse = inuse2;
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->key = key2;
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->val = val2;
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, add it. */
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(h->used < h->size);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->inuse[h->used] = True;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->key[h->used] = key;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->val[h->used] = val;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->used++;
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Flattening out a BB into atomic SSA form                ---*/
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Non-critical helper, heuristic for reducing the number of tmp-tmp
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   copies made by flattening.  If in doubt return False. */
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isFlat ( IRExpr* e )
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get)
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop)
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( isIRAtom(e->Iex.Binop.arg1)
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     && isIRAtom(e->Iex.Binop.arg2) );
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load)
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return isIRAtom(e->Iex.Load.addr);
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Flatten out 'ex' so it is atomic, returning a new expression with
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same value, after having appended extra IRTemp assignments to
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the end of 'bb'. */
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* flatten_Expr ( IRSB* bb, IRExpr* ex )
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** newargs;
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(bb->tyenv, ex);
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ex->tag) {
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_GetI(ex->Iex.GetI.descr,
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.GetI.ix),
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ex->Iex.GetI.bias)));
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb,
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRStmt_WrTmp(t1, ex));
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Qop: {
302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRQop* qop = ex->Iex.Qop.details;
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr_Qop(qop->op,
306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg1),
307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg2),
308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg3),
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg4))));
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Triop: {
314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop* triop = ex->Iex.Triop.details;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr_Triop(triop->op,
318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, triop->arg1),
319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, triop->arg2),
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, triop->arg3))));
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Binop(ex->Iex.Binop.op,
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Binop.arg1),
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Binop.arg2))));
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Unop(ex->Iex.Unop.op,
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.Unop.arg))));
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Load(ex->Iex.Load.end,
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ex->Iex.Load.ty,
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.Load.addr))));
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         newargs = shallowCopyIRExprVec(ex->Iex.CCall.args);
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; newargs[i]; i++)
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            newargs[i] = flatten_Expr(bb, newargs[i]);
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_CCall(ex->Iex.CCall.cee,
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ex->Iex.CCall.retty,
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         newargs)));
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X(flatten_Expr(bb, ex->Iex.Mux0X.cond),
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Mux0X.expr0),
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Mux0X.exprX))));
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Lift F64i constants out onto temps so they can be CSEd
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            later. */
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ex->Iex.Const.con->tag == Ico_F64i) {
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t1 = newIRTemp(bb->tyenv, ty);
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_WrTmp(t1,
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Const(ex->Iex.Const.con)));
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return IRExpr_RdTmp(t1);
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Leave all other constants alone. */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ex;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ex;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ex);
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("flatten_Expr");
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Append a completely flattened form of 'st' to the end of 'bb'. */
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flatten_Stmt ( IRSB* bb, IRStmt* st )
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr  *e1, *e2, *e3, *e4, *e5;
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty *d,  *d2;
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS   *cas, *cas2;
399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI  *puti, *puti2;
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isIRAtom(st->Ist.Put.data)) {
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* optimisation to reduce the amount of heap wasted
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               by the flattener */
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, st);
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* general case, always correct */
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e1 = flatten_Expr(bb, st->Ist.Put.data);
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti = st->Ist.PutI.details;
414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         e1 = flatten_Expr(bb, puti->ix);
415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         e2 = flatten_Expr(bb, puti->data);
416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti2 = mkIRPutI(puti->descr, e1, puti->bias, e2);
417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addStmtToIRSB(bb, IRStmt_PutI(puti2));
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isFlat(st->Ist.WrTmp.data)) {
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* optimisation, to reduce the number of tmp-tmp
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               copies generated */
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, st);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* general case, always correct */
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e1 = flatten_Expr(bb, st->Ist.WrTmp.data);
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_WrTmp(st->Ist.WrTmp.tmp, e1));
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.Store.addr);
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.Store.data);
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Store(st->Ist.Store.end, e1,e2));
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas  = st->Ist.CAS.details;
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1   = flatten_Expr(bb, cas->addr);
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2   = cas->expdHi ? flatten_Expr(bb, cas->expdHi) : NULL;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e3   = flatten_Expr(bb, cas->expdLo);
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e4   = cas->dataHi ? flatten_Expr(bb, cas->dataHi) : NULL;
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e5   = flatten_Expr(bb, cas->dataLo);
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS( cas->oldHi, cas->oldLo, cas->end,
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         e1, e2, e3, e4, e5 );
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_CAS(cas2));
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.LLSC.addr);
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = st->Ist.LLSC.storedata
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ? flatten_Expr(bb, st->Ist.LLSC.storedata)
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 : NULL;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_LLSC(st->Ist.LLSC.end,
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       st->Ist.LLSC.result, e1, e2));
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->args = shallowCopyIRExprVec(d2->args);
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None) {
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = flatten_Expr(bb, d2->mAddr);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(d2->mAddr == NULL);
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = flatten_Expr(bb, d2->guard);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++)
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->args[i] = flatten_Expr(bb, d2->args[i]);
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Dirty(d2));
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.AbiHint.base);
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.AbiHint.nia);
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len, e2));
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.Exit.guard);
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Exit(e1, st->Ist.Exit.jk,
482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       st->Ist.Exit.dst,
483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       st->Ist.Exit.offsIP));
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("flatten_Stmt");
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* flatten_BB ( IRSB* in )
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   i;
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB* out;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out = emptyIRSB();
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < in->stmts_used; i++)
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (in->stmts[i])
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         flatten_Stmt( out, in->stmts[i] );
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->next     = flatten_Expr( out, in->next );
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->jumpkind = in->jumpkind;
505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   out->offsIP   = in->offsIP;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return out;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- In-place removal of redundant GETs                      ---*/
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan forwards, building up an environment binding (min offset, max
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset) pairs to values, which will either be temps or constants.
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 't = Get(minoff,maxoff)', look up (minoff,maxoff) in the
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env and if it matches, replace the Get with the stored value.  If
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there is no match, add a (minoff,maxoff) :-> t binding.
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Put (minoff,maxoff) = t or c', first remove in the env
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   any binding which fully or partially overlaps with (minoff,maxoff).
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Then add a new (minoff,maxoff) :-> t or c binding.  */
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract the min/max offsets from a guest state array descriptor. */
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void getArrayBounds ( IRRegArray* descr,
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UInt* minoff, UInt* maxoff )
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *minoff = descr->base;
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *maxoff = *minoff + descr->nElems*sizeofIRType(descr->elemTy) - 1;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((*minoff & ~0xFFFF) == 0);
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((*maxoff & ~0xFFFF) == 0);
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(*minoff <= *maxoff);
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create keys, of the form ((minoffset << 16) | maxoffset). */
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt mk_key_GetPut ( Int offset, IRType ty )
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* offset should fit in 16 bits. */
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff = offset;
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt maxoff = minoff + sizeofIRType(ty) - 1;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((minoff & ~0xFFFF) == 0);
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((maxoff & ~0xFFFF) == 0);
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (minoff << 16) | maxoff;
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt mk_key_GetIPutI ( IRRegArray* descr )
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff, maxoff;
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr, &minoff, &maxoff );
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((minoff & ~0xFFFF) == 0);
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((maxoff & ~0xFFFF) == 0);
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (minoff << 16) | maxoff;
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Supposing h has keys of the form generated by mk_key_GetPut and
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mk_key_GetIPutI, invalidate any key which overlaps (k_lo
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   .. k_hi).
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void invalidateOverlaps ( HashHW* h, UInt k_lo, UInt k_hi )
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  j;
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt e_lo, e_hi;
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(k_lo <= k_hi);
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* invalidate any env entries which in any way overlap (k_lo
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. k_hi) */
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("invalidate %d .. %d\n", k_lo, k_hi ); */
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < h->used; j++) {
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!h->inuse[j])
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e_lo = (((UInt)h->key[j]) >> 16) & 0xFFFF;
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e_hi = ((UInt)h->key[j]) & 0xFFFF;
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e_lo <= e_hi);
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e_hi < k_lo || k_hi < e_lo)
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* no overlap possible */
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* overlap; invalidate */
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h->inuse[j] = False;
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void redundant_get_removal_BB ( IRSB* bb )
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* env = newHHW();
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord   val;
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRStmt* st = bb->stmts[i];
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Gets */
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_Get) {
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* st is 't = Get(...)'.  Look up in the environment and see
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if the Get can be replaced. */
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* get = st->Ist.WrTmp.data;
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         key = (HWord)mk_key_GetPut( get->Iex.Get.offset,
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     get->Iex.Get.ty );
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (lookupHHW(env, &val, (HWord)key)) {
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* found it */
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note, we could do better here.  If the types are
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               different we don't do the substitution, since doing so
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               could lead to invalidly-typed IR.  An improvement would
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               be to stick in a reinterpret-style cast, although that
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               would make maintaining flatness more difficult. */
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* valE    = (IRExpr*)val;
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool    typesOK = toBool( typeOfIRExpr(bb->tyenv,valE)
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      == st->Ist.WrTmp.data->Iex.Get.ty );
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typesOK && DEBUG_IROPT) {
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rGET: "); ppIRExpr(get);
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("  ->  "); ppIRExpr(valE);
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typesOK)
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, valE);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Not found, but at least we know that t and the Get(...)
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               are now associated.  So add a binding to reflect that
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fact. */
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addToHHW( env, (HWord)key,
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (HWord)(void*)(IRExpr_RdTmp(st->Ist.WrTmp.tmp)) );
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Puts: invalidate any env entries overlapped by this
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Put */
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put || st->tag == Ist_PutI) {
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt k_lo, k_hi;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag == Ist_Put) {
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetPut( st->Ist.Put.offset,
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(st->tag == Ist_PutI);
643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k_lo = (key >> 16) & 0xFFFF;
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k_hi = key & 0xFFFF;
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidateOverlaps(env, k_lo, k_hi);
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty) {
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Deal with dirty helpers which write or modify guest state.
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Invalidate the entire env.  We could do a lot better
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            here. */
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty* d      = st->Ist.Dirty.details;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool     writes = False;
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < d->nFxState; j++) {
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->fxState[j].fx == Ifx_Modify
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || d->fxState[j].fx == Ifx_Write)
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            writes = True;
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (writes) {
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* dump the entire env (not clever, but correct ...) */
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = 0; j < env->used; j++)
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               env->inuse[j] = False;
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) vex_printf("rGET: trash env due to dirty helper\n");
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add this one to the env, if appropriate */
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put) {
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Put.data));
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( env, (HWord)key, (HWord)(st->Ist.Put.data));
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for (i = 0; i < bb->stmts_used; i++) */
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- In-place removal of redundant PUTs                      ---*/
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find any Get uses in st and invalidate any partially or fully
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlapping ranges listed in env.  Due to the flattening phase, the
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only stmt kind we expect to find a Get on is IRStmt_WrTmp. */
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_gets_Stmt (
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HashHW* env,
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRStmt* st,
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool (*preciseMemExnsFn)(Int,Int)
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     j;
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isGet;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    memRW = False;
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the only interesting case.  Deal with Gets in the RHS
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expression. */
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e = st->Ist.WrTmp.data;
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->tag) {
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Get:
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = True;
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               key = mk_key_GetPut ( e->Iex.Get.offset, e->Iex.Get.ty );
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_GetI:
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = True;
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               key = mk_key_GetIPutI ( e->Iex.GetI.descr );
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Load:
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = False;
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               memRW = True;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = False;
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isGet) {
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt k_lo, k_hi;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k_lo = (key >> 16) & 0xFFFF;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k_hi = key & 0xFFFF;
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalidateOverlaps(env, k_lo, k_hi);
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Be very conservative for dirty helper calls; dump the entire
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         environment.  The helper might read guest state, in which
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case it needs to be flushed first.  Also, the helper might
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         access guest memory, in which case all parts of the guest
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state requiring precise exceptions needs to be flushed.  The
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         crude solution is just to flush everything; we could easily
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         enough do a lot better if needed. */
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Probably also overly-conservative, but also dump everything
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if we hit a memory bus event (fence, lock, unlock).  Ditto
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AbiHints, CASs, LLs and SCs. */
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.base));
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.nia));
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < env->used; j++)
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* all other cases are boring. */
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.addr));
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.data));
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memRW = True;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(st->Ist.PutI.details->ix));
766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(st->Ist.PutI.details->data));
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("handle_gets_Stmt");
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (memRW) {
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This statement accesses memory.  So we need to dump all parts
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the environment corresponding to guest state that may not
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be reordered with respect to memory references.  That means
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at least the stack pointer. */
785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (vex_control.iropt_register_updates) {
786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case VexRegUpdAllregsAtMemAccess:
787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Precise exceptions required at mem access.
788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Flush all guest state. */
789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (j = 0; j < env->used; j++)
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               env->inuse[j] = False;
791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case VexRegUpdUnwindregsAtMemAccess:
793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (j = 0; j < env->used; j++) {
794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (!env->inuse[j])
795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  continue;
796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Just flush the minimal amount required, as computed by
797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  preciseMemExnsFn. */
798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               HWord k_hi = env->key[j] & 0xFFFF;
800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (preciseMemExnsFn( k_lo, k_hi ))
801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  env->inuse[j] = False;
802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            // VexRegUpdAllregsAtEachInsn cannot happen here.
806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            // Neither any rubbish other value.
807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(0);
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (memRW) */
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan backwards, building up a set of (min offset, max
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset) pairs, indicating those parts of the guest state
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for which the next event is a write.
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing a conditional exit, empty the set.
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Put (minoff,maxoff) = t or c', if (minoff,maxoff) is
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   completely within the set, remove the Put.  Otherwise, add
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (minoff,maxoff) to the set.
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Get (minoff,maxoff)', remove any part of the set
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlapping (minoff,maxoff).  The same has to happen for any events
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which implicitly read parts of the guest state: dirty helper calls
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and loads/stores.
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void redundant_put_removal_BB (
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRSB* bb,
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool (*preciseMemExnsFn)(Int,Int)
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j;
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isPut;
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert
841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (vex_control.iropt_register_updates == VexRegUpdUnwindregsAtMemAccess
842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || vex_control.iropt_register_updates == VexRegUpdAllregsAtMemAccess);
843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* env = newHHW();
845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Initialise the running env with the fact that the final exit
847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      writes the IP (or, whatever it claims to write.  We don't
848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      care.) */
849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   key = mk_key_GetPut(bb->offsIP, typeOfIRExpr(bb->tyenv, bb->next));
850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addToHHW(env, (HWord)key, 0);
851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And now scan backwards through the statements. */
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with conditional exits. */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Exit) {
861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //Bool re_add;
862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Need to throw out from the env, any part of it which
863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            doesn't overlap with the guest state written by this exit.
864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Since the exit only writes one section, it's simplest to
865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do this: (1) check whether env contains a write that
866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            completely overlaps the write done by this exit; (2) empty
867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            out env; and (3) if (1) was true, add the write done by
868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            this exit.
869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            To make (1) a bit simpler, merely search for a write that
871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            exactly matches the one done by this exit.  That's safe
872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            because it will fail as often or more often than a full
873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            overlap check, and failure to find an overlapping write in
874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            env is the safe case (we just nuke env if that
875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            happens). */
876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //vassert(isIRAtom(st->Ist.Exit.guard));
877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (1) */
878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //key = mk_key_GetPut(st->Ist.Exit.offsIP,
879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //                    typeOfIRConst(st->Ist.Exit.dst));
880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //re_add = lookupHHW(env, NULL, key);
881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (2) */
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < env->used; j++)
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (3) */
885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //if (0 && re_add)
886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //   addToHHW(env, (HWord)key, 0);
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Puts */
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = True;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetPut( st->Ist.Put.offset,
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Put.data));
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = True;
900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(isIRAtom(st->Ist.PutI.details->ix));
902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(isIRAtom(st->Ist.PutI.details->data));
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = False;
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isPut && st->tag != Ist_PutI) {
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See if any single entry in env overlaps this Put.  This is
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            simplistic in that the transformation is valid if, say, two
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or more entries in the env overlap this Put, but the use of
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lookupHHW will only find a single entry which exactly
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            overlaps this Put.  This is suboptimal but safe. */
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (lookupHHW(env, NULL, (HWord)key)) {
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This Put is redundant because a later one will overwrite
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               it.  So NULL (nop) it out. */
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rPUT: "); ppIRStmt(st);
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i] = IRStmt_NoOp();
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We can't demonstrate that this Put is redundant, so add it
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to the running collection. */
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addToHHW(env, (HWord)key, 0);
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Gets.  These remove bits of the environment since
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         appearance of a Get means that the next event for that slice
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the guest state is no longer a write, but a read.  Also
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deals with implicit reads of guest state needed to maintain
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         precise exceptions. */
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      handle_gets_Stmt( env, st, preciseMemExnsFn );
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constant propagation and folding                        ---*/
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often sameIRExprs was invoked */
945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt invocation_count;
946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often sameIRExprs recursed through IRTemp assignments */
947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt recursion_count;
948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often sameIRExprs found identical IRExprs */
949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt success_count;
950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often recursing through assignments to IRTemps helped
951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   establishing equality. */
952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt recursion_success_count;
953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Whether or not recursing through an IRTemp assignment helped
954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   establishing IRExpr equality for a given sameIRExprs invocation. */
955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool recursion_helped;
956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Whether or not a given sameIRExprs invocation recursed through an
957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp assignment */
958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool recursed;
959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Maximum number of nodes ever visited when comparing two IRExprs. */
960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt max_nodes_visited;
961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif /* STATS_IROPT */
962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Count the number of nodes visited for a given sameIRExprs invocation. */
964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt num_nodes_visited;
965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Do not visit more than NODE_LIMIT nodes when comparing two IRExprs.
967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This is to guard against performance degradation by visiting large
968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   trees without success. */
969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define NODE_LIMIT 30
970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The env in this section is a map from IRTemp to IRExpr*,
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is, an array indexed by IRTemp. */
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Do both expressions compute the same value? The answer is generally
976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   conservative, i.e. it will report that the expressions do not compute
977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the same value when in fact they do. The reason is that we do not
978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   keep track of changes in the guest state and memory. Thusly, two
979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Get's, GetI's or Load's, even when accessing the same location, will be
980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assumed to compute different values. After all the accesses may happen
981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at different times and the guest state / memory can have changed in
982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the meantime.
983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   XXX IMPORTANT XXX the two expressions must have the same IR type.
985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DO NOT CALL HERE WITH DIFFERENTLY-TYPED EXPRESSIONS. */
986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* JRS 20-Mar-2012: split sameIRExprs_aux into a fast inlineable
988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   wrapper that deals with the common tags-don't-match case, and a
989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   slower out of line general case.  Saves a few insns. */
990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs_aux2 ( IRExpr** env, IRExpr* e1, IRExpr* e2 );
993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenginline
995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs_aux ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e1->tag != e2->tag) return False;
998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return sameIRExprs_aux2(env, e1, e2);
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
1002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs_aux2 ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (num_nodes_visited++ > NODE_LIMIT) return False;
1005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e1->tag) {
1007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_RdTmp:
1008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp) return True;
1009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env[e1->Iex.RdTmp.tmp] && env[e2->Iex.RdTmp.tmp]) {
1011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool same = sameIRExprs_aux(env, env[e1->Iex.RdTmp.tmp],
1012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        env[e2->Iex.RdTmp.tmp]);
1013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
1014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            recursed = True;
1015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (same) recursion_helped = True;
1016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
1017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return same;
1018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
1020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Get:
1022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_GetI:
1023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Load:
1024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Guest state / memory could have changed in the meantime. */
1025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
1026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Binop:
1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool( e1->Iex.Binop.op == e2->Iex.Binop.op
1029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Binop.arg1,
1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Binop.arg1 )
1031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Binop.arg2,
1032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Binop.arg2 ));
1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Unop:
1035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool( e1->Iex.Unop.op == e2->Iex.Unop.op
1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Unop.arg,
1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Unop.arg ));
1038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Const: {
1040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c1 = e1->Iex.Const.con;
1041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c2 = e2->Iex.Const.con;
1042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(c1->tag == c2->tag);
1043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (c1->tag) {
1044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U1:   return toBool( c1->Ico.U1  == c2->Ico.U1 );
1045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U8:   return toBool( c1->Ico.U8  == c2->Ico.U8 );
1046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U16:  return toBool( c1->Ico.U16 == c2->Ico.U16 );
1047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U32:  return toBool( c1->Ico.U32 == c2->Ico.U32 );
1048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U64:  return toBool( c1->Ico.U64 == c2->Ico.U64 );
1049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: break;
1050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
1052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Triop: {
1055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop *tri1 = e1->Iex.Triop.details;
1056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop *tri2 = e2->Iex.Triop.details;
1057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool( tri1->op == tri2->op
1058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, tri1->arg1, tri2->arg1 )
1059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, tri1->arg2, tri2->arg2 )
1060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, tri1->arg3, tri2->arg3 ));
1061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Mux0X:
1064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool(    sameIRExprs_aux( env, e1->Iex.Mux0X.cond,
1065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Mux0X.cond )
1066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Mux0X.expr0,
1067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Mux0X.expr0 )
1068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Mux0X.exprX,
1069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Mux0X.exprX ));
1070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
1072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Not very likely to be "same". */
1073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
1074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return False;
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenginline
1080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool same;
1083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   num_nodes_visited = 0;
1085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   same = sameIRExprs_aux(env, e1, e2);
1086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
1088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ++invocation_count;
1089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (recursed) ++recursion_count;
1090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   success_count += same;
1091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (same && recursion_helped)
1092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ++recursion_success_count;
1093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (num_nodes_visited > max_nodes_visited)
1094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      max_nodes_visited = num_nodes_visited;
1095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   recursed = False; /* reset */
1096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   recursion_helped = False;  /* reset */
1097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif /* STATS_IROPT */
1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return same;
1100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Debugging-only hack (not used in production runs): make a guess
1104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   whether sameIRExprs might assert due to the two args being of
1105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   different types.  If in doubt return False.  Is only used when
1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   --vex-iropt-level > 0, that is, vex_control.iropt_verbosity > 0.
1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bad because it duplicates functionality from typeOfIRExpr.  See
1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   comment on the single use point below for rationale. */
1109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
1110663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengBool debug_only_hack_sameIRExprs_might_assert ( IRExpr* e1, IRExpr* e2 )
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e1->tag != e2->tag) return False;
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e1->tag) {
1114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Const: {
1115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* The only interesting case */
1116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c1 = e1->Iex.Const.con;
1117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c2 = e2->Iex.Const.con;
1118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return c1->tag != c2->tag;
1119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return False;
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Is this literally IRExpr_Const(IRConst_U32(0)) ? */
1128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool isZeroU32 ( IRExpr* e )
1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toBool( e->tag == Iex_Const
1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->tag == Ico_U32
1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->Ico.U32 == 0);
1133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Is this literally IRExpr_Const(IRConst_U32(1---1)) ? */
1136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool isOnesU32 ( IRExpr* e )
1137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return toBool( e->tag == Iex_Const
1139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  && e->Iex.Const.con->tag == Ico_U32
1140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  && e->Iex.Const.con->Ico.U32 == 0xFFFFFFFF );
1141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Is this literally IRExpr_Const(IRConst_U64(0)) ? */
1144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool isZeroU64 ( IRExpr* e )
1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toBool( e->tag == Iex_Const
1147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->tag == Ico_U64
1148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->Ico.U64 == 0);
1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Is this an integer constant with value 0 ? */
1152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool isZeroU ( IRExpr* e )
1153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag != Iex_Const) return False;
1155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->Iex.Const.con->tag) {
1156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U1:    return toBool( e->Iex.Const.con->Ico.U1  == 0);
1157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U8:    return toBool( e->Iex.Const.con->Ico.U8  == 0);
1158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U16:   return toBool( e->Iex.Const.con->Ico.U16 == 0);
1159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U32:   return toBool( e->Iex.Const.con->Ico.U32 == 0);
1160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U64:   return toBool( e->Iex.Const.con->Ico.U64 == 0);
1161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vpanic("isZeroU");
1162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Is this an integer constant with value 1---1b ? */
1166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool isOnesU ( IRExpr* e )
1167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag != Iex_Const) return False;
1169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->Iex.Const.con->tag) {
1170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U8:    return toBool( e->Iex.Const.con->Ico.U8  == 0xFF);
1171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U16:   return toBool( e->Iex.Const.con->Ico.U16 == 0xFFFF);
1172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U32:   return toBool( e->Iex.Const.con->Ico.U32
1173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     == 0xFFFFFFFF);
1174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U64:   return toBool( e->Iex.Const.con->Ico.U64
1175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     == 0xFFFFFFFFFFFFFFFFULL);
1176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: ppIRExpr(e); vpanic("isOnesU");
1177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool notBool ( Bool b )
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b == True) return False;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b == False) return True;
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("notBool");
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a zero which has the same type as the result of the given
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   primop. */
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkZeroOfPrimopResultType ( IROp op )
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpNE32: return IRExpr_Const(IRConst_U1(toBool(0)));
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8:  return IRExpr_Const(IRConst_U8(0));
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32:
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64:
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128: return IRExpr_Const(IRConst_V128(0));
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("mkZeroOfPrimopResultType: bad primop");
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a value containing all 1-bits, which has the same type as the
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result of the given primop. */
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkOnesOfPrimopResultType ( IROp op )
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpEQ32:
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_U1(toBool(1)));
1212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or8:
1213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_Const(IRConst_U8(0xFF));
1214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or16:
1215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_Const(IRConst_U16(0xFFFF));
1216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or32:
1217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_Const(IRConst_U32(0xFFFFFFFF));
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x8:
1219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or64:
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_U64(0xFFFFFFFFFFFFFFFFULL));
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:
1222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpEQ16x8:
1223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpEQ32x4:
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_V128(0xFFFF));
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppIROp(op);
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mkOnesOfPrimopResultType: bad primop");
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Helpers for folding Clz32/64. */
1232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt fold_Clz64 ( ULong value )
1233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt i;
1235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(value != 0ULL); /* no defined semantics for arg==0 */
1236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 64; ++i) {
1237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0ULL != (value & (((ULong)1) << (63 - i)))) return i;
1238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(0);
1240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
1241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
1242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt fold_Clz32 ( UInt value )
1245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt i;
1247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(value != 0); /* no defined semantics for arg==0 */
1248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 32; ++i) {
1249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0 != (value & (((UInt)1) << (31 - i)))) return i;
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(0);
1252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
1253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
1254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* V64 holds 8 summary-constant bits in V128/V256 style.  Convert to
1257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the corresponding real constant. */
1258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//XXX re-check this before use
1259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//static ULong de_summarise_V64 ( UChar v64 )
1260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//{
1261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   ULong r = 0;
1262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<0)) r |= 0x00000000000000FFULL;
1263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<1)) r |= 0x000000000000FF00ULL;
1264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<2)) r |= 0x0000000000FF0000ULL;
1265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<3)) r |= 0x00000000FF000000ULL;
1266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<4)) r |= 0x000000FF00000000ULL;
1267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<5)) r |= 0x0000FF0000000000ULL;
1268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<6)) r |= 0x00FF000000000000ULL;
1269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<7)) r |= 0xFF00000000000000ULL;
1270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   return r;
1271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//}
1272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* fold_Expr ( IRExpr** env, IRExpr* e )
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     shift;
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e2 = e; /* e2 is the result of folding e, if possible */
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->tag) {
1279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Unop:
1280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* UNARY ops */
1281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->Iex.Unop.arg->tag == Iex_Const) {
1282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (e->Iex.Unop.op) {
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto8:
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0)));
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto32:
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0));
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto64:
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0));
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto8:
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFF : 0)));
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto16:
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFF : 0)));
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto32:
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFFFFFF : 0));
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto64:
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFFFFFFFFFFFFFFULL : 0));
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto32: {
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 <<= 24;
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 >>= 24;
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32((UInt)s32));
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16Sto32: {
1328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s32 <<= 16;
1330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s32 >>= 16;
1331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U32( (UInt)s32) );
1332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto64:
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto64:
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto32:
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_8Sto16: {
1347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Short s16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s16 <<= 8;
1349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s16 >>= 8;
1350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U16( (UShort)s16) );
1351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_8Uto16:
1354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U16(
1355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto32:
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to16:
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to8:
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to1:
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to1:
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U64)
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_NotV128:
1381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            e2 = IRExpr_Const(IRConst_V128(
1382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.V128)));
1383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not64:
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U64)));
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not32:
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not16:
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U16))));
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not8:
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U8))));
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not1:
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to8: {
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0xFFULL;
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8( (UChar)w64 ));
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to16: {
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0xFFFFULL;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16( (UShort)w64 ));
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to32: {
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0x00000000FFFFFFFFULL;
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64HIto32: {
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 >>= 32;
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Uto64:
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFFFFFFULL
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    & e->Iex.Unop.arg->Iex.Const.con->Ico.U32));
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16Sto64: {
1436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Long s64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s64 <<= 48;
1438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s64 >>= 48;
1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Sto64: {
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* signed */ Long s64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 <<= 32;
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 >>= 32;
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16to8: {
1451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 &= 0xFF;
1453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
1454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16HIto8: {
1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 >>= 8;
1459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 &= 0xFF;
1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ8:
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0 !=
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ32:
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0 !=
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ64:
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ32: {
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt w32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (w32 == 0)
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32( 0 ));
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32( 0xFFFFFFFF ));
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ64: {
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (w64 == 0)
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64( 0 ));
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64( 0xFFFFFFFFFFFFFFFFULL ));
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left32: {
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int  s32 = (Int)(u32 & 0xFFFFFFFF);
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 = (s32 | (-s32));
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const( IRConst_U32( (UInt)s32 ));
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left64: {
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Long  s64 = (Long)u64;
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 = (s64 | (-s64));
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const( IRConst_U64( (ULong)s64 ));
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_Clz32: {
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (u32 != 0)
1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U32(fold_Clz32(u32)));
1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_Clz64: {
1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (u64 != 0ULL)
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U64(fold_Clz64(u64)));
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* For these vector ones, can't fold all cases, but at least
1529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do the most obvious one.  Could do better here using
1530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            summarise/desummarise of vector constants, but too
1531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            difficult to verify; hence just handle the zero cases. */
1532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32UtoV128: {
1533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == u32) {
1535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(0x0000));
1536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V128to64: {
1542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
1543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == ((v128 >> 0) & 0xFF)) {
1544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_U64(0));
1545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V128HIto64: {
1551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
1552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == ((v128 >> 8) & 0xFF)) {
1553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_U64(0));
1554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64UtoV128: {
1560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == u64) {
1562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(0x0000));
1563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Even stupider (although still correct ..) */
1570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V256to64_0: case Iop_V256to64_1:
1571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V256to64_2: case Iop_V256to64_3: {
1572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt v256 = e->Iex.Unop.arg->Iex.Const.con->Ico.V256;
1573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (v256 == 0x00000000) {
1574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_U64(0));
1575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Binop:
1588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* BINARY ops */
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.arg1->tag == Iex_Const
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const) {
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cases where both args are consts */
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Or -- */
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or8:
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or16:
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U16(toUShort(
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or32:
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or64:
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_OrV128:
1616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(
1617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
1618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
1619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Xor -- */
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor8:
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor16:
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U16(toUShort(
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor32:
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor64:
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_XorV128:
1643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(
1644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
1645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
1646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- And -- */
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And8:
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_And16:
1655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U16(toUShort(
1656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And32:
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And64:
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_AndV128:
1670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(
1671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
1672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
1673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Add -- */
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add8:
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add32:
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add64:
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Sub -- */
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub8:
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub32:
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub64:
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Max32U -- */
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Max32U: {
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt res  = u32a > u32b ? u32a : u32b;
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(res));
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Mul -- */
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Mul32:
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Mul64:
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullS32: {
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* very paranoid */
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32a = (Int)u32a;
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32b = (Int)u32b;
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  s64a = (Long)s32a;
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  s64b = (Long)s32b;
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  sres = s64a * s64b;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong ures = (ULong)sres;
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(ures));
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Shl -- */
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl32:
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31)
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32(
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           << shift)));
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl64:
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63)
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64(
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           << shift)));
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Sar -- */
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar32: {
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*signed*/ Int s32;
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               s32   = (Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31) {
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  s32 >>=/*signed*/ shift;
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32((UInt)s32));
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar64: {
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*signed*/ Long s64;
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               s64   = (Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63) {
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  s64 >>=/*signed*/ shift;
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Shr -- */
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr32: {
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*unsigned*/ UInt u32;
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               u32   = (UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31) {
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  u32 >>=/*unsigned*/ shift;
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32(u32));
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr64: {
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*unsigned*/ ULong u64;
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               u64   = (ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63) {
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  u64 >>=/*unsigned*/ shift;
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64(u64));
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpEQ -- */
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ32:
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ64:
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpNE -- */
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE8:
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((0xFF & e->Iex.Binop.arg1->Iex.Const.con->Ico.U8)
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != (0xFF & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8)))));
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE32:
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE64:
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLEU -- */
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLE32U:
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        <= (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLE64U:
1850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        <= (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLES -- */
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLE32S:
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        <= (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLE64S:
1862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        <= (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLTS -- */
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLT32S:
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        < (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLT64S:
1874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        < (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLTU -- */
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLT32U:
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        < (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLT64U:
1886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        < (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpORD -- */
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpORD32S: {
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* very paranoid */
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32a = (Int)u32a;
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32b = (Int)u32b;
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   r = 0x2; /* EQ */
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (s32a < s32b) {
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r = 0x8; /* LT */
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else if (s32a > s32b) {
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r = 0x4; /* GT */
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(r));
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- nHLto2n -- */
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_32HLto64:
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (((ULong)(e->Iex.Binop.arg1
1913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  ->Iex.Const.con->Ico.U32)) << 32)
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       | ((ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ));
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_64HLto128:
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* We can't fold this, because there is no way to
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  express he result in IR, but at least pretend to
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  handle it, so as to stop getting blasted with
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  no-rule-for-this-primop messages. */
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* For this vector one, can't fold all cases, but at
1924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               least do the most obvious one.  Could do better here
1925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               using summarise/desummarise of vector constants, but
1926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               too difficult to verify; hence just handle the zero
1927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               cases. */
1928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_64HLtoV128: {
1929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ULong argHi = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64;
1930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ULong argLo = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64;
1931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (0 == argHi && 0 == argLo) {
1932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Const(IRConst_V128(0));
1933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
1934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  goto unhandled;
1935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
1936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* -- V128 stuff -- */
1940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_InterleaveLO8x16: {
1941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* This turns up a lot in Memcheck instrumentation of
1942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Icc generated code.  I don't know why. */
1943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               UShort arg1 =  e->Iex.Binop.arg1->Iex.Const.con->Ico.V128;
1944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               UShort arg2 =  e->Iex.Binop.arg2->Iex.Const.con->Ico.V128;
1945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (0 == arg1 && 0 == arg2) {
1946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Const(IRConst_V128(0));
1947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
1948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  goto unhandled;
1949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
1950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled;
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* other cases (identities, etc) */
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shl32:
1963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shl64:
1964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shr64:
1965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Shl32/Shl64/Shr64(x,0) ==> x */
1966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
1967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
1968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
1970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Shl32/Shl64/Shr64(0,x) ==> 0 */
1971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg1)) {
1972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
1973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
1975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shr32:
1978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Shr32(x,0) ==> x */
1979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
1980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
1981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
1983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or8:
1986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or16:
1987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or32:
1988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or64:
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Max32U:
1990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(x,0) ==> x */
1991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
1992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
1993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
1995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(0,x) ==> x */
1996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg1)) {
1997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg2;
1998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(x,1---1b) ==> 1---1b */
2001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(1---1b,x) ==> 1---1b */
2002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isOnesU(e->Iex.Binop.arg1) || isOnesU(e->Iex.Binop.arg2)) {
2003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
2004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(t,t) ==> t, for some IRTemp t */
2007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = e->Iex.Binop.arg1;
2009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add8:
2014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add8(t,t) ==> t << 1.
2015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Memcheck doesn't understand that
2016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  x+x produces a defined least significant bit, and it seems
2017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  simplest just to get rid of the problem by rewriting it
2018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  out, since the opportunity to do so exists. */
2019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Binop(Iop_Shl8, e->Iex.Binop.arg1,
2021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    IRExpr_Const(IRConst_U8(1)));
2022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* NB no Add16(t,t) case yet as no known test case exists */
2027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add32:
2029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add64:
2030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add32/Add64(x,0) ==> x */
2031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
2032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add32/Add64(0,x) ==> x */
2036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg1)) {
2037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg2;
2038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add32/Add64(t,t) ==> t << 1. Same rationale as for Add8. */
2041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Binop(
2043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          e->Iex.Binop.op == Iop_Add32 ? Iop_Shl32 : Iop_Shl64,
2044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          e->Iex.Binop.arg1, IRExpr_Const(IRConst_U8(1)));
2045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sub64:
2050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Sub64(x,0) ==> x */
2051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU64(e->Iex.Binop.arg2)) {
2052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Sub64(t,t) ==> 0, for some IRTemp t */
2056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And32:
2063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* And32(x,0xFFFFFFFF) ==> x */
2064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isOnesU32(e->Iex.Binop.arg2)) {
2065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* And32(x,0) ==> 0 */
2069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU32(e->Iex.Binop.arg2)) {
2070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg2;
2071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* And32(0,x) ==> 0 */
2074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU32(e->Iex.Binop.arg1)) {
2075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* And32(t,t) ==> t, for some IRTemp t */
2079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And8:
2086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And16:
2087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And64:
2088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_AndV128:
2089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_AndV256:
2090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* And8/And16/And64/AndV128/AndV256(t,t)
2091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  ==> t, for some IRTemp t */
2092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_OrV128:
2099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_OrV256:
2100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* V128/V256(t,t) ==> t, for some IRTemp t */
2101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor8:
2108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor16:
2109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor32:
2110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor64:
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_XorV128:
2112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Xor8/16/32/64/V128(t,t) ==> 0, for some IRTemp t */
2113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sub32:
2120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpNE32:
2121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Sub32/CmpNE32(t,t) ==> 0, for some IRTemp t */
2122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpEQ32:
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ64:
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8x8:
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8x16:
2132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpEQ16x8:
2133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpEQ32x4:
2134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
2136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
2145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Mux0X:
2147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Mux0X */
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* is the discriminant is a constant? */
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Mux0X.cond->tag == Iex_Const) {
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool zero;
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assured us by the IR type rules */
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(e->Iex.Mux0X.cond->Iex.Const.con->tag == Ico_U8);
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zero = toBool(0 == (0xFF & e->Iex.Mux0X.cond
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     ->Iex.Const.con->Ico.U8));
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = zero ? e->Iex.Mux0X.expr0 : e->Iex.Mux0X.exprX;
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* are the arms identical? (pretty weedy test) */
2160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (sameIRExprs(env, e->Iex.Mux0X.expr0,
2161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      e->Iex.Mux0X.exprX)) {
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = e->Iex.Mux0X.expr0;
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
2165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
2167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* not considered */
2168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Show cases where we've found but not folded 'op(t,t)'.  Be
2172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      careful not to call sameIRExprs with values of different types,
2173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      though, else it will assert (and so it should!).  We can't
2174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      conveniently call typeOfIRExpr on the two args without a whole
2175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bunch of extra plumbing to pass in a type env, so just use a
2176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      hacky test to check the arguments are not anything that might
2177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sameIRExprs to assert.  This is only OK because this kludge is
2178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      only used for debug printing, not for "real" operation.  For
2179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      "real" operation (ie, all other calls to sameIRExprs), it is
2180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      essential that the to args have the same type.
2181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      The "right" solution is to plumb the containing block's
2183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTypeEnv through to here and use typeOfIRExpr to be sure.  But
2184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      that's a bunch of extra parameter passing which will just slow
2185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      down the normal case, for no purpose. */
2186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_control.iropt_verbosity > 0
2187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && e == e2
2188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && e->tag == Iex_Binop
2189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && !debug_only_hack_sameIRExprs_might_assert(e->Iex.Binop.arg1,
2190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                    e->Iex.Binop.arg2)
2191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("vex iropt: fold_Expr: no ident rule for: ");
2193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRExpr(e);
2194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("\n");
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Show the overall results of folding. */
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_IROPT && e2 != e) {
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("FOLD: ");
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e); vex_printf("  ->  ");
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e2); vex_printf("\n");
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e2;
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unhandled:
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n\n");
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("fold_Expr: no rule for the above");
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_verbosity > 0) {
2213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("vex iropt: fold_Expr: no const rule for: ");
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e);
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e2;
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Apply the subst to a simple 1-level expression -- guaranteed to be
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1-level due to previous flattening pass. */
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex )
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ex->tag) {
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[(Int)ex->Iex.RdTmp.tmp] != NULL) {
2230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr *rhs = env[(Int)ex->Iex.RdTmp.tmp];
2231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (rhs->tag == Iex_RdTmp)
2232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return rhs;
2233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (rhs->tag == Iex_Const
2234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                && rhs->Iex.Const.con->tag != Ico_F64i)
2235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return rhs;
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* not bound in env */
2238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return ex;
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ex;
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.GetI.ix));
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ex->Iex.GetI.descr,
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            subst_Expr(env, ex->Iex.GetI.ix),
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ex->Iex.GetI.bias
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Qop: {
2253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRQop* qop = ex->Iex.Qop.details;
2254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg1));
2255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg2));
2256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg3));
2257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg4));
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Qop(
2259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   qop->op,
2260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg1),
2261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg2),
2262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg3),
2263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg4)
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Triop: {
2268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop* triop = ex->Iex.Triop.details;
2269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(triop->arg1));
2270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(triop->arg2));
2271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(triop->arg3));
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Triop(
2273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   triop->op,
2274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, triop->arg1),
2275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, triop->arg2),
2276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, triop->arg3)
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Binop.arg1));
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Binop.arg2));
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop(
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Binop.op,
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Binop.arg1),
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Binop.arg2)
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Unop.arg));
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Unop.op,
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Unop.arg)
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Load.addr));
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Load(
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Load.end,
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Load.ty,
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Load.addr)
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall: {
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int      i;
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args2 = shallowCopyIRExprVec(ex->Iex.CCall.args);
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args2[i]; i++) {
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(args2[i]));
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args2[i] = subst_Expr(env, args2[i]);
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_CCall(
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.CCall.cee,
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.CCall.retty,
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   args2
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Mux0X.cond));
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Mux0X.expr0));
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Mux0X.exprX));
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Mux0X(
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Mux0X.cond),
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Mux0X.expr0),
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Mux0X.exprX)
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n\n"); ppIRExpr(ex);
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("subst_Expr");
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Apply the subst to stmt, then fold the result as much as possible.
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Much simplified due to stmt being previously flattened.  As a
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result of this, the stmt may wind up being turned into a no-op.
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nsubst and fold stmt\n");
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(st);
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.base));
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.nia));
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_AbiHint(
2353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.base)),
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.AbiHint.len,
2355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.nia))
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Put.data));
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Put(
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Put.offset,
2361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.Put.data))
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_PutI: {
2365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *puti, *puti2;
2366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti = st->Ist.PutI.details;
2367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(puti->ix));
2368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(puti->data));
2369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti2 = mkIRPutI(puti->descr,
2370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          fold_Expr(env, subst_Expr(env, puti->ix)),
2371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          puti->bias,
2372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          fold_Expr(env, subst_Expr(env, puti->data)));
2373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRStmt_PutI(puti2);
2374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is the one place where an expr (st->Ist.WrTmp.data) is
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            allowed to be more than just a constant or a tmp. */
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_WrTmp(
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.WrTmp.tmp,
2381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.WrTmp.data))
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.addr));
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.data));
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Store(
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Store.end,
2389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.Store.addr)),
2390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.Store.data))
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS: {
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS *cas, *cas2;
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->addr));
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->expdLo));
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->dataLo));
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS(
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->oldHi, cas->oldLo, cas->end,
2403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, cas->addr)),
2404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   cas->expdHi ? fold_Expr(env, subst_Expr(env, cas->expdHi))
2405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               : NULL,
2406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, cas->expdLo)),
2407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   cas->dataHi ? fold_Expr(env, subst_Expr(env, cas->dataHi))
2408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               : NULL,
2409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, cas->dataLo))
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_CAS(cas2);
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.LLSC.addr));
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.LLSC.storedata));
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_LLSC(
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.end,
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.result,
2421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.LLSC.addr)),
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.storedata
2423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      ? fold_Expr(env, subst_Expr(env, st->Ist.LLSC.storedata))
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : NULL
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty: {
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int     i;
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty *d, *d2;
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->args = shallowCopyIRExprVec(d2->args);
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None) {
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d2->mAddr));
2436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d2->mAddr = fold_Expr(env, subst_Expr(env, d2->mAddr));
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(d2->guard));
2439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d2->guard = fold_Expr(env, subst_Expr(env, d2->guard));
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++) {
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d2->args[i]));
2442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d2->args[i] = fold_Expr(env, subst_Expr(env, d2->args[i]));
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Dirty(d2);
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
2448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return IRStmt_IMark(st->Ist.IMark.addr,
2449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.len,
2450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.delta);
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_NoOp();
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_MBE(st->Ist.MBE.event);
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit: {
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* fcond;
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
2461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fcond = fold_Expr(env, subst_Expr(env, st->Ist.Exit.guard));
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fcond->tag == Iex_Const) {
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Interesting.  The condition on this exit has folded down to
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a constant. */
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(fcond->Iex.Const.con->tag == Ico_U1);
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(fcond->Iex.Const.con->Ico.U1 == False
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    || fcond->Iex.Const.con->Ico.U1 == True);
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fcond->Iex.Const.con->Ico.U1 == False) {
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* exit is never going to happen, so dump the statement. */
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return IRStmt_NoOp();
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(fcond->Iex.Const.con->Ico.U1 == True);
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Hmmm.  The exit has become unconditional.  Leave it
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  as it is for now, since we'd have to truncate the BB
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  at this point, which is tricky.  Such truncation is
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  done later by the dead-code elimination pass. */
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* fall out into the reconstruct-the-exit code. */
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (vex_control.iropt_verbosity > 0)
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* really a misuse of vex_control.iropt_verbosity */
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vex_printf("vex iropt: IRStmt_Exit became unconditional\n");
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRStmt_Exit(fcond, st->Ist.Exit.jk,
2484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   st->Ist.Exit.dst, st->Ist.Exit.offsIP);
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n"); ppIRStmt(st);
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("subst_and_fold_Stmt");
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cprop_BB ( IRSB* in )
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*    out;
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st2;
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      n_tmps = in->tyenv->types_used;
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** env = LibVEX_Alloc(n_tmps * sizeof(IRExpr*));
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out = emptyIRSB();
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up the env with which travels forward.  This holds a
2506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      substitution, mapping IRTemps to IRExprs. The environment
2507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is to be applied as we move along.  Keys are IRTemps.
2508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Values are IRExpr*s.
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i] = NULL;
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each original SSA-form stmt ... */
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < in->stmts_used; i++) {
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* First apply the substitution to the current stmt.  This
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         propagates in any constants and tmp-tmp assignments
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         accumulated prior to this point.  As part of the subst_Stmt
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         call, also then fold any constant expressions resulting. */
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = in->stmts[i];
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* perhaps st2 is already a no-op? */
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_NoOp) continue;
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = subst_and_fold_Stmt( env, st2 );
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the statement has been folded into a no-op, forget it. */
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_NoOp) continue;
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* If the statement assigns to an IRTemp add it to the running
2532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         environment. This is for the benefit of copy propagation
2533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         and to allow sameIRExpr look through IRTemps. */
2534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (st2->tag == Ist_WrTmp) {
2535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(env[(Int)(st2->Ist.WrTmp.tmp)] == NULL);
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[(Int)(st2->Ist.WrTmp.tmp)] = st2->Ist.WrTmp.data;
2537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 't1 = t2' -- don't add to BB; will be optimized out */
2539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (st2->Ist.WrTmp.data->tag == Iex_RdTmp) continue;
2540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 't = const' && 'const != F64i' -- don't add to BB
2542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Note, we choose not to propagate const when const is an
2543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            F64i, so that F64i literals can be CSE'd later.  This helps
2544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            x86 floating point code generation. */
2545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (st2->Ist.WrTmp.data->tag == Iex_Const
2546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             && st2->Ist.WrTmp.data->Iex.Const.con->tag != Ico_F64i) continue;
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Not interesting, copy st2 into the output block. */
2550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB( out, st2 );
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
2554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("sameIRExpr: invoked = %u/%u  equal = %u/%u max_nodes = %u\n",
2555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              invocation_count, recursion_count, success_count,
2556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              recursion_success_count, max_nodes_visited);
2557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
2558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->next     = subst_Expr( env, in->next );
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->jumpkind = in->jumpkind;
2561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   out->offsIP   = in->offsIP;
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return out;
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Dead code (t = E) removal                               ---*/
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* As a side effect, also removes all code following an unconditional
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   side exit. */
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The type of the HashHW map is: a map from IRTemp to nothing
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- really just operating a set or IRTemps.
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Temp ( Bool* set, IRTemp tmp )
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set[(Int)tmp] = True;
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Expr ( Bool* set, IRExpr* e )
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.GetI.ix);
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Mux0X.cond);
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Mux0X.expr0);
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Mux0X.exprX);
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, e->Iex.CCall.args[i]);
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Load.addr);
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
2603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg1);
2604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg2);
2605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg3);
2606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg4);
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
2609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Triop.details->arg1);
2610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Triop.details->arg2);
2611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Triop.details->arg3);
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Binop.arg1);
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Binop.arg2);
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Unop.arg);
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Temp(set, e->Iex.RdTmp.tmp);
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addUses_Expr");
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Stmt ( Bool* set, IRStmt* st )
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.AbiHint.base);
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.AbiHint.nia);
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
2644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, st->Ist.PutI.details->ix);
2645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, st->Ist.PutI.details->data);
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.WrTmp.data);
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Put.data);
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Store.addr);
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Store.data);
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->addr);
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->expdHi)
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, cas->expdHi);
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->expdLo);
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->dataHi)
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, cas->dataHi);
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->dataLo);
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.LLSC.addr);
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, st->Ist.LLSC.storedata);
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mFx != Ifx_None)
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, d->mAddr);
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, d->guard);
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i] != NULL; i++)
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, d->args[i]);
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Exit.guard);
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addUses_Stmt");
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this literally IRExpr_Const(IRConst_U1(False)) ? */
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU1 ( IRExpr* e )
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U1
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U1 == False );
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this literally IRExpr_Const(IRConst_U1(True)) ? */
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isOneU1 ( IRExpr* e )
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U1
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U1 == True );
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note, this destructively modifies the given IRSB. */
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan backwards through statements, carrying a set of IRTemps which
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are known to be used after the current point.  On encountering 't =
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E', delete the binding if it is not used.  Otherwise, add any temp
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uses to the set and keep on moving backwards.
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   As an enhancement, the first (backwards) pass searches for IR exits
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with always-taken conditions and notes the location of the earliest
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   one in the block.  If any such are found, a second pass copies the
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exit destination and jump kind to the bb-end.  Then, the exit and
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all statements following it are turned into no-ops.
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* notstatic */ void do_deadcode_BB ( IRSB* bb )
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, i_unconditional_exit;
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     n_tmps = bb->tyenv->types_used;
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool*   set = LibVEX_Alloc(n_tmps * sizeof(Bool));
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set[i] = False;
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* start off by recording IRTemp uses in the next field. */
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addUses_Expr(set, bb->next);
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First pass */
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Work backwards through the stmts */
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_unconditional_exit = -1;
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* take note of any unconditional exits */
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Exit
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isOneU1(st->Ist.Exit.guard))
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i_unconditional_exit = i;
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && set[(Int)(st->Ist.WrTmp.tmp)] == False) {
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* it's an IRTemp which never got used.  Delete it. */
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("DEAD: ");
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.Dirty.details->guard
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isZeroU1(st->Ist.Dirty.details->guard)) {
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is a dirty helper which will never get called.
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Delete it. */
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       else {
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note any IRTemp uses made by the current statement. */
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Stmt(set, st);
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Optional second pass: if any unconditional exits were found,
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete them and all following statements. */
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i_unconditional_exit != -1) {
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) vex_printf("ZAPPING ALL FORWARDS from %d\n",
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        i_unconditional_exit);
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i_unconditional_exit >= 0
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && i_unconditional_exit < bb->stmts_used);
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->next
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRExpr_Const( bb->stmts[i_unconditional_exit]->Ist.Exit.dst );
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->jumpkind
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = bb->stmts[i_unconditional_exit]->Ist.Exit.jk;
2787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bb->offsIP
2788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         = bb->stmts[i_unconditional_exit]->Ist.Exit.offsIP;
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = i_unconditional_exit; i < bb->stmts_used; i++)
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Specialisation of helper function calls, in             ---*/
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- collaboration with the front end                        ---*/
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* spec_helpers_BB(
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb,
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* (*specHelper) (HChar*, IRExpr**, IRStmt**, Int)
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ex;
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    any = False;
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || st->Ist.WrTmp.data->tag != Iex_CCall)
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ex = (*specHelper)( st->Ist.WrTmp.data->Iex.CCall.cee->name,
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          st->Ist.WrTmp.data->Iex.CCall.args,
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          &bb->stmts[0], i );
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ex)
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* the front end can't think of a suitable replacement */
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        continue;
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We got something better.  Install it in the bb. */
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      any = True;
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->stmts[i]
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRStmt_WrTmp(st->Ist.WrTmp.tmp, ex);
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) {
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("SPEC: ");
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(st->Ist.WrTmp.data);
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("  -->  ");
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ex);
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (any)
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = flatten_BB(bb);
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Determination of guest state aliasing relationships     ---*/
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are helper functions for CSE and GetI/PutI transformations.
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Determine, to the extent possible, the relationship between two
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest state accesses.  The possible outcomes are:
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Exact alias.  These two accesses denote precisely the same
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     piece of the guest state.
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Definitely no alias.  These two accesses are guaranteed not to
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     overlap any part of the guest state.
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Unknown -- if neither of the above can be established.
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If in doubt, return Unknown.  */
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum { ExactAlias, NoAlias, UnknownAlias }
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing;
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces the alias relation between an indexed guest
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state access and a non-indexed access. */
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGSAliasing getAliasingRelation_IC ( IRRegArray* descr1, IRExpr* ix1,
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    Int offset2, IRType ty2 )
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff1, maxoff1, minoff2, maxoff2;
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr1, &minoff1, &maxoff1 );
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   minoff2 = offset2;
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   maxoff2 = minoff2 + sizeofIRType(ty2) - 1;
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff1 < minoff2 || maxoff2 < minoff1)
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NoAlias;
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Could probably do better here if required.  For the moment
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      however just claim not to know anything more. */
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return UnknownAlias;
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces the alias relation between two indexed guest state
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accesses. */
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGSAliasing getAliasingRelation_II (
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRRegArray* descr1, IRExpr* ix1, Int bias1,
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRRegArray* descr2, IRExpr* ix2, Int bias2
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           )
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff1, maxoff1, minoff2, maxoff2;
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  iters;
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First try hard to show they don't alias. */
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr1, &minoff1, &maxoff1 );
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr2, &minoff2, &maxoff2 );
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff1 < minoff2 || maxoff2 < minoff1)
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NoAlias;
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So the two arrays at least partially overlap.  To get any
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      further we'll have to be sure that the descriptors are
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      identical. */
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!eqIRRegArray(descr1, descr2))
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return UnknownAlias;
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The descriptors are identical.  Now the only difference can be
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in the index expressions.  If they cannot be shown to be
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      identical, we have to say we don't know what the aliasing
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      relation will be.  Now, since the IR is flattened, the index
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expressions should be atoms -- either consts or tmps.  So that
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      makes the comparison simple. */
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isIRAtom(ix1));
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isIRAtom(ix2));
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!eqIRAtom(ix1,ix2))
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return UnknownAlias;
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, the index expressions are identical.  So now the only way
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      they can be different is in the bias.  Normalise this
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      paranoidly, to reliably establish equality/non-equality. */
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So now we know that the GetI and PutI index the same array
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      with the same base.  Are the offsets the same, modulo the
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      array size?  Do this paranoidly. */
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->nElems == descr2->nElems);
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->elemTy == descr2->elemTy);
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->base   == descr2->base);
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iters = 0;
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (bias1 < 0 || bias2 < 0) {
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bias1 += descr1->nElems;
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bias2 += descr1->nElems;
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters++;
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (iters > 10)
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("getAliasingRelation: iters");
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias1 >= 0 && bias2 >= 0);
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias1 %= descr1->nElems;
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias2 %= descr1->nElems;
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias1 >= 0 && bias1 < descr1->nElems);
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias2 >= 0 && bias2 < descr1->nElems);
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, biasP and biasG are normalised into the range
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0 .. descrP/G->nElems - 1.  And so we can establish
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      equality/non-equality. */
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bias1==bias2 ? ExactAlias : NoAlias;
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Common Subexpression Elimination                        ---*/
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expensive in time and space. */
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Uses two environments:
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a IRTemp -> IRTemp mapping
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a mapping from AvailExpr* to IRTemp
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
2971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      enum { TCc, TCt } tag;
2972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      union { IRTemp tmp; IRConst* con; } u;
2973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   TmpOrConst;
2975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool eqTmpOrConst ( TmpOrConst* tc1, TmpOrConst* tc2 )
2977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (tc1->tag != tc2->tag)
2979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return False;
2980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (tc1->tag) {
2981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case TCc:
2982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return eqIRConst(tc1->u.con, tc2->u.con);
2983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case TCt:
2984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return tc1->u.tmp == tc2->u.tmp;
2985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
2986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("eqTmpOrConst");
2987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool eqIRCallee ( IRCallee* cee1, IRCallee* cee2 )
2991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool eq = cee1->addr == cee2->addr;
2993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (eq) {
2994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cee1->regparms == cee2->regparms);
2995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cee1->mcx_mask == cee2->mcx_mask);
2996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Names should be the same too, but we don't bother to
2997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         check. */
2998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return eq;
3000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Convert a NULL terminated IRExpr* vector to an array of
3003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   TmpOrConsts, and a length. */
3004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void irExprVec_to_TmpOrConsts ( /*OUT*/TmpOrConst** outs,
3005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       /*OUT*/Int* nOuts,
3006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       IRExpr** ins )
3007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int i, n;
3009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* We have to make two passes, one to count, one to copy. */
3010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (n = 0; ins[n]; n++)
3011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ;
3012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *outs  = LibVEX_Alloc(n * sizeof(TmpOrConst));
3013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *nOuts = n;
3014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* and now copy .. */
3015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < n; i++) {
3016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr*       arg = ins[i];
3017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      TmpOrConst* dst = &(*outs)[i];
3018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (arg->tag == Iex_RdTmp) {
3019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->tag   = TCt;
3020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->u.tmp = arg->Iex.RdTmp.tmp;
3021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else if (arg->tag == Iex_Const) {
3023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->tag   = TCc;
3024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->u.con = arg->Iex.Const.con;
3025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else {
3027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Failure of this is serious; it means that the presented arg
3028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            isn't an IR atom, as it should be. */
3029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("irExprVec_to_TmpOrConsts");
3030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef
3035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   struct {
3036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      enum { Ut, Btt, Btc, Bct, Cf64i, Mttt, GetIt, CCall } tag;
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union {
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unop(tmp) */
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   op;
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg;
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Ut;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(tmp,tmp) */
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   op;
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg1;
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg2;
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Btt;
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(tmp,const) */
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp    op;
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp  arg1;
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst con2;
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Btc;
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(const,tmp) */
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp    op;
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst con1;
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp  arg2;
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bct;
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* F64i-style const */
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong f64i;
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Cf64i;
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Mux0X(tmp,tmp,tmp) */
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp co;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp e0;
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp eX;
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Mttt;
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* GetI(descr,tmp,bias)*/
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRRegArray* descr;
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp      ix;
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int         bias;
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } GetIt;
3077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Clean helper call */
3078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         struct {
3079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRCallee*   cee;
3080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            TmpOrConst* args;
3081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int         nArgs;
3082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRType      retty;
3083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } CCall;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } u;
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr;
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool eq_AvailExpr ( AvailExpr* a1, AvailExpr* a2 )
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (LIKELY(a1->tag != a2->tag))
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (a1->tag) {
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Ut.op == a2->u.Ut.op
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Ut.arg == a2->u.Ut.arg);
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Btt.op == a2->u.Btt.op
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btt.arg1 == a2->u.Btt.arg1
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btt.arg2 == a2->u.Btt.arg2);
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Btc.op == a2->u.Btc.op
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btc.arg1 == a2->u.Btc.arg1
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && eqIRConst(&a1->u.Btc.con2, &a2->u.Btc.con2));
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Bct.op == a2->u.Bct.op
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Bct.arg2 == a2->u.Bct.arg2
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && eqIRConst(&a1->u.Bct.con1, &a2->u.Bct.con1));
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(a1->u.Cf64i.f64i == a2->u.Cf64i.f64i);
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Mttt:
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(a1->u.Mttt.co == a2->u.Mttt.co
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.Mttt.e0 == a2->u.Mttt.e0
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.Mttt.eX == a2->u.Mttt.eX);
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(eqIRRegArray(a1->u.GetIt.descr, a2->u.GetIt.descr)
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.GetIt.ix == a2->u.GetIt.ix
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.GetIt.bias == a2->u.GetIt.bias);
3122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case CCall: {
3123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int  i, n;
3124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool eq = a1->u.CCall.nArgs == a2->u.CCall.nArgs
3125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   && eqIRCallee(a1->u.CCall.cee, a2->u.CCall.cee);
3126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (eq) {
3127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            n = a1->u.CCall.nArgs;
3128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (i = 0; i < n; i++) {
3129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (!eqTmpOrConst( &a1->u.CCall.args[i],
3130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  &a2->u.CCall.args[i] )) {
3131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  eq = False;
3132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
3134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (eq) vassert(a1->u.CCall.retty == a2->u.CCall.retty);
3137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return eq;
3138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("eq_AvailExpr");
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* availExpr_to_IRExpr ( AvailExpr* ae )
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ae->tag) {
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( ae->u.Ut.op, IRExpr_RdTmp(ae->u.Ut.arg) );
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Btt.op,
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btt.arg1),
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btt.arg2) );
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con = LibVEX_Alloc(sizeof(IRConst));
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *con = ae->u.Btc.con2;
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Btc.op,
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btc.arg1),
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(con) );
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con = LibVEX_Alloc(sizeof(IRConst));
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *con = ae->u.Bct.con1;
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Bct.op,
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(con),
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Bct.arg2) );
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_F64i(ae->u.Cf64i.f64i));
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Mttt:
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Mux0X(IRExpr_RdTmp(ae->u.Mttt.co),
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(ae->u.Mttt.e0),
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(ae->u.Mttt.eX));
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(ae->u.GetIt.descr,
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRExpr_RdTmp(ae->u.GetIt.ix),
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            ae->u.GetIt.bias);
3175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case CCall: {
3176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int i, n = ae->u.CCall.nArgs;
3177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(n >= 0);
3178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr** vec = LibVEX_Alloc((n+1) * sizeof(IRExpr*));
3179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vec[n] = NULL;
3180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < n; i++) {
3181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            TmpOrConst* tc = &ae->u.CCall.args[i];
3182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (tc->tag == TCc) {
3183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vec[i] = IRExpr_Const(tc->u.con);
3184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else if (tc->tag == TCt) {
3186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vec[i] = IRExpr_RdTmp(tc->u.tmp);
3187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else vpanic("availExpr_to_IRExpr:CCall-arg");
3189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_CCall(ae->u.CCall.cee,
3191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             ae->u.CCall.retty,
3192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             vec);
3193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("availExpr_to_IRExpr");
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp subst_AvailExpr_Temp ( HashHW* env, IRTemp tmp )
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord res;
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* env :: IRTemp -> IRTemp */
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (lookupHHW( env, &res, (HWord)tmp ))
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (IRTemp)res;
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return tmp;
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void subst_AvailExpr ( HashHW* env, AvailExpr* ae )
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* env :: IRTemp -> IRTemp */
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ae->tag) {
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Ut.arg = subst_AvailExpr_Temp( env, ae->u.Ut.arg );
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btt.arg1 = subst_AvailExpr_Temp( env, ae->u.Btt.arg1 );
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btt.arg2 = subst_AvailExpr_Temp( env, ae->u.Btt.arg2 );
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btc.arg1 = subst_AvailExpr_Temp( env, ae->u.Btc.arg1 );
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Bct.arg2 = subst_AvailExpr_Temp( env, ae->u.Bct.arg2 );
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Mttt:
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Mttt.co = subst_AvailExpr_Temp( env, ae->u.Mttt.co );
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Mttt.e0 = subst_AvailExpr_Temp( env, ae->u.Mttt.e0 );
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Mttt.eX = subst_AvailExpr_Temp( env, ae->u.Mttt.eX );
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.GetIt.ix = subst_AvailExpr_Temp( env, ae->u.GetIt.ix );
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case CCall: {
3238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int i, n = ae->u.CCall.nArgs;;
3239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < n; i++) {
3240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            TmpOrConst* tc = &ae->u.CCall.args[i];
3241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (tc->tag == TCt) {
3242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               tc->u.tmp = subst_AvailExpr_Temp( env, tc->u.tmp );
3243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("subst_AvailExpr");
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AvailExpr* irExpr_to_AvailExpr ( IRExpr* e )
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* ae;
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.arg->tag == Iex_RdTmp) {
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag      = Ut;
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Ut.op  = e->Iex.Unop.op;
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Ut.arg = e->Iex.Unop.arg->Iex.RdTmp.tmp;
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1->tag == Iex_RdTmp
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_RdTmp) {
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag        = Btt;
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btt.op   = e->Iex.Binop.op;
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btt.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btt.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg1->tag == Iex_RdTmp
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg2->tag == Iex_Const) {
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag        = Btc;
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btc.op   = e->Iex.Binop.op;
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btc.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Btc.con2 = *(e->Iex.Binop.arg2->Iex.Const.con);
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg1->tag == Iex_Const
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      && e->Iex.Binop.arg2->tag == Iex_RdTmp) {
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag        = Bct;
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Bct.op   = e->Iex.Binop.op;
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Bct.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Bct.con1 = *(e->Iex.Binop.arg1->Iex.Const.con);
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->tag == Ico_F64i) {
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag          = Cf64i;
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Cf64i.f64i = e->Iex.Const.con->Ico.F64i;
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Mux0X.cond->tag == Iex_RdTmp
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Mux0X.expr0->tag == Iex_RdTmp
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Mux0X.exprX->tag == Iex_RdTmp) {
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag       = Mttt;
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Mttt.co = e->Iex.Mux0X.cond->Iex.RdTmp.tmp;
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Mttt.e0 = e->Iex.Mux0X.expr0->Iex.RdTmp.tmp;
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.Mttt.eX = e->Iex.Mux0X.exprX->Iex.RdTmp.tmp;
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_GetI
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.GetI.ix->tag == Iex_RdTmp) {
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae = LibVEX_Alloc(sizeof(AvailExpr));
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->tag           = GetIt;
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.GetIt.descr = e->Iex.GetI.descr;
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.GetIt.ix    = e->Iex.GetI.ix->Iex.RdTmp.tmp;
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ae->u.GetIt.bias  = e->Iex.GetI.bias;
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ae;
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_CCall) {
3329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ae = LibVEX_Alloc(sizeof(AvailExpr));
3330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ae->tag = CCall;
3331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Ok to share only the cee, since it is immutable. */
3332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ae->u.CCall.cee   = e->Iex.CCall.cee;
3333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ae->u.CCall.retty = e->Iex.CCall.retty;
3334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* irExprVec_to_TmpOrConsts will assert if the args are
3335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         neither tmps nor constants, but that's ok .. that's all they
3336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         should be. */
3337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      irExprVec_to_TmpOrConsts(
3338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         &ae->u.CCall.args, &ae->u.CCall.nArgs,
3339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         e->Iex.CCall.args
3340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      );
3341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return ae;
3342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The BB is modified in-place.  Returns True if any changes were
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   made. */
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool do_cse_BB ( IRSB* bb )
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, j, paranoia;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp     t, q;
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* eprime;
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* ae;
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       invalidate;
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       anyDone = False;
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* tenv = newHHW(); /* :: IRTemp -> IRTemp */
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* aenv = newHHW(); /* :: AvailExpr* -> IRTemp */
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sizeof(IRTemp) <= sizeof(HWord));
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) { ppIRSB(bb); vex_printf("\n\n"); }
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate forwards over the stmts.
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      On seeing "t = E", where E is one of the 5 AvailExpr forms:
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         let E' = apply tenv substitution to E
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         search aenv for E'
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if a mapping E' -> q is found,
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               replace this stmt by "t = q"
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and add binding t -> q to tenv
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add binding E' -> t to aenv
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               replace this stmt by "t = E'"
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Other statements are only interesting to the extent that they
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      might invalidate some of the expressions in aenv.  So there is
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an invalidate-bindings check for each statement seen.
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ BEGIN invalidate aenv bindings ------ */
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is critical: remove from aenv any E' -> .. bindings
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         which might be invalidated by this statement.  The only
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vulnerable kind of bindings are the GetI kind.
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Dirty call - dump (paranoia level -> 2)
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Store      - dump (ditto)
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Put, PutI  - dump unless no-overlap is proven (.. -> 1)
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Uses getAliasingRelation_IC and getAliasingRelation_II
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to do the no-overlap assessments needed for Put/PutI.
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty: case Ist_Store: case Ist_MBE:
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS: case Ist_LLSC:
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 2; break;
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put: case Ist_PutI:
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 1; break;
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp: case Ist_IMark: case Ist_AbiHint:
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp: case Ist_Exit:
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 0; break;
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("do_cse_BB(1)");
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (paranoia > 0) {
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < aenv->used; j++) {
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!aenv->inuse[j])
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ae = (AvailExpr*)aenv->key[j];
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ae->tag != GetIt)
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalidate = False;
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (paranoia >= 2) {
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               invalidate = True;
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(paranoia == 1);
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (st->tag == Ist_Put) {
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (getAliasingRelation_IC(
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.descr,
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(ae->u.GetIt.ix),
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.Put.offset,
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         typeOfIRExpr(bb->tyenv,st->Ist.Put.data)
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ) != NoAlias)
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     invalidate = True;
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (st->tag == Ist_PutI) {
3432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRPutI *puti = st->Ist.PutI.details;
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (getAliasingRelation_II(
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.descr,
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(ae->u.GetIt.ix),
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.bias,
3437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         puti->descr,
3438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         puti->ix,
3439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         puti->bias
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ) != NoAlias)
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     invalidate = True;
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vpanic("do_cse_BB(2)");
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (invalidate) {
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               aenv->inuse[j] = False;
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               aenv->key[j]   = (HWord)NULL;  /* be sure */
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } /* for j */
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* paranoia > 0 */
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ ENV invalidate aenv bindings ------ */
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore not-interestings */
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp)
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t = st->Ist.WrTmp.tmp;
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eprime = irExpr_to_AvailExpr(st->Ist.WrTmp.data);
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore if not of AvailExpr form */
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!eprime)
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("considering: " ); ppIRStmt(st); vex_printf("\n"); */
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* apply tenv */
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subst_AvailExpr( tenv, eprime );
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* search aenv for eprime, unfortunately the hard way */
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = 0; j < aenv->used; j++)
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (aenv->inuse[j] && eq_AvailExpr(eprime, (AvailExpr*)aenv->key[j]))
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (j < aenv->used) {
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A binding E' -> q was found.  Replace stmt by "t = q" and
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            note the t->q binding in tenv. */
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* (this is the core of the CSE action) */
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         q = (IRTemp)aenv->val[j];
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_WrTmp( t, IRExpr_RdTmp(q) );
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( tenv, (HWord)t, (HWord)q );
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         anyDone = True;
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No binding was found, so instead we add E' -> t to our
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            collection of available expressions, replace this stmt
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            with "t = E'", and move on. */
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_WrTmp( t, availExpr_to_IRExpr(eprime) );
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( aenv, (HWord)eprime, (HWord)t );
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRSB(bb);
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sanityCheckIRSB(bb, Ity_I32);
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n\n");
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return anyDone;
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Add32/Sub32 chain collapsing                            ---*/
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----- Helper functions for Add32/Sub32 chain collapsing ----- */
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this expression "Add32(tmp,const)" or "Sub32(tmp,const)" ?  If
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   yes, set *tmp and *i32 appropriately.  *i32 is set as if the
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   root node is Add32, not Sub32. */
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isAdd32OrSub32 ( IRExpr* e, IRTemp* tmp, Int* i32 )
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag != Iex_Binop)
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.op != Iop_Add32 && e->Iex.Binop.op != Iop_Sub32)
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.arg1->tag != Iex_RdTmp)
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.arg2->tag != Iex_Const)
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *tmp = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i32 = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32);
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.op == Iop_Sub32)
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *i32 = -*i32;
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if tmp can be expressed as tmp2 +32 const, for some
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   other tmp2.  Scan backwards from the specified start point -- an
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisation. */
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool collapseChain ( IRSB* bb, Int startHere,
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp tmp,
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp* tmp2, Int* i32 )
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     j, ii;
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  vv;
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* the (var, con) pair contain the current 'representation' for
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'tmp'.  We start with 'tmp + 0'.  */
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp var = tmp;
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    con = 0;
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan backwards to see if tmp can be replaced by some other tmp
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     +/- a constant. */
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = startHere; j >= 0; j--) {
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[j];
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp)
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->Ist.WrTmp.tmp != var)
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = st->Ist.WrTmp.data;
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isAdd32OrSub32(e, &vv, &ii))
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      var = vv;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con += ii;
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (j == -1)
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no earlier binding for var .. ill-formed IR */
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("collapseChain");
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* so, did we find anything interesting? */
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (var == tmp)
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; /* no .. */
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *tmp2 = var;
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i32  = con;
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------- Main function for Add32/Sub32 chain collapsing ------ */
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void collapse_AddSub_chains_BB ( IRSB* bb )
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt *st;
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp var, var2;
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, con, con2;
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Try to collapse 't1 = Add32/Sub32(t2, con)'. */
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isAdd32OrSub32(st->Ist.WrTmp.data, &var, &con)) {
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* So e1 is of the form Add32(var,con) or Sub32(var,-con).
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Find out if var can be expressed as var2 + con2. */
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (collapseChain(bb, i-1, var, &var2, &con2)) {
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("replacing1 ");
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRStmt(st);
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf(" with ");
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            con2 += con;
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i]
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = IRStmt_WrTmp(
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    st->Ist.WrTmp.tmp,
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (con2 >= 0)
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? IRExpr_Binop(Iop_Add32,
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_RdTmp(var2),
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Const(IRConst_U32(con2)))
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : IRExpr_Binop(Iop_Sub32,
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_RdTmp(var2),
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Const(IRConst_U32(-con2)))
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRStmt(bb->stmts[i]);
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Try to collapse 't1 = GetI[t2, con]'. */
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_GetI
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && collapseChain(bb, i-1, st->Ist.WrTmp.data->Iex.GetI.ix
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ->Iex.RdTmp.tmp, &var2, &con2)) {
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("replacing3 ");
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" with ");
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con2 += st->Ist.WrTmp.data->Iex.GetI.bias;
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i]
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_WrTmp(
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.WrTmp.tmp,
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_GetI(st->Ist.WrTmp.data->Iex.GetI.descr,
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(var2),
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             con2));
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(bb->stmts[i]);
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perhaps st is PutI[t, con] ? */
3650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRPutI *puti = st->Ist.PutI.details;
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_PutI
3652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && puti->ix->tag == Iex_RdTmp
3653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && collapseChain(bb, i-1, puti->ix->Iex.RdTmp.tmp,
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &var2, &con2)) {
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("replacing2 ");
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" with ");
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         con2 += puti->bias;
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i]
3662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            = IRStmt_PutI(mkIRPutI(puti->descr,
3663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   IRExpr_RdTmp(var2),
3664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   con2,
3665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   puti->data));
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(bb->stmts[i]);
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for */
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PutI/GetI transformations                               ---*/
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given the parts (descr, tmp, bias) for a GetI, scan backwards from
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the given starting point to find, if any, a PutI which writes
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exactly the same piece of guest state, and so return the expression
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that the PutI writes.  This is the core of PutI-GetI forwarding. */
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* findPutI ( IRSB* bb, Int startHere,
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRRegArray* descrG, IRExpr* ixG, Int biasG )
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        j;
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing relation;
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\nfindPutI ");
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRRegArray(descrG);
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" ");
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(ixG);
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" %d\n", biasG);
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan backwards in bb from startHere to find a suitable PutI
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binding for (descrG, ixG, biasG), if any. */
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = startHere; j >= 0; j--) {
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[j];
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put) {
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Non-indexed Put.  This can't give a binding, but we do
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            need to check it doesn't invalidate the search by
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            overlapping any part of the indexed guest state. */
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_IC(
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 descrG, ixG,
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.Put.offset,
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == NoAlias) {
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we're OK; keep going */
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relation == UnknownAlias || relation == ExactAlias */
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* If this assertion fails, we've found a Put which writes
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               an area of guest state which is read by a GetI.  Which
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               is unlikely (although not per se wrong). */
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(relation != ExactAlias);
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This Put potentially writes guest state that the GetI
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reads; we must fail. */
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_PutI) {
3737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *puti = st->Ist.PutI.details;
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation = getAliasingRelation_II(
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       descrG, ixG, biasG,
3741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       puti->descr,
3742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       puti->ix,
3743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       puti->bias
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    );
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == NoAlias) {
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This PutI definitely doesn't overlap.  Ignore it and
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               keep going. */
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue; /* the for j loop */
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == UnknownAlias) {
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We don't know if this PutI writes to the same guest
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state that the GetI, or not.  So we have to give up. */
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Otherwise, we've found what we're looking for.  */
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(relation == ExactAlias);
3760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return puti->data;
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* if (st->tag == Ist_PutI) */
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty) {
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Be conservative.  If the dirty call has any guest effects at
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            all, give up.  We could do better -- only give up if there
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            are any guest writes/modifies. */
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.Dirty.details->nFxState > 0)
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for */
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No valid replacement was found. */
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assuming pi is a PutI stmt, is s2 identical to it (in the sense
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that it writes exactly the same piece of guest state) ?  Safe
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   answer: False. */
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool identicalPutIs ( IRStmt* pi, IRStmt* s2 )
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pi->tag == Ist_PutI);
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s2->tag != Ist_PutI)
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI *p1 = pi->Ist.PutI.details;
3791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI *p2 = s2->Ist.PutI.details;
3792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getAliasingRelation_II(
3795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             p1->descr, p1->ix, p1->bias,
3796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             p2->descr, p2->ix, p2->bias
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          )
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          == ExactAlias
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assuming pi is a PutI stmt, is s2 a Get/GetI/Put/PutI which might
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlap it?  Safe answer: True.  Note, we could do a lot better
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   than this if needed. */
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool guestAccessWhichMightOverlapPutI (
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTypeEnv* tyenv, IRStmt* pi, IRStmt* s2
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     )
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing relation;
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       minoffP, maxoffP;
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pi->tag == Ist_PutI);
3816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI *p1 = pi->Ist.PutI.details;
3818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   getArrayBounds(p1->descr, &minoffP, &maxoffP);
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (s2->tag) {
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* just be paranoid ... these should be rare. */
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is unbelievably lame, but it's probably not
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            significant from a performance point of view.  Really, a
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CAS is a load-store op, so it should be safe to say False.
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            However .. */
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If the dirty call has any guest effects at all, give up.
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Probably could do better. */
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.Dirty.details->nFxState > 0)
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Put.data));
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_IC(
3849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 p1->descr, p1->ix,
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 s2->Ist.Put.offset,
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(tyenv,s2->Ist.Put.data)
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto have_relation;
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_PutI: {
3856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *p2 = s2->Ist.PutI.details;
3857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(p2->ix));
3859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(p2->data));
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_II(
3862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 p1->descr, p1->ix, p1->bias,
3863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 p2->descr, p2->ix, p2->bias
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto have_relation;
3866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.WrTmp.data->tag == Iex_GetI) {
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relation
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = getAliasingRelation_II(
3872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    p1->descr, p1->ix, p1->bias,
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.descr,
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.ix,
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.bias
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto have_relation;
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.WrTmp.data->tag == Iex_Get) {
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relation
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = getAliasingRelation_IC(
3882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    p1->descr, p1->ix,
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.Get.offset,
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.Get.ty
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto have_relation;
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Store.addr));
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Store.data));
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(s2); vex_printf("\n");
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("guestAccessWhichMightOverlapPutI");
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  have_relation:
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (relation == NoAlias)
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True; /* ExactAlias or UnknownAlias */
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------- PutI/GetI transformations main functions --------- */
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remove redundant GetIs, to the extent that they can be detected.
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb is modified in-place. */
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_redundant_GetI_elimination ( IRSB* bb )
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_GetI
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp) {
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr = st->Ist.WrTmp.data->Iex.GetI.descr;
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr*     ix    = st->Ist.WrTmp.data->Iex.GetI.ix;
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int         bias  = st->Ist.WrTmp.data->Iex.GetI.bias;
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr*     replacement = findPutI(bb, i-1, descr, ix, bias);
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (replacement
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && isIRAtom(replacement)
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* Make sure we're doing a type-safe transformation! */
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && typeOfIRExpr(bb->tyenv, replacement) == descr->elemTy) {
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rGI:  ");
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(st->Ist.WrTmp.data);
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf(" -> ");
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(replacement);
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, replacement);
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remove redundant PutIs, to the extent which they can be detected.
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb is modified in-place. */
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_redundant_PutI_elimination ( IRSB* bb )
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, j;
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   delete;
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt *st, *stj;
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert
3962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (vex_control.iropt_register_updates == VexRegUpdUnwindregsAtMemAccess
3963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || vex_control.iropt_register_updates == VexRegUpdAllregsAtMemAccess);
3964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_PutI)
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, search forwards from here to see if we can find another
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PutI which makes this one redundant, and dodging various
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         hazards.  Search forwards:
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If conditional exit, give up (because anything after that
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           does not postdominate this put).
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Get which might overlap, give up (because this PutI
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           not necessarily dead).
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which is identical, stop with success.
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which might overlap, but is not identical, give up.
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a dirty helper call which might write guest state, give up.
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which definitely doesn't overlap, or any other
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           kind of stmt, continue.
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete = False;
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = i+1; j < bb->stmts_used; j++) {
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stj = bb->stmts[j];
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stj->tag == Ist_NoOp)
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (identicalPutIs(st, stj)) {
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* success! */
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete = True;
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stj->tag == Ist_Exit)
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up */
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag == Ist_Dirty)
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up; could do better here */
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (guestAccessWhichMightOverlapPutI(bb->tyenv, st, stj))
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up */
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (delete) {
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("rPI:  ");
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Loop unrolling                                          ---*/
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust all tmp values (names) in e by delta.  e is destructively
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified. */
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deltaIRExpr ( IRExpr* e, Int delta )
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e->Iex.RdTmp.tmp += delta;
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.GetI.ix, delta);
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg1, delta);
4038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg2, delta);
4039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg3, delta);
4040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg4, delta);
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Triop.details->arg1, delta);
4044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Triop.details->arg2, delta);
4045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Triop.details->arg3, delta);
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Binop.arg1, delta);
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Binop.arg2, delta);
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Unop.arg, delta);
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Load.addr, delta);
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(e->Iex.CCall.args[i], delta);
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Mux0X.cond, delta);
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Mux0X.expr0, delta);
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Mux0X.exprX, delta);
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("deltaIRExpr");
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust all tmp values (names) in st by delta.  st is destructively
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified. */
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deltaIRStmt ( IRStmt* st, Int delta )
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.AbiHint.base, delta);
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.AbiHint.nia, delta);
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Put.data, delta);
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
4092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(st->Ist.PutI.details->ix, delta);
4093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(st->Ist.PutI.details->data, delta);
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.WrTmp.tmp += delta;
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.WrTmp.data, delta);
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Exit.guard, delta);
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Store.addr, delta);
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Store.data, delta);
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->oldHi != IRTemp_INVALID)
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            st->Ist.CAS.details->oldHi += delta;
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.CAS.details->oldLo += delta;
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->addr, delta);
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->expdHi)
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.CAS.details->expdHi, delta);
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->expdLo, delta);
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->dataHi)
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.CAS.details->dataHi, delta);
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->dataLo, delta);
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.LLSC.result += delta;
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.LLSC.addr, delta);
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.LLSC.storedata, delta);
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(d->guard, delta);
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i]; i++)
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(d->args[i], delta);
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->tmp != IRTemp_INVALID)
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d->tmp += delta;
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mAddr)
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(d->mAddr, delta);
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("deltaIRStmt");
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If possible, return a loop-unrolled version of bb0.  The original
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is changed.  If not possible, return NULL.  */
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The two schemas considered are:
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     X: BODY; goto X
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     which unrolls to (eg)  X: BODY;BODY; goto X
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       X: BODY; if (c) goto X; goto Y
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which trivially transforms to
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       X: BODY; if (!c) goto Y; goto X;
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so it falls in the scope of the first case.
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X and Y must be literal (guest) addresses.
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int calc_unroll_factor( IRSB* bb )
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int n_stmts, i;
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_stmts = 0;
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb->stmts[i]->tag != Ist_NoOp)
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_stmts++;
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/8) {
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 8 x unrolling (%d sts -> %d sts)\n",
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 8* n_stmts);
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 8;
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/4) {
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 4 x unrolling (%d sts -> %d sts)\n",
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 4* n_stmts);
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 4;
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/2) {
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 2 x unrolling (%d sts -> %d sts)\n",
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 2* n_stmts);
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 2;
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_verbosity > 0)
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("vex iropt: not unrolling (%d sts)\n", n_stmts);
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 1;
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* maybe_loop_unroll_BB ( IRSB* bb0, Addr64 my_addr )
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j, jmax, n_vars;
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     xxx_known;
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64   xxx_value, yyy_value;
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  udst;
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB     *bb1, *bb2;
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      unroll_factor;
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_unroll_thresh <= 0)
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First off, figure out if we can unroll this loop.  Do this
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      without modifying bb0. */
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bb0->jumpkind != Ijk_Boring)
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_known = False;
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_value = 0;
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Extract the next-guest address.  If it isn't a literal, we
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to give up. */
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = bb0->next;
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (udst->tag == Iex_Const
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (udst->Iex.Const.con->tag == Ico_U32
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || udst->Iex.Const.con->tag == Ico_U64)) {
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The BB ends in a jump to a literal location. */
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xxx_known = True;
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xxx_value = udst->Iex.Const.con->tag == Ico_U64
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ?  udst->Iex.Const.con->Ico.U64
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : (Addr64)(udst->Iex.Const.con->Ico.U32);
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!xxx_known)
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we know the BB ends to a jump to a literal location.  If
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it's a jump to itself (viz, idiom #1), move directly to the
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrolling stage, first cloning the bb so the original isn't
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      modified. */
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xxx_value == my_addr) {
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unroll_factor = calc_unroll_factor( bb0 );
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (unroll_factor < 2)
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return NULL;
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb1 = deepCopyIRSB( bb0 );
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb0 = NULL;
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst = NULL; /* is now invalid */
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto do_unroll;
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Search for the second idiomatic form:
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        X: BODY; if (c) goto X; goto Y
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      We know Y, but need to establish that the last stmt
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is 'if (c) goto X'.
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   yyy_value = xxx_value;
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb0->stmts_used-1; i >= 0; i--)
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb0->stmts[i])
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i < 0)
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL; /* block with no stmts.  Strange. */
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = bb0->stmts[i];
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (st->tag != Ist_Exit)
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (st->Ist.Exit.jk != Ijk_Boring)
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = st->Ist.Exit.dst;
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_value = con->tag == Ico_U64
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ? st->Ist.Exit.dst->Ico.U64
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  : (Addr64)(st->Ist.Exit.dst->Ico.U32);
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this assertion fails, we have some kind of type error. */
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == udst->Iex.Const.con->tag);
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xxx_value != my_addr)
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We didn't find either idiom.  Give up. */
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, we found idiom #2.  Copy the BB, switch around the xxx and
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      yyy values (which makes it look like idiom #1), and go into
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrolling proper.  This means finding (again) the last stmt, in
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the copied BB. */
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unroll_factor = calc_unroll_factor( bb0 );
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (unroll_factor < 2)
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb1 = deepCopyIRSB( bb0 );
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb0 = NULL;
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = NULL; /* is now invalid */
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb1->stmts_used-1; i >= 0; i--)
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb1->stmts[i])
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The next bunch of assertions should be true since we already
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      found and checked the last stmt in the original bb. */
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i >= 0);
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = bb1->stmts[i];
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(st->tag == Ist_Exit);
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = st->Ist.Exit.dst;
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = bb1->next;
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(udst->tag == Iex_Const);
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(udst->Iex.Const.con->tag == Ico_U32
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || udst->Iex.Const.con->tag == Ico_U64);
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == udst->Iex.Const.con->tag);
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* switch the xxx and yyy fields around */
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (con->tag == Ico_U64) {
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst->Iex.Const.con->Ico.U64 = xxx_value;
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con->Ico.U64 = yyy_value;
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst->Iex.Const.con->Ico.U32 = (UInt)xxx_value;
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con->Ico.U32 = (UInt)yyy_value;
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* negate the test condition */
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st->Ist.Exit.guard
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = IRExpr_Unop(Iop_Not1,deepCopyIRExpr(st->Ist.Exit.guard));
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- The unroller proper.  Both idioms are by now --- */
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- now converted to idiom 1. --- */
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_unroll:
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(unroll_factor == 2
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || unroll_factor == 4
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || unroll_factor == 8);
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   jmax = unroll_factor==8 ? 3 : (unroll_factor==4 ? 2 : 1);
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 1; j <= jmax; j++) {
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_vars = bb1->tyenv->types_used;
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb2 = deepCopyIRSB(bb1);
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_vars; i++)
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void)newIRTemp(bb1->tyenv, bb2->tyenv->types[i]);
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < bb2->stmts_used; i++) {
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* deltaIRStmt destructively modifies the stmt, but
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that's OK since bb2 is a complete fresh copy of bb1. */
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRStmt(bb2->stmts[i], n_vars);
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb1, bb2->stmts[i]);
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_IROPT) {
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\nUNROLLED (%llx)\n", my_addr);
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb1);
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flattening; sigh.  The unroller succeeds in breaking flatness
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by negating the test condition.  This should be fixed properly.
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      For the moment use this shotgun approach.  */
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return flatten_BB(bb1);
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The tree builder                                        ---*/
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This isn't part of IR optimisation.  Really it's a pass done prior
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to instruction selection, which improves the code that the
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction selector can produce. */
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- The 'tmp' environment is the central data structure here --- */
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The number of outstanding bindings we're prepared to track.
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The number of times the env becomes full and we have to dump
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the oldest binding (hence reducing code quality) falls very
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rapidly as the env size increases.  8 gives reasonable performance
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   under most circumstances. */
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define A_NENV 10
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bindee == NULL   ===  slot is not in use
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bindee != NULL   ===  slot is in use
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  binder;
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* bindee;
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    doesLoad;
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    doesGet;
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ATmpInfo;
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused))
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppAEnv ( ATmpInfo* env )
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%d  tmp %d  val ", i, (Int)env[i].binder);
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[i].bindee)
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(env[i].bindee);
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("(null)");
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Tree-traversal fns --- */
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Traverse an expr, and detect if any part of it reads memory or does
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a Get.  Be careful ... this really controls how much the
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tree-builder can reorder the code, so getting it right is critical.
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setHints_Expr (Bool* doesLoad, Bool* doesGet, IRExpr* e )
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setHints_Expr(doesLoad, doesGet, e->Iex.CCall.args[i]);
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Mux0X.cond);
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Mux0X.expr0);
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Mux0X.exprX);
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.details->arg1);
4433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.details->arg2);
4434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.details->arg3);
4435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Qop.details->arg4);
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Triop.details->arg1);
4439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Triop.details->arg2);
4440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         setHints_Expr(doesLoad, doesGet, e->Iex.Triop.details->arg3);
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Binop.arg1);
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Binop.arg2);
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Unop.arg);
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesLoad = True;
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.Load.addr);
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesGet = True;
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesGet = True;
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(doesLoad, doesGet, e->Iex.GetI.ix);
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("setHints_Expr");
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a binding to the front of the env and slide all the rest
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   backwards.  It should be the case that the last slot is free. */
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addToEnvFront ( ATmpInfo* env, IRTemp binder, IRExpr* bindee )
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env[A_NENV-1].bindee == NULL);
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = A_NENV-1; i >= 1; i--)
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i] = env[i-1];
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].binder   = binder;
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].bindee   = bindee;
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].doesLoad = False; /* filled in later */
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].doesGet  = False; /* filled in later */
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given uses :: array of UShort, indexed by IRTemp
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Add the use-occurrences of temps in this expression
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the env.
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void aoccCount_Expr ( UShort* uses, IRExpr* e )
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp: /* the only interesting case */
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uses[e->Iex.RdTmp.tmp]++;
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Mux0X.cond);
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Mux0X.expr0);
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Mux0X.exprX);
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg1);
4506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg2);
4507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg3);
4508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg4);
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Triop.details->arg1);
4513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Triop.details->arg2);
4514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Triop.details->arg3);
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Binop.arg1);
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Binop.arg2);
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Unop.arg);
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Load.addr);
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, e->Iex.CCall.args[i]);
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.GetI.ix);
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("aoccCount_Expr");
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given uses :: array of UShort, indexed by IRTemp
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Add the use-occurrences of temps in this statement
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the env.
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void aoccCount_Stmt ( UShort* uses, IRStmt* st )
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.AbiHint.base);
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.AbiHint.nia);
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.WrTmp.data);
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Put.data);
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
4571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, st->Ist.PutI.details->ix);
4572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, st->Ist.PutI.details->data);
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Store.addr);
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Store.data);
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->addr);
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->expdHi)
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, cas->expdHi);
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->expdLo);
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->dataHi)
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, cas->dataHi);
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->dataLo);
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.LLSC.addr);
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, st->Ist.LLSC.storedata);
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mFx != Ifx_None)
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, d->mAddr);
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, d->guard);
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i]; i++)
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, d->args[i]);
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Exit.guard);
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("aoccCount_Stmt");
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up a binding for tmp in the env.  If found, return the bound
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, and set the env's binding to NULL so it is marked as
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used.  If not found, return NULL. */
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* atbSubst_Temp ( ATmpInfo* env, IRTemp tmp )
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[i].binder == tmp && env[i].bindee != NULL) {
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* bindee = env[i].bindee;
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[i].bindee = NULL;
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return bindee;
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Traverse e, looking for temps.  For each observed temp, see if env
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   contains a binding for the temp, and if so return the bound value.
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The env has the property that any binding it holds is
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'single-shot', so once a binding is used, it is marked as no longer
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   available, by setting its .bindee field to NULL. */
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool is_Unop ( IRExpr* e, IROp op ) {
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Unop && e->Iex.Unop.op == op;
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool is_Binop ( IRExpr* e, IROp op ) {
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Binop && e->Iex.Binop.op == op;
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_IRExpr_Binop ( IROp op, IRExpr* a1, IRExpr* a2 )
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_Or32:
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Or32( CmpwNEZ32(x), CmpwNEZ32(y) ) --> CmpwNEZ32( Or32( x, y ) )  */
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(a1, Iop_CmpwNEZ32) && is_Unop(a2, Iop_CmpwNEZ32))
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32,
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Binop( Iop_Or32, a1->Iex.Unop.arg,
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     a2->Iex.Unop.arg ) );
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Iop_CmpNE32:
4656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Since X has type Ity_I1 we can simplify:
4657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         CmpNE32(1Uto32(X),0)) ==> X */
4658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(a1, Iop_1Uto32) && isZeroU32(a2))
4659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return a1->Iex.Unop.arg;
4660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
4661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no reduction rule applies */
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop( op, a1, a2 );
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_IRExpr_Unop ( IROp op, IRExpr* aa )
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpwNEZ64:
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64( Or64 ( CmpwNEZ64(x), y ) ) --> CmpwNEZ64( Or64( x, y ) ) */
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Binop(aa, Iop_Or64)
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Binop.arg1, Iop_CmpwNEZ64))
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Iop_CmpwNEZ64,
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Binop(Iop_Or64,
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg1->Iex.Unop.arg,
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg2));
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64( Or64 ( x, CmpwNEZ64(y) ) ) --> CmpwNEZ64( Or64( x, y ) ) */
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Binop(aa, Iop_Or64)
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Binop.arg2, Iop_CmpwNEZ64))
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Iop_CmpwNEZ64,
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Binop(Iop_Or64,
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg1,
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg2->Iex.Unop.arg));
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpNEZ64:
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpNEZ64( Left64(x) ) --> CmpNEZ64(x) */
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left64))
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_CmpNEZ64, aa->Iex.Unop.arg);
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpwNEZ32:
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ32( CmpwNEZ32 ( x ) ) --> CmpwNEZ32 ( x ) */
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ32))
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32, aa->Iex.Unop.arg );
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpNEZ32:
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpNEZ32( Left32(x) ) --> CmpNEZ32(x) */
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left32))
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_CmpNEZ32, aa->Iex.Unop.arg);
4704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* CmpNEZ32( 1Uto32(X) ) --> X */
4705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(aa, Iop_1Uto32))
4706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return aa->Iex.Unop.arg;
4707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
4708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Iop_CmpNEZ8:
4709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* CmpNEZ8( 1Uto8(X) ) --> X */
4710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(aa, Iop_1Uto8))
4711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return aa->Iex.Unop.arg;
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_Left32:
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Left32( Left32(x) ) --> Left32(x) */
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left32))
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_Left32, aa->Iex.Unop.arg );
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_32to1:
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32to1( 1Uto32 ( x ) ) --> x */
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_1Uto32))
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32to1( CmpwNEZ32 ( x )) --> CmpNEZ32(x) */
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ32))
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpNEZ32, aa->Iex.Unop.arg );
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_64to1:
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to1( 1Uto64 ( x ) ) --> x */
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_1Uto64))
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to1( CmpwNEZ64 ( x )) --> CmpNEZ64(x) */
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ64))
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpNEZ64, aa->Iex.Unop.arg );
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_64to32:
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to32( 32Uto64 ( x )) --> x */
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_32Uto64))
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to32( 8Uto64 ( x )) --> 8Uto32(x) */
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_8Uto64))
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_8Uto32, aa->Iex.Unop.arg);
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_32Uto64:
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64( 8Uto32( x )) --> 8Uto64(x) */
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_8Uto32))
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_8Uto64, aa->Iex.Unop.arg);
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64( 16Uto32( x )) --> 16Uto64(x) */
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_16Uto32))
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_16Uto64, aa->Iex.Unop.arg);
4750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 32Uto64(64to32( Shr64( 32Uto64(64to32(x)), sh ))
4751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     --> Shr64( 32Uto64(64to32(x)), sh )) */
4752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (is_Unop(aa, Iop_64to32)
4753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Binop(aa->Iex.Unop.arg, Iop_Shr64)
4754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1, Iop_32Uto64)
4755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg,
4756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Iop_64to32)) {
4757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return aa->Iex.Unop.arg;
4758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /*     32Uto64(64to32( Shl64( 32Uto64(64to32(x)), sh ))
4760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         --> 32Uto64(64to32( Shl64(                x,   sh )) */
4761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (is_Unop(aa, Iop_64to32)
4762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Binop(aa->Iex.Unop.arg, Iop_Shl64)
4763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1, Iop_32Uto64)
4764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg,
4765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Iop_64to32)) {
4766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return
4767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr_Unop(
4768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Iop_32Uto64,
4769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr_Unop(
4770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Iop_64to32,
4771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRExpr_Binop(
4772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Iop_Shl64,
4773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg->Iex.Unop.arg,
4774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     aa->Iex.Unop.arg->Iex.Binop.arg2
4775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )));
4776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_1Sto32:
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Sto32( CmpNEZ8( 32to8( 1Uto32( CmpNEZ32( x ))))) -> CmpwNEZ32(x) */
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpNEZ8)
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg, Iop_32to8)
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg, Iop_1Uto32)
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg->Iex.Unop.arg,
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_CmpNEZ32)) {
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32,
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             aa->Iex.Unop.arg->Iex.Unop.arg
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ->Iex.Unop.arg->Iex.Unop.arg);
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no reduction rule applies */
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop( op, aa );
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* atbSubst_Expr ( ATmpInfo* env, IRExpr* e )
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  e2;
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args2;
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         args2 = shallowCopyIRExprVec(e->Iex.CCall.args);
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args2[i]; i++)
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args2[i] = atbSubst_Expr(env,args2[i]);
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_CCall(
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.CCall.cee,
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.CCall.retty,
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   args2
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = atbSubst_Temp(env, e->Iex.RdTmp.tmp);
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e2 ? e2 : e;
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Mux0X(
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Mux0X.cond),
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Mux0X.expr0),
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Mux0X.exprX)
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Qop(
4827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Qop.details->op,
4828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg1),
4829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg2),
4830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg3),
4831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg4)
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Triop(
4835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Triop.details->op,
4836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Triop.details->arg1),
4837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Triop.details->arg2),
4838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Triop.details->arg3)
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Binop(
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.op,
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Binop.arg1),
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Binop.arg2)
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Unop.op,
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Unop.arg)
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Load(
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Load.end,
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Load.ty,
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Load.addr)
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.descr,
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.GetI.ix),
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.bias
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e;
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("atbSubst_Expr");
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same deal as atbSubst_Expr, except for stmts. */
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty *d, *d2;
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS   *cas, *cas2;
4879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI  *puti, *puti2;
4880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_AbiHint(
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.AbiHint.base),
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.AbiHint.len,
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.AbiHint.nia)
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Store(
4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Store.end,
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Store.addr),
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Store.data)
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_WrTmp(
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.WrTmp.tmp,
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.WrTmp.data)
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Put(
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Put.offset,
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Put.data)
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
4905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti  = st->Ist.PutI.details;
4906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti2 = mkIRPutI(puti->descr,
4907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          atbSubst_Expr(env, puti->ix),
4908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          puti->bias,
4909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          atbSubst_Expr(env, puti->data));
4910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRStmt_PutI(puti2);
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Exit(
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Exit.guard),
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Exit.jk,
4916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   st->Ist.Exit.dst,
4917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   st->Ist.Exit.offsIP
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return IRStmt_IMark(st->Ist.IMark.addr,
4921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.len,
4922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.delta);
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_NoOp();
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_MBE(st->Ist.MBE.event);
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas  = st->Ist.CAS.details;
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS(
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->oldHi, cas->oldLo, cas->end,
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->addr),
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->expdHi ? atbSubst_Expr(env, cas->expdHi) : NULL,
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->expdLo),
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->dataHi ? atbSubst_Expr(env, cas->dataHi) : NULL,
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->dataLo)
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_CAS(cas2);
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_LLSC(
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.end,
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.result,
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.LLSC.addr),
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.storedata
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? atbSubst_Expr(env, st->Ist.LLSC.storedata) : NULL
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d  = st->Ist.Dirty.details;
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None)
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = atbSubst_Expr(env, d2->mAddr);
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = atbSubst_Expr(env, d2->guard);
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++)
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->args[i] = atbSubst_Expr(env, d2->args[i]);
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Dirty(d2);
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("atbSubst_Stmt");
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* notstatic */ Addr64 ado_treebuild_BB ( IRSB* bb )
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j, k, m;
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     stmtPuts, stmtStores, invalidateMe;
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st2;
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ATmpInfo env[A_NENV];
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool   max_ga_known = False;
4971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Addr64 max_ga       = 0;
4972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       n_tmps = bb->tyenv->types_used;
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort*   uses   = LibVEX_Alloc(n_tmps * sizeof(UShort));
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Phase 1.  Scan forwards in bb, counting use occurrences of each
4977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      temp.  Also count occurrences in the bb->next field.  Take the
4978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      opportunity to also find the maximum guest address in the block,
4979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      since that will be needed later for deciding when we can safely
4980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      elide event checks. */
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uses[i] = 0;
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
4987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (st->tag) {
4988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ist_NoOp:
4989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
4990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ist_IMark: {
4991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int    len = st->Ist.IMark.len;
4992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Addr64 mga = st->Ist.IMark.addr + (len < 1 ? 1 : len) - 1;
4993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            max_ga_known = True;
4994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (mga > max_ga)
4995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               max_ga = mga;
4996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
4999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
5000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aoccCount_Stmt( uses, st );
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   aoccCount_Expr(uses, bb->next );
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++) {
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uses[i] == 0)
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        continue;
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRTemp( (IRTemp)i );
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("  used %d\n", (Int)uses[i] );
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Phase 2.  Scan forwards in bb.  For each statement in turn:
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         If the env is full, emit the end element.  This guarantees
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         there is at least one free slot in the following.
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         On seeing 't = E', occ(t)==1,
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let E'=env(E)
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete this stmt
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add t -> E' to the front of the env
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Examine E' and set the hints for E' appropriately
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (doesLoad? doesGet?)
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         On seeing any other stmt,
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let stmt' = env(stmt)
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove from env any 't=E' binds invalidated by stmt
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                emit the invalidated stmts
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit stmt'
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compact any holes in env
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              by sliding entries towards the front
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Finally, apply env to bb->next.
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i].bindee = NULL;
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i].binder = IRTemp_INVALID;
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The stmts in bb are being reordered, and we are guaranteed to
5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      end up with no more than the number we started with.  Use i to
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be the cursor of the current stmt examined and j <= i to be that
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for the current stmt being written.
5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ensure there's at least one space in the env, by emitting
5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the oldest binding if necessary. */
5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[A_NENV-1].bindee != NULL) {
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[j] = IRStmt_WrTmp( env[A_NENV-1].binder,
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      env[A_NENV-1].bindee );
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j++;
5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(j <= i);
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[A_NENV-1].bindee = NULL;
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Consider current stmt. */
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp && uses[st->Ist.WrTmp.tmp] <= 1) {
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr *e, *e2;
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* optional extra: dump dead bindings as we find them.
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Removes the need for a prior dead-code removal pass. */
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (uses[st->Ist.WrTmp.tmp] == 0) {
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (0) vex_printf("DEAD binding\n");
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(uses[st->Ist.WrTmp.tmp] == 1);
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ok, we have 't = E', occ(t)==1.  Do the abovementioned
5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            actions. */
5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e  = st->Ist.WrTmp.data;
5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = atbSubst_Expr(env, e);
5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToEnvFront(env, st->Ist.WrTmp.tmp, e2);
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setHints_Expr(&env[0].doesLoad, &env[0].doesGet, e2);
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* don't advance j, as we are deleting this stmt and instead
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            holding it temporarily in the env. */
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we get here for any other kind of statement. */
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 'use up' any bindings required by the current statement. */
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = atbSubst_Stmt(env, st);
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, before this stmt, dump any bindings in env that it
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidates.  These need to be dumped in the order in which
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         they originally entered env -- that means from oldest to
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         youngest. */
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* stmtPuts/stmtStores characterise what the stmt under
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consideration does, or might do (sidely safe @ True). */
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmtPuts
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toBool( st->tag == Ist_Put
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_PutI
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_Dirty );
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be True if this stmt writes memory or might do (==> we don't
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         want to reorder other loads or stores relative to it).  Also,
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         both LL and SC fall under this classification, since we
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         really ought to be conservative and not reorder any other
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memory transactions relative to them. */
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmtStores
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toBool( st->tag == Ist_Store
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   || st->tag == Ist_Dirty
5111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || st->tag == Ist_LLSC
5112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || st->tag == Ist_CAS );
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = A_NENV-1; k >= 0; k--) {
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[k].bindee == NULL)
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compare the actions of this stmt with the actions of
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binding 'k', to see if they invalidate the binding. */
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidateMe
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = toBool(
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a store invalidates loaded data */
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (env[k].doesLoad && stmtStores)
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a put invalidates get'd data */
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || (env[k].doesGet && stmtPuts)
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a put invalidates loaded data.  Note, we could do
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 much better here in the sense that we only need to
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 invalidate trees containing loads if the Put in
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 question is marked as requiring precise
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 exceptions. */
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || (env[k].doesLoad && stmtPuts)
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* probably overly conservative: a memory bus event
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 invalidates absolutely everything, so that all
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 computation prior to it is forced to complete before
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 proceeding with the event (fence,lock,unlock). */
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || st->tag == Ist_MBE
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* also be (probably overly) paranoid re AbiHints */
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || st->tag == Ist_AbiHint
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (invalidateMe) {
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[j] = IRStmt_WrTmp( env[k].binder, env[k].bindee );
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            j++;
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(j <= i);
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env[k].bindee = NULL;
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Slide in-use entries in env up to the front */
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      m = 0;
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = 0; k < A_NENV; k++) {
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[k].bindee != NULL) {
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env[m] = env[k];
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            m++;
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (m = m; m < A_NENV; m++) {
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[m].bindee = NULL;
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* finally, emit the substituted statement */
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->stmts[j] = st2;
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("**2  "); ppIRStmt(bb->stmts[j]); vex_printf("\n"); */
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      j++;
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(j <= i+1);
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for each stmt in the original bb ... */
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally ... substitute the ->next field as much as possible, and
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dump any left-over bindings.  Hmm.  Perhaps there should be no
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      left over bindings?  Or any left-over bindings are
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by definition dead? */
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->next = atbSubst_Expr(env, bb->next);
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->stmts_used = j;
5173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return max_ga_known ? max_ga : ~(Addr64)0;
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- iropt main                                              ---*/
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool iropt_verbose = False; /* True; */
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a simple cleanup pass on bb.  This is: redundant Get removal,
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant Put removal, constant propagation, dead code removal,
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clean helper specialisation, and dead code removal (again).
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cheap_transformations (
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb,
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* (*specHelper) (HChar*, IRExpr**, IRStmt**, Int),
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool (*preciseMemExnsFn)(Int,Int)
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant_get_removal_BB ( bb );
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= REDUNDANT GET\n\n" );
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) {
5205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      redundant_put_removal_BB ( bb, preciseMemExnsFn );
5206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= REDUNDANT PUT\n\n" );
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = cprop_BB ( bb );
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= CPROPD\n\n" );
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB ( bb );
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= DEAD\n\n" );
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = spec_helpers_BB ( bb, specHelper );
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB ( bb );
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= SPECd \n\n" );
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do some more expensive transformations on bb, which are aimed at
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimising as much as possible in the presence of GetI and PutI.  */
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* expensive_transformations( IRSB* bb )
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (void)do_cse_BB( bb );
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   collapse_AddSub_chains_BB( bb );
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_redundant_GetI_elimination( bb );
5244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) {
5245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_redundant_PutI_elimination( bb );
5246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB( bb );
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan a flattened BB to look for signs that more expensive
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisations might be useful:
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - find out if there are any GetIs and PutIs
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - find out if there are any floating or vector-typed temporaries
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void considerExpensives ( /*OUT*/Bool* hasGetIorPutI,
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/Bool* hasVorFtemps,
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRSB* bb )
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j;
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *hasGetIorPutI = False;
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *hasVorFtemps  = False;
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_AbiHint:
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.AbiHint.base));
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.AbiHint.nia));
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *hasGetIorPutI = True;
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp:
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.WrTmp.data->tag == Iex_GetI)
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *hasGetIorPutI = True;
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp)) {
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I1: case Ity_I8: case Ity_I16:
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I32: case Ity_I64: case Ity_I128:
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
5287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Ity_F32: case Ity_F64: case Ity_F128:
5288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Ity_V128: case Ity_V256:
5289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  *hasVorFtemps = True;
5290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
5291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Ity_D32: case Ity_D64: case Ity_D128:
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *hasVorFtemps = True;
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  goto bad;
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Put.data));
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Store:
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Store.addr));
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Store.data));
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS:
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cas = st->Ist.CAS.details;
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->addr));
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->expdLo));
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->dataLo));
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC:
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.LLSC.addr));
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.LLSC.storedata)
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(st->Ist.LLSC.storedata));
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty:
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d = st->Ist.Dirty.details;
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d->guard));
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = 0; d->args[j]; j++)
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(d->args[j]));
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->mFx != Ifx_None)
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(d->mAddr));
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp:
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_IMark:
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_MBE:
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Exit:
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Exit.guard));
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bad:
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("considerExpensives");
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- The main iropt entry point. ---------------- */
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* exported from this file */
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Rules of the game:
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - IRExpr/IRStmt trees should be treated as immutable, as they
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     may get shared.  So never change a field of such a tree node;
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     instead construct and return a new one if needed.
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* do_iropt_BB(
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb0,
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* (*specHelper) (HChar*, IRExpr**, IRStmt**, Int),
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool (*preciseMemExnsFn)(Int,Int),
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr64 guest_addr,
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VexArch guest_arch
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_total     = 0;
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_expensive = 0;
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool hasGetIorPutI, hasVorFtemps;
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB *bb, *bb2;
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_total++;
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First flatten the block out, since all other
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      phases assume flat code. */
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = flatten_BB ( bb0 );
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= FLAT\n\n" );
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If at level 0, stop now. */
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_level <= 0) return bb;
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now do a preliminary cleanup pass, and figure out if we also
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need to do 'expensive' optimisations.  Expensive optimisations
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are deemed necessary if the block contains any GetIs or PutIs.
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If needed, do expensive transformations and then another cheap
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cleanup pass. */
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guest_arch == VexArchARM) {
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Translating Thumb2 code produces a lot of chaff.  We have to
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         work extra hard to get rid of it. */
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = cprop_BB(bb);
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = spec_helpers_BB ( bb, specHelper );
5395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) {
5396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         redundant_put_removal_BB ( bb, preciseMemExnsFn );
5397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      do_cse_BB( bb );
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_deadcode_BB( bb );
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_level > 1) {
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Peer at what we have, to decide how much more effort to throw
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at it. */
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      considerExpensives( &hasGetIorPutI, &hasVorFtemps, bb );
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (hasVorFtemps && !hasGetIorPutI) {
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If any evidence of FP or Vector activity, CSE, as that
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tends to mop up all manner of lardy code to do with
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rounding modes.  Don't bother if hasGetIorPutI since that
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case leads into the expensive transformations, which do
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CSE anyway. */
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void)do_cse_BB( bb );
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_deadcode_BB( bb );
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (hasGetIorPutI) {
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool cses;
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_expensive++;
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT)
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive);
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = expensive_transformations( bb );
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Potentially common up GetIs */
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cses = do_cse_BB( bb );
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cses)
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now have a go at unrolling simple (single-BB) loops.  If
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         successful, clean up the results as much as possible. */
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb2 = maybe_loop_unroll_BB( bb, guest_addr );
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb2) {
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn );
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (hasGetIorPutI) {
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = expensive_transformations( bb );
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* at least do CSE and dead code removal */
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_cse_BB( bb );
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_deadcode_BB( bb );
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) vex_printf("vex iropt: unrolled a loop\n");
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                            ir_opt.c ---*/
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5457