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
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2004-2013 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
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   * If iropt_register_updates == VexRegUpdSpAtMemAccess :
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     The guest state is only up to date only as explained above
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     (i.e. at SB exits and as specified by dirty helper call).
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     Also, the stack pointer register is up to date at memory
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     exception points (as this is needed for the stack extension
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     logic in m_signals.c).
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   * If iropt_register_updates == VexRegUpdUnwindregsAtMemAccess :
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Immediately prior to any load or store, those parts of the guest
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     state marked as requiring precise exceptions will be up to date.
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Also, guest memory will be up to date.  Parts of the guest state
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     not marked as requiring precise exceptions cannot be assumed to
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     be up-to-date at the point of the load/store.
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   * If iropt_register_updates == VexRegUpdAllregsAtMemAccess:
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Same as minimal, but all the guest state is up to date at memory
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     exception points.
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   * If iropt_register_updates == VexRegUpdAllregsAtEachInsn :
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Guest state is up to date at each instruction.
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The relative order of loads and stores (including loads/stores of
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest memory done by dirty helpers annotated as such) is not
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   changed.  However, the relative order of loads with no intervening
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stores/modifies may be changed.
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Transformation order
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ~~~~~~~~~~~~~~~~~~~~
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There are three levels of optimisation, controlled by
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_control.iropt_level.  Define first:
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Cheap transformations" are the following sequence:
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-Get removal
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-Put removal
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Constant propagation/folding
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Specialisation of clean helper functions
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Expensive transformations" are the following sequence:
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * CSE
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Folding of add/sub chains
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-GetI removal
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Redundant-PutI removal
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Dead code removal
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Then the transformations are as follows, as defined by
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_control.iropt_level:
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 0:
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 1: the following sequence:
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Cheap transformations.
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Level 2: the following sequence
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Flatten into atomic form.
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Cheap transformations.
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If block contains any floating or vector types, CSE.
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If block contains GetI or PutI, Expensive transformations.
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * Try unrolling loops.  Three possible outcomes:
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - No effect: do nothing more.
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - Unrolled a loop, and block does not contain GetI or PutI:
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Do: * CSE
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              * Dead code removal
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - Unrolled a loop, and block contains GetI or PutI:
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Do: * Expensive transformations
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              * Cheap transformations
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Implementation notes, 29 Dec 04.
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO (important): I think rPutI removal ignores precise exceptions
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and is therefore in a sense, wrong.  In the sense that PutIs are
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assumed not to write parts of the guest state that we need to have
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   up-to-date at loads/stores.  So far on x86 guest that has not
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mattered since indeed only the x87 FP registers and tags are
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accessed using GetI/PutI, and there is no need so far for them to
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be up to date at mem exception points.  The rPutI pass should be
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fixed.
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: improve pessimistic handling of precise exceptions
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     in the tree builder.
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: check interaction of rGetI and dirty helpers.
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   F64i constants are treated differently from other constants.
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   They are not regarded as atoms, and instead lifted off and
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bound to temps.  This allows them to participate in CSE, which
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is important for getting good performance for x86 guest code.
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CSE up F64 literals (already doing F64is)
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CSE: consider carefully the requirement for precise exns
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        prior to making CSE any more aggressive.  */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Finite mappery, of a sort                               ---*/
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* General map from HWord-sized thing HWord-sized thing.  Could be by
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hashing, but it's not clear whether or not this would really be any
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   faster. */
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool*  inuse;
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* key;
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* val;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    size;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    used;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW;
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HashHW* newHHW ( void )
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* h = LibVEX_Alloc(sizeof(HashHW));
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->size   = 8;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->used   = 0;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->inuse  = LibVEX_Alloc(h->size * sizeof(Bool));
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->key    = LibVEX_Alloc(h->size * sizeof(HWord));
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->val    = LibVEX_Alloc(h->size * sizeof(HWord));
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return h;
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up key in the map. */
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool lookupHHW ( HashHW* h, /*OUT*/HWord* val, HWord key )
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("lookupHHW(%llx)\n", key ); */
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < h->used; i++) {
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h->inuse[i] && h->key[i] == key) {
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (val)
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *val = h->val[i];
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add key->val to the map.  Replaces any existing binding for key. */
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addToHHW ( HashHW* h, HWord key, HWord val )
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i, j;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("addToHHW(%llx, %llx)\n", key, val); */
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Find and replace existing binding, if any. */
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < h->used; i++) {
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h->inuse[i] && h->key[i] == key) {
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h->val[i] = val;
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ensure a space is available. */
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (h->used == h->size) {
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Copy into arrays twice the size. */
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool*  inuse2 = LibVEX_Alloc(2 * h->size * sizeof(Bool));
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* key2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* val2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = j = 0; i < h->size; i++) {
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!h->inuse[i]) continue;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         inuse2[j] = True;
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         key2[j] = h->key[i];
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val2[j] = h->val[i];
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j++;
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->used = j;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->size *= 2;
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->inuse = inuse2;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->key = key2;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      h->val = val2;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, add it. */
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(h->used < h->size);
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->inuse[h->used] = True;
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->key[h->used] = key;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->val[h->used] = val;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   h->used++;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Flattening out a BB into atomic SSA form                ---*/
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Non-critical helper, heuristic for reducing the number of tmp-tmp
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   copies made by flattening.  If in doubt return False. */
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isFlat ( IRExpr* e )
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get)
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop)
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( isIRAtom(e->Iex.Binop.arg1)
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     && isIRAtom(e->Iex.Binop.arg2) );
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load)
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return isIRAtom(e->Iex.Load.addr);
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Flatten out 'ex' so it is atomic, returning a new expression with
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same value, after having appended extra IRTemp assignments to
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the end of 'bb'. */
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* flatten_Expr ( IRSB* bb, IRExpr* ex )
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** newargs;
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(bb->tyenv, ex);
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t1;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ex->tag) {
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_GetI(ex->Iex.GetI.descr,
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.GetI.ix),
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ex->Iex.GetI.bias)));
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb,
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRStmt_WrTmp(t1, ex));
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Qop: {
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRQop* qop = ex->Iex.Qop.details;
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr_Qop(qop->op,
313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg1),
314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg2),
315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg3),
316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, qop->arg4))));
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Triop: {
321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop* triop = ex->Iex.Triop.details;
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr_Triop(triop->op,
325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, triop->arg1),
326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, triop->arg2),
327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         flatten_Expr(bb, triop->arg3))));
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Binop(ex->Iex.Binop.op,
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Binop.arg1),
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         flatten_Expr(bb, ex->Iex.Binop.arg2))));
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Unop(ex->Iex.Unop.op,
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.Unop.arg))));
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Load(ex->Iex.Load.end,
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ex->Iex.Load.ty,
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        flatten_Expr(bb, ex->Iex.Load.addr))));
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         newargs = shallowCopyIRExprVec(ex->Iex.CCall.args);
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; newargs[i]; i++)
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            newargs[i] = flatten_Expr(bb, newargs[i]);
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_CCall(ex->Iex.CCall.cee,
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ex->Iex.CCall.retty,
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         newargs)));
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = newIRTemp(bb->tyenv, ty);
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr_ITE(flatten_Expr(bb, ex->Iex.ITE.cond),
369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       flatten_Expr(bb, ex->Iex.ITE.iftrue),
370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       flatten_Expr(bb, ex->Iex.ITE.iffalse))));
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp(t1);
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Lift F64i constants out onto temps so they can be CSEd
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            later. */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ex->Iex.Const.con->tag == Ico_F64i) {
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t1 = newIRTemp(bb->tyenv, ty);
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_WrTmp(t1,
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Const(ex->Iex.Const.con)));
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return IRExpr_RdTmp(t1);
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Leave all other constants alone. */
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ex;
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ex;
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ex);
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("flatten_Expr");
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Append a completely flattened form of 'st' to the end of 'bb'. */
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flatten_Stmt ( IRSB* bb, IRStmt* st )
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRExpr   *e1, *e2, *e3, *e4, *e5;
404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRDirty  *d,  *d2;
405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRCAS    *cas, *cas2;
406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRPutI   *puti, *puti2;
407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRLoadG  *lg;
408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRStoreG *sg;
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isIRAtom(st->Ist.Put.data)) {
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* optimisation to reduce the amount of heap wasted
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               by the flattener */
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, st);
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* general case, always correct */
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e1 = flatten_Expr(bb, st->Ist.Put.data);
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti = st->Ist.PutI.details;
423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         e1 = flatten_Expr(bb, puti->ix);
424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         e2 = flatten_Expr(bb, puti->data);
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti2 = mkIRPutI(puti->descr, e1, puti->bias, e2);
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addStmtToIRSB(bb, IRStmt_PutI(puti2));
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isFlat(st->Ist.WrTmp.data)) {
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* optimisation, to reduce the number of tmp-tmp
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               copies generated */
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, st);
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* general case, always correct */
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e1 = flatten_Expr(bb, st->Ist.WrTmp.data);
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addStmtToIRSB(bb, IRStmt_WrTmp(st->Ist.WrTmp.tmp, e1));
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.Store.addr);
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.Store.data);
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Store(st->Ist.Store.end, e1,e2));
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG:
445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         sg = st->Ist.StoreG.details;
446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e1 = flatten_Expr(bb, sg->addr);
447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e2 = flatten_Expr(bb, sg->data);
448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e3 = flatten_Expr(bb, sg->guard);
449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addStmtToIRSB(bb, IRStmt_StoreG(sg->end, e1, e2, e3));
450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG:
452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         lg = st->Ist.LoadG.details;
453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e1 = flatten_Expr(bb, lg->addr);
454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e2 = flatten_Expr(bb, lg->alt);
455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e3 = flatten_Expr(bb, lg->guard);
456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addStmtToIRSB(bb, IRStmt_LoadG(lg->end, lg->cvt, lg->dst,
457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        e1, e2, e3));
458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas  = st->Ist.CAS.details;
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1   = flatten_Expr(bb, cas->addr);
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2   = cas->expdHi ? flatten_Expr(bb, cas->expdHi) : NULL;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e3   = flatten_Expr(bb, cas->expdLo);
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e4   = cas->dataHi ? flatten_Expr(bb, cas->dataHi) : NULL;
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e5   = flatten_Expr(bb, cas->dataLo);
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS( cas->oldHi, cas->oldLo, cas->end,
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         e1, e2, e3, e4, e5 );
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_CAS(cas2));
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.LLSC.addr);
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = st->Ist.LLSC.storedata
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ? flatten_Expr(bb, st->Ist.LLSC.storedata)
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 : NULL;
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_LLSC(st->Ist.LLSC.end,
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       st->Ist.LLSC.result, e1, e2));
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->args = shallowCopyIRExprVec(d2->args);
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None) {
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = flatten_Expr(bb, d2->mAddr);
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(d2->mAddr == NULL);
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = flatten_Expr(bb, d2->guard);
489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         for (i = 0; d2->args[i]; i++) {
490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr* arg = d2->args[i];
491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               d2->args[i] = flatten_Expr(bb, arg);
493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Dirty(d2));
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.AbiHint.base);
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = flatten_Expr(bb, st->Ist.AbiHint.nia);
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len, e2));
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1 = flatten_Expr(bb, st->Ist.Exit.guard);
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, IRStmt_Exit(e1, st->Ist.Exit.jk,
509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       st->Ist.Exit.dst,
510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       st->Ist.Exit.offsIP));
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("flatten_Stmt");
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* flatten_BB ( IRSB* in )
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   i;
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB* out;
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out = emptyIRSB();
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < in->stmts_used; i++)
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (in->stmts[i])
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         flatten_Stmt( out, in->stmts[i] );
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->next     = flatten_Expr( out, in->next );
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->jumpkind = in->jumpkind;
532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   out->offsIP   = in->offsIP;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return out;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- In-place removal of redundant GETs                      ---*/
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan forwards, building up an environment binding (min offset, max
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset) pairs to values, which will either be temps or constants.
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 't = Get(minoff,maxoff)', look up (minoff,maxoff) in the
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env and if it matches, replace the Get with the stored value.  If
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there is no match, add a (minoff,maxoff) :-> t binding.
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Put (minoff,maxoff) = t or c', first remove in the env
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   any binding which fully or partially overlaps with (minoff,maxoff).
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Then add a new (minoff,maxoff) :-> t or c binding.  */
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract the min/max offsets from a guest state array descriptor. */
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void getArrayBounds ( IRRegArray* descr,
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UInt* minoff, UInt* maxoff )
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *minoff = descr->base;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *maxoff = *minoff + descr->nElems*sizeofIRType(descr->elemTy) - 1;
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((*minoff & ~0xFFFF) == 0);
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((*maxoff & ~0xFFFF) == 0);
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(*minoff <= *maxoff);
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create keys, of the form ((minoffset << 16) | maxoffset). */
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt mk_key_GetPut ( Int offset, IRType ty )
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* offset should fit in 16 bits. */
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff = offset;
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt maxoff = minoff + sizeofIRType(ty) - 1;
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((minoff & ~0xFFFF) == 0);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((maxoff & ~0xFFFF) == 0);
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (minoff << 16) | maxoff;
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt mk_key_GetIPutI ( IRRegArray* descr )
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff, maxoff;
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr, &minoff, &maxoff );
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((minoff & ~0xFFFF) == 0);
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert((maxoff & ~0xFFFF) == 0);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (minoff << 16) | maxoff;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Supposing h has keys of the form generated by mk_key_GetPut and
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mk_key_GetIPutI, invalidate any key which overlaps (k_lo
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   .. k_hi).
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void invalidateOverlaps ( HashHW* h, UInt k_lo, UInt k_hi )
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  j;
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt e_lo, e_hi;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(k_lo <= k_hi);
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* invalidate any env entries which in any way overlap (k_lo
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. k_hi) */
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("invalidate %d .. %d\n", k_lo, k_hi ); */
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < h->used; j++) {
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!h->inuse[j])
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e_lo = (((UInt)h->key[j]) >> 16) & 0xFFFF;
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e_hi = ((UInt)h->key[j]) & 0xFFFF;
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e_lo <= e_hi);
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e_hi < k_lo || k_hi < e_lo)
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* no overlap possible */
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* overlap; invalidate */
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         h->inuse[j] = False;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void redundant_get_removal_BB ( IRSB* bb )
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* env = newHHW();
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j;
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord   val;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRStmt* st = bb->stmts[i];
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Gets */
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_Get) {
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* st is 't = Get(...)'.  Look up in the environment and see
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if the Get can be replaced. */
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* get = st->Ist.WrTmp.data;
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         key = (HWord)mk_key_GetPut( get->Iex.Get.offset,
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     get->Iex.Get.ty );
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (lookupHHW(env, &val, (HWord)key)) {
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* found it */
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note, we could do better here.  If the types are
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               different we don't do the substitution, since doing so
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               could lead to invalidly-typed IR.  An improvement would
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               be to stick in a reinterpret-style cast, although that
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               would make maintaining flatness more difficult. */
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* valE    = (IRExpr*)val;
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool    typesOK = toBool( typeOfIRExpr(bb->tyenv,valE)
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      == st->Ist.WrTmp.data->Iex.Get.ty );
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typesOK && DEBUG_IROPT) {
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rGET: "); ppIRExpr(get);
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("  ->  "); ppIRExpr(valE);
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typesOK)
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, valE);
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Not found, but at least we know that t and the Get(...)
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               are now associated.  So add a binding to reflect that
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fact. */
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addToHHW( env, (HWord)key,
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (HWord)(void*)(IRExpr_RdTmp(st->Ist.WrTmp.tmp)) );
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Puts: invalidate any env entries overlapped by this
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Put */
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put || st->tag == Ist_PutI) {
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt k_lo, k_hi;
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag == Ist_Put) {
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetPut( st->Ist.Put.offset,
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(st->tag == Ist_PutI);
670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k_lo = (key >> 16) & 0xFFFF;
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k_hi = key & 0xFFFF;
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidateOverlaps(env, k_lo, k_hi);
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty) {
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Deal with dirty helpers which write or modify guest state.
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Invalidate the entire env.  We could do a lot better
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            here. */
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty* d      = st->Ist.Dirty.details;
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool     writes = False;
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < d->nFxState; j++) {
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->fxState[j].fx == Ifx_Modify
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || d->fxState[j].fx == Ifx_Write)
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            writes = True;
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (writes) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* dump the entire env (not clever, but correct ...) */
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = 0; j < env->used; j++)
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               env->inuse[j] = False;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) vex_printf("rGET: trash env due to dirty helper\n");
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add this one to the env, if appropriate */
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Put.data));
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( env, (HWord)key, (HWord)(st->Ist.Put.data));
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for (i = 0; i < bb->stmts_used; i++) */
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- In-place removal of redundant PUTs                      ---*/
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find any Get uses in st and invalidate any partially or fully
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlapping ranges listed in env.  Due to the flattening phase, the
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only stmt kind we expect to find a Get on is IRStmt_WrTmp. */
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_gets_Stmt (
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HashHW* env,
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRStmt* st,
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool (*preciseMemExnsFn)(Int,Int)
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     j;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isGet;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    memRW = False;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the only interesting case.  Deal with Gets in the RHS
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expression. */
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e = st->Ist.WrTmp.data;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->tag) {
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Get:
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = True;
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               key = mk_key_GetPut ( e->Iex.Get.offset, e->Iex.Get.ty );
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_GetI:
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = True;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               key = mk_key_GetIPutI ( e->Iex.GetI.descr );
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Load:
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = False;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               memRW = True;
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               isGet = False;
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isGet) {
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt k_lo, k_hi;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k_lo = (key >> 16) & 0xFFFF;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k_hi = key & 0xFFFF;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalidateOverlaps(env, k_lo, k_hi);
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Be very conservative for dirty helper calls; dump the entire
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         environment.  The helper might read guest state, in which
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case it needs to be flushed first.  Also, the helper might
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         access guest memory, in which case all parts of the guest
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state requiring precise exceptions needs to be flushed.  The
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         crude solution is just to flush everything; we could easily
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         enough do a lot better if needed. */
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Probably also overly-conservative, but also dump everything
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if we hit a memory bus event (fence, lock, unlock).  Ditto
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AbiHints, CASs, LLs and SCs. */
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.base));
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.nia));
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < env->used; j++)
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* all other cases are boring. */
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.addr));
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.data));
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memRW = True;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(sg->addr));
789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(sg->data));
790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(sg->guard));
791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         memRW = True;
792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(lg->addr));
797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(lg->alt));
798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(lg->guard));
799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         memRW = True;
800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(st->Ist.PutI.details->ix));
808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(st->Ist.PutI.details->data));
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("handle_gets_Stmt");
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (memRW) {
823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* This statement accesses memory.  So we might need to dump all parts
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the environment corresponding to guest state that may not
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be reordered with respect to memory references.  That means
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at least the stack pointer. */
827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (vex_control.iropt_register_updates) {
828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case VexRegUpdAllregsAtMemAccess:
829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Precise exceptions required at mem access.
830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Flush all guest state. */
831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (j = 0; j < env->used; j++)
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               env->inuse[j] = False;
833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case VexRegUpdSpAtMemAccess:
835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* We need to dump the stack pointer
836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               (needed for stack extension in m_signals.c).
837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               preciseMemExnsFn will use vex_control.iropt_register_updates
838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               to verify only the sp is to be checked. */
839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* fallthrough */
840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case VexRegUpdUnwindregsAtMemAccess:
841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (j = 0; j < env->used; j++) {
842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (!env->inuse[j])
843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  continue;
844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Just flush the minimal amount required, as computed by
845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  preciseMemExnsFn. */
846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               HWord k_hi = env->key[j] & 0xFFFF;
848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (preciseMemExnsFn( k_lo, k_hi ))
849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  env->inuse[j] = False;
850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            // VexRegUpdAllregsAtEachInsn cannot happen here.
854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            // Neither any rubbish other value.
855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(0);
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (memRW) */
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan backwards, building up a set of (min offset, max
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset) pairs, indicating those parts of the guest state
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for which the next event is a write.
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing a conditional exit, empty the set.
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Put (minoff,maxoff) = t or c', if (minoff,maxoff) is
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   completely within the set, remove the Put.  Otherwise, add
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (minoff,maxoff) to the set.
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On seeing 'Get (minoff,maxoff)', remove any part of the set
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlapping (minoff,maxoff).  The same has to happen for any events
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which implicitly read parts of the guest state: dirty helper calls
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and loads/stores.
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void redundant_put_removal_BB (
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRSB* bb,
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool (*preciseMemExnsFn)(Int,Int)
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    isPut;
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    key = 0; /* keep gcc -O happy */
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
888436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn);
889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* env = newHHW();
891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Initialise the running env with the fact that the final exit
893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      writes the IP (or, whatever it claims to write.  We don't
894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      care.) */
895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   key = mk_key_GetPut(bb->offsIP, typeOfIRExpr(bb->tyenv, bb->next));
896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addToHHW(env, (HWord)key, 0);
897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And now scan backwards through the statements. */
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with conditional exits. */
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Exit) {
907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //Bool re_add;
908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Need to throw out from the env, any part of it which
909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            doesn't overlap with the guest state written by this exit.
910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Since the exit only writes one section, it's simplest to
911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do this: (1) check whether env contains a write that
912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            completely overlaps the write done by this exit; (2) empty
913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            out env; and (3) if (1) was true, add the write done by
914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            this exit.
915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            To make (1) a bit simpler, merely search for a write that
917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            exactly matches the one done by this exit.  That's safe
918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            because it will fail as often or more often than a full
919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            overlap check, and failure to find an overlapping write in
920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            env is the safe case (we just nuke env if that
921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            happens). */
922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //vassert(isIRAtom(st->Ist.Exit.guard));
923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (1) */
924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //key = mk_key_GetPut(st->Ist.Exit.offsIP,
925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //                    typeOfIRConst(st->Ist.Exit.dst));
926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //re_add = lookupHHW(env, NULL, key);
927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (2) */
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < env->used; j++)
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env->inuse[j] = False;
930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* (3) */
931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //if (0 && re_add)
932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         //   addToHHW(env, (HWord)key, 0);
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Puts */
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = True;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            key = mk_key_GetPut( st->Ist.Put.offset,
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Put.data));
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = True;
946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(isIRAtom(st->Ist.PutI.details->ix));
948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(isIRAtom(st->Ist.PutI.details->data));
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isPut = False;
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isPut && st->tag != Ist_PutI) {
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See if any single entry in env overlaps this Put.  This is
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            simplistic in that the transformation is valid if, say, two
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or more entries in the env overlap this Put, but the use of
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lookupHHW will only find a single entry which exactly
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            overlaps this Put.  This is suboptimal but safe. */
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (lookupHHW(env, NULL, (HWord)key)) {
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This Put is redundant because a later one will overwrite
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               it.  So NULL (nop) it out. */
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rPUT: "); ppIRStmt(st);
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i] = IRStmt_NoOp();
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We can't demonstrate that this Put is redundant, so add it
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to the running collection. */
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addToHHW(env, (HWord)key, 0);
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with Gets.  These remove bits of the environment since
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         appearance of a Get means that the next event for that slice
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the guest state is no longer a write, but a read.  Also
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deals with implicit reads of guest state needed to maintain
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         precise exceptions. */
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      handle_gets_Stmt( env, st, preciseMemExnsFn );
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constant propagation and folding                        ---*/
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often sameIRExprs was invoked */
991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt invocation_count;
992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often sameIRExprs recursed through IRTemp assignments */
993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt recursion_count;
994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often sameIRExprs found identical IRExprs */
995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt success_count;
996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How often recursing through assignments to IRTemps helped
997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   establishing equality. */
998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt recursion_success_count;
999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Whether or not recursing through an IRTemp assignment helped
1000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   establishing IRExpr equality for a given sameIRExprs invocation. */
1001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool recursion_helped;
1002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Whether or not a given sameIRExprs invocation recursed through an
1003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp assignment */
1004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool recursed;
1005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Maximum number of nodes ever visited when comparing two IRExprs. */
1006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt max_nodes_visited;
1007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif /* STATS_IROPT */
1008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Count the number of nodes visited for a given sameIRExprs invocation. */
1010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic UInt num_nodes_visited;
1011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Do not visit more than NODE_LIMIT nodes when comparing two IRExprs.
1013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This is to guard against performance degradation by visiting large
1014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   trees without success. */
1015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define NODE_LIMIT 30
1016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The env in this section is a map from IRTemp to IRExpr*,
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is, an array indexed by IRTemp. */
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Do both expressions compute the same value? The answer is generally
1022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   conservative, i.e. it will report that the expressions do not compute
1023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the same value when in fact they do. The reason is that we do not
1024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   keep track of changes in the guest state and memory. Thusly, two
1025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Get's, GetI's or Load's, even when accessing the same location, will be
1026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assumed to compute different values. After all the accesses may happen
1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at different times and the guest state / memory can have changed in
1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the meantime.
1029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   XXX IMPORTANT XXX the two expressions must have the same IR type.
1031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DO NOT CALL HERE WITH DIFFERENTLY-TYPED EXPRESSIONS. */
1032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* JRS 20-Mar-2012: split sameIRExprs_aux into a fast inlineable
1034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   wrapper that deals with the common tags-don't-match case, and a
1035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   slower out of line general case.  Saves a few insns. */
1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
1038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs_aux2 ( IRExpr** env, IRExpr* e1, IRExpr* e2 );
1039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenginline
1041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs_aux ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e1->tag != e2->tag) return False;
1044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return sameIRExprs_aux2(env, e1, e2);
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng__attribute__((noinline))
1048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs_aux2 ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (num_nodes_visited++ > NODE_LIMIT) return False;
1051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e1->tag) {
1053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_RdTmp:
1054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp) return True;
1055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env[e1->Iex.RdTmp.tmp] && env[e2->Iex.RdTmp.tmp]) {
1057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool same = sameIRExprs_aux(env, env[e1->Iex.RdTmp.tmp],
1058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        env[e2->Iex.RdTmp.tmp]);
1059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
1060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            recursed = True;
1061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (same) recursion_helped = True;
1062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
1063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return same;
1064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
1066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Get:
1068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_GetI:
1069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Load:
1070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Guest state / memory could have changed in the meantime. */
1071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
1072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Binop:
1074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool( e1->Iex.Binop.op == e2->Iex.Binop.op
1075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Binop.arg1,
1076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Binop.arg1 )
1077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Binop.arg2,
1078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Binop.arg2 ));
1079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Unop:
1081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool( e1->Iex.Unop.op == e2->Iex.Unop.op
1082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, e1->Iex.Unop.arg,
1083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 e2->Iex.Unop.arg ));
1084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Const: {
1086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c1 = e1->Iex.Const.con;
1087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c2 = e2->Iex.Const.con;
1088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(c1->tag == c2->tag);
1089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (c1->tag) {
1090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U1:   return toBool( c1->Ico.U1  == c2->Ico.U1 );
1091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U8:   return toBool( c1->Ico.U8  == c2->Ico.U8 );
1092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U16:  return toBool( c1->Ico.U16 == c2->Ico.U16 );
1093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U32:  return toBool( c1->Ico.U32 == c2->Ico.U32 );
1094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Ico_U64:  return toBool( c1->Ico.U64 == c2->Ico.U64 );
1095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default: break;
1096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Triop: {
1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop *tri1 = e1->Iex.Triop.details;
1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop *tri2 = e2->Iex.Triop.details;
1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool( tri1->op == tri2->op
1104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, tri1->arg1, tri2->arg1 )
1105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, tri1->arg2, tri2->arg2 )
1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        && sameIRExprs_aux( env, tri1->arg3, tri2->arg3 ));
1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
1110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return toBool(    sameIRExprs_aux( env, e1->Iex.ITE.cond,
1111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                 e2->Iex.ITE.cond )
1112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        && sameIRExprs_aux( env, e1->Iex.ITE.iftrue,
1113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                 e2->Iex.ITE.iftrue )
1114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        && sameIRExprs_aux( env, e1->Iex.ITE.iffalse,
1115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                 e2->Iex.ITE.iffalse ));
1116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
1118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Not very likely to be "same". */
1119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
1120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return False;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenginline
1126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sameIRExprs ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool same;
1129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   num_nodes_visited = 0;
1131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   same = sameIRExprs_aux(env, e1, e2);
1132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if STATS_IROPT
1134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ++invocation_count;
1135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (recursed) ++recursion_count;
1136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   success_count += same;
1137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (same && recursion_helped)
1138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ++recursion_success_count;
1139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (num_nodes_visited > max_nodes_visited)
1140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      max_nodes_visited = num_nodes_visited;
1141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   recursed = False; /* reset */
1142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   recursion_helped = False;  /* reset */
1143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif /* STATS_IROPT */
1144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return same;
1146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Debugging-only hack (not used in production runs): make a guess
1150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   whether sameIRExprs might assert due to the two args being of
1151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   different types.  If in doubt return False.  Is only used when
1152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   --vex-iropt-level > 0, that is, vex_control.iropt_verbosity > 0.
1153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bad because it duplicates functionality from typeOfIRExpr.  See
1154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   comment on the single use point below for rationale. */
1155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
1156663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengBool debug_only_hack_sameIRExprs_might_assert ( IRExpr* e1, IRExpr* e2 )
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e1->tag != e2->tag) return False;
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e1->tag) {
1160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Const: {
1161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* The only interesting case */
1162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c1 = e1->Iex.Const.con;
1163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst *c2 = e2->Iex.Const.con;
1164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return c1->tag != c2->tag;
1165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return False;
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Is this literally IRExpr_Const(IRConst_U32(0)) ? */
1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool isZeroU32 ( IRExpr* e )
1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toBool( e->tag == Iex_Const
1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->tag == Ico_U32
1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->Ico.U32 == 0);
1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Is this literally IRExpr_Const(IRConst_U64(0)) ? */
1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool isZeroU64 ( IRExpr* e )
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toBool( e->tag == Iex_Const
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->tag == Ico_U64
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  && e->Iex.Const.con->Ico.U64 == 0);
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Is this literally IRExpr_Const(IRConst_V128(0)) ? */
1190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool isZeroV128 ( IRExpr* e )
1191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return toBool( e->tag == Iex_Const
1193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  && e->Iex.Const.con->tag == Ico_V128
1194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  && e->Iex.Const.con->Ico.V128 == 0x0000);
1195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Is this literally IRExpr_Const(IRConst_V256(0)) ? */
1198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool isZeroV256 ( IRExpr* e )
1199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return toBool( e->tag == Iex_Const
1201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  && e->Iex.Const.con->tag == Ico_V256
1202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  && e->Iex.Const.con->Ico.V256 == 0x00000000);
1203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Is this an integer constant with value 0 ? */
1206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool isZeroU ( IRExpr* e )
1207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag != Iex_Const) return False;
1209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->Iex.Const.con->tag) {
1210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U1:    return toBool( e->Iex.Const.con->Ico.U1  == 0);
1211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U8:    return toBool( e->Iex.Const.con->Ico.U8  == 0);
1212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U16:   return toBool( e->Iex.Const.con->Ico.U16 == 0);
1213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U32:   return toBool( e->Iex.Const.con->Ico.U32 == 0);
1214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U64:   return toBool( e->Iex.Const.con->Ico.U64 == 0);
1215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: vpanic("isZeroU");
1216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Is this an integer constant with value 1---1b ? */
1220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool isOnesU ( IRExpr* e )
1221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag != Iex_Const) return False;
1223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->Iex.Const.con->tag) {
1224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U8:    return toBool( e->Iex.Const.con->Ico.U8  == 0xFF);
1225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U16:   return toBool( e->Iex.Const.con->Ico.U16 == 0xFFFF);
1226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U32:   return toBool( e->Iex.Const.con->Ico.U32
1227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     == 0xFFFFFFFF);
1228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ico_U64:   return toBool( e->Iex.Const.con->Ico.U64
1229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     == 0xFFFFFFFFFFFFFFFFULL);
1230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: ppIRExpr(e); vpanic("isOnesU");
1231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool notBool ( Bool b )
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b == True) return False;
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b == False) return True;
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("notBool");
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a zero which has the same type as the result of the given
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   primop. */
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkZeroOfPrimopResultType ( IROp op )
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpNE32: return IRExpr_Const(IRConst_U1(toBool(0)));
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8:  return IRExpr_Const(IRConst_U8(0));
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32:
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));
1251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_And64:
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64:
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));
1254eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      case Iop_XorV128:
1255eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      case Iop_AndV128: return IRExpr_Const(IRConst_V128(0));
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("mkZeroOfPrimopResultType: bad primop");
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a value containing all 1-bits, which has the same type as the
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result of the given primop. */
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkOnesOfPrimopResultType ( IROp op )
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpEQ32:
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_U1(toBool(1)));
1268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or8:
1269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_Const(IRConst_U8(0xFF));
1270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or16:
1271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_Const(IRConst_U16(0xFFFF));
1272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or32:
1273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_Const(IRConst_U32(0xFFFFFFFF));
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x8:
1275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Or64:
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_U64(0xFFFFFFFFFFFFFFFFULL));
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:
1278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpEQ16x8:
1279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpEQ32x4:
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_V128(0xFFFF));
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppIROp(op);
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mkOnesOfPrimopResultType: bad primop");
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Helpers for folding Clz32/64. */
1288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt fold_Clz64 ( ULong value )
1289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt i;
1291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(value != 0ULL); /* no defined semantics for arg==0 */
1292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 64; ++i) {
1293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0ULL != (value & (((ULong)1) << (63 - i)))) return i;
1294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(0);
1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
1297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
1298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt fold_Clz32 ( UInt value )
1301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt i;
1303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(value != 0); /* no defined semantics for arg==0 */
1304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 32; ++i) {
1305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0 != (value & (((UInt)1) << (31 - i)))) return i;
1306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(0);
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
1309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return 0;
1310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* V64 holds 8 summary-constant bits in V128/V256 style.  Convert to
1313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the corresponding real constant. */
1314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//XXX re-check this before use
1315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//static ULong de_summarise_V64 ( UChar v64 )
1316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//{
1317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   ULong r = 0;
1318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<0)) r |= 0x00000000000000FFULL;
1319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<1)) r |= 0x000000000000FF00ULL;
1320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<2)) r |= 0x0000000000FF0000ULL;
1321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<3)) r |= 0x00000000FF000000ULL;
1322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<4)) r |= 0x000000FF00000000ULL;
1323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<5)) r |= 0x0000FF0000000000ULL;
1324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<6)) r |= 0x00FF000000000000ULL;
1325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   if (v64 & (1<<7)) r |= 0xFF00000000000000ULL;
1326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//   return r;
1327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//}
1328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Helper for arbitrary expression pattern matching in flat IR.  If
1330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   'e' is a reference to a tmp, look it up in env -- repeatedly, if
1331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   necessary -- until it resolves to a non-tmp.  Note that this can
1332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return NULL if it can't resolve 'e' to a new expression, which will
1333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   be the case if 'e' is instead defined by an IRStmt (IRDirty or
1334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   LLSC). */
1335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic IRExpr* chase ( IRExpr** env, IRExpr* e )
1336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Why is this loop guaranteed to terminate?  Because all tmps must
1338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      have definitions before use, hence a tmp cannot be bound
1339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      (directly or indirectly) to itself. */
1340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while (e->tag == Iex_RdTmp) {
1341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0) { vex_printf("chase "); ppIRExpr(e); vex_printf("\n"); }
1342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      e = env[(Int)e->Iex.RdTmp.tmp];
1343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e == NULL) break;
1344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return e;
1346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* fold_Expr ( IRExpr** env, IRExpr* e )
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     shift;
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e2 = e; /* e2 is the result of folding e, if possible */
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->tag) {
1354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Unop:
1355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* UNARY ops */
1356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->Iex.Unop.arg->tag == Iex_Const) {
1357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (e->Iex.Unop.op) {
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto8:
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0)));
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto32:
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0));
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto64:
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 1 : 0));
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto8:
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFF : 0)));
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto16:
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFF : 0)));
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto32:
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFFFFFF : 0));
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto64:
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? 0xFFFFFFFFFFFFFFFFULL : 0));
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto32: {
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 <<= 24;
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 >>= 24;
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32((UInt)s32));
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16Sto32: {
1403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s32 <<= 16;
1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s32 >>= 16;
1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U32( (UInt)s32) );
1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto64:
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto64:
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto32:
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_8Sto16: {
1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Short s16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s16 <<= 8;
1424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s16 >>= 8;
1425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U16( (UShort)s16) );
1426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_8Uto16:
1429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U16(
1430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto32:
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to16:
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to8:
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to1:
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to1:
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U64)
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_NotV128:
1456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            e2 = IRExpr_Const(IRConst_V128(
1457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.V128)));
1458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not64:
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U64)));
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not32:
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32(
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not16:
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16(toUShort(
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U16))));
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not8:
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8(toUChar(
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U8))));
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not1:
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to8: {
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0xFFULL;
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U8( (UChar)w64 ));
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to16: {
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0xFFFFULL;
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U16( (UShort)w64 ));
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to32: {
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 &= 0x00000000FFFFFFFFULL;
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64HIto32: {
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            w64 >>= 32;
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Uto64:
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64(
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0xFFFFFFFFULL
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    & e->Iex.Unop.arg->Iex.Const.con->Ico.U32));
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16Sto64: {
1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* signed */ Long s64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s64 <<= 48;
1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            s64 >>= 48;
1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Sto64: {
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* signed */ Long s64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 <<= 32;
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 >>= 32;
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16to8: {
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 &= 0xFF;
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_16HIto8: {
1532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 >>= 8;
1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            w16 &= 0xFF;
1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ8:
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0 !=
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ32:
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0 !=
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ64:
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const(IRConst_U1(toBool(
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )));
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ32: {
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt w32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (w32 == 0)
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32( 0 ));
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32( 0xFFFFFFFF ));
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ64: {
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (w64 == 0)
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64( 0 ));
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64( 0xFFFFFFFFFFFFFFFFULL ));
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left32: {
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int  s32 = (Int)(u32 & 0xFFFFFFFF);
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s32 = (s32 | (-s32));
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const( IRConst_U32( (UInt)s32 ));
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left64: {
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Long  s64 = (Long)u64;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s64 = (s64 | (-s64));
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e2 = IRExpr_Const( IRConst_U64( (ULong)s64 ));
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_Clz32: {
1591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (u32 != 0)
1593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U32(fold_Clz32(u32)));
1594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_Clz64: {
1597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (u64 != 0ULL)
1599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U64(fold_Clz64(u64)));
1600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* For these vector ones, can't fold all cases, but at least
1604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do the most obvious one.  Could do better here using
1605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            summarise/desummarise of vector constants, but too
1606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            difficult to verify; hence just handle the zero cases. */
1607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32UtoV128: {
1608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == u32) {
1610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(0x0000));
1611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V128to64: {
1617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
1618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == ((v128 >> 0) & 0xFF)) {
1619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_U64(0));
1620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V128HIto64: {
1626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
1627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == ((v128 >> 8) & 0xFF)) {
1628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_U64(0));
1629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64UtoV128: {
1635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0 == u64) {
1637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(0x0000));
1638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Even stupider (although still correct ..) */
1645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V256to64_0: case Iop_V256to64_1:
1646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V256to64_2: case Iop_V256to64_3: {
1647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UInt v256 = e->Iex.Unop.arg->Iex.Const.con->Ico.V256;
1648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (v256 == 0x00000000) {
1649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_U64(0));
1650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else {
1651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto unhandled;
1652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Binop:
1663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* BINARY ops */
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.arg1->tag == Iex_Const
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const) {
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cases where both args are consts */
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Or -- */
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or8:
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or16:
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U16(toUShort(
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or32:
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Or64:
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_OrV128:
1691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(
1692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
1693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
1694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Xor -- */
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor8:
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor16:
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U16(toUShort(
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor32:
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Xor64:
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_XorV128:
1718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(
1719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
1720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
1721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- And -- */
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And8:
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_And16:
1730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U16(toUShort(
1731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
1733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And32:
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_And64:
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_AndV128:
1745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               e2 = IRExpr_Const(IRConst_V128(
1746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
1747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
1748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Add -- */
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add8:
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add32:
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Add64:
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Sub -- */
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub8:
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U8(toUChar(
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub32:
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sub64:
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Max32U -- */
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Max32U: {
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt res  = u32a > u32b ? u32a : u32b;
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(res));
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Mul -- */
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Mul32:
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Mul64:
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullS32: {
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* very paranoid */
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32a = (Int)u32a;
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32b = (Int)u32b;
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  s64a = (Long)s32a;
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  s64b = (Long)s32b;
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Long  sres = s64a * s64b;
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong ures = (ULong)sres;
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(ures));
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Shl -- */
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl32:
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31)
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32(
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           << shift)));
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl64:
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63)
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64(
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           << shift)));
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Sar -- */
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar32: {
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*signed*/ Int s32;
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               s32   = (Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31) {
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  s32 >>=/*signed*/ shift;
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32((UInt)s32));
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar64: {
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*signed*/ Long s64;
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               s64   = (Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63) {
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  s64 >>=/*signed*/ shift;
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- Shr -- */
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr32: {
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*unsigned*/ UInt u32;
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               u32   = (UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 31) {
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  u32 >>=/*unsigned*/ shift;
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U32(u32));
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr64: {
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* paranoid ... */
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*unsigned*/ ULong u64;
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               u64   = (ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift >= 0 && shift <= 63) {
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  u64 >>=/*unsigned*/ shift;
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = IRExpr_Const(IRConst_U64(u64));
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpEQ -- */
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ32:
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ64:
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpNE -- */
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE8:
1903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_CasCmpNE8:
1904436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_ExpCmpNE8:
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((0xFF & e->Iex.Binop.arg1->Iex.Const.con->Ico.U8)
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != (0xFF & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8)))));
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE32:
1910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_CasCmpNE32:
1911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_ExpCmpNE32:
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE64:
1917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_CasCmpNE64:
1918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_ExpCmpNE64:
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLEU -- */
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLE32U:
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        <= (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLE64U:
1931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        <= (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLES -- */
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLE32S:
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        <= (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLE64S:
1943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        <= (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLTS -- */
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLT32S:
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        < (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLT64S:
1955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        < (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpLTU -- */
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpLT32U:
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U1(toBool(
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        < (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_CmpLT64U:
1967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e2 = IRExpr_Const(IRConst_U1(toBool(
1968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
1969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        < (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
1970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- CmpORD -- */
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpORD32S: {
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* very paranoid */
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32a = (Int)u32a;
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   s32b = (Int)u32b;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Int   r = 0x2; /* EQ */
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (s32a < s32b) {
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r = 0x8; /* LT */
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else if (s32a > s32b) {
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r = 0x4; /* GT */
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U32(r));
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* -- nHLto2n -- */
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_32HLto64:
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               e2 = IRExpr_Const(IRConst_U64(
1993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       (((ULong)(e->Iex.Binop.arg1
1994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  ->Iex.Const.con->Ico.U32)) << 32)
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       | ((ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ));
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_64HLto128:
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* We can't fold this, because there is no way to
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  express he result in IR, but at least pretend to
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  handle it, so as to stop getting blasted with
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  no-rule-for-this-primop messages. */
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* For this vector one, can't fold all cases, but at
2005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               least do the most obvious one.  Could do better here
2006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               using summarise/desummarise of vector constants, but
2007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               too difficult to verify; hence just handle the zero
2008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               cases. */
2009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_64HLtoV128: {
2010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ULong argHi = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64;
2011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ULong argLo = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64;
2012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (0 == argHi && 0 == argLo) {
2013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Const(IRConst_V128(0));
2014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
2015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  goto unhandled;
2016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
2019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Same reasoning for the 256-bit version. */
2020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_V128HLtoV256: {
2021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               IRExpr* argHi = e->Iex.Binop.arg1;
2022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               IRExpr* argLo = e->Iex.Binop.arg2;
2023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isZeroV128(argHi) && isZeroV128(argLo)) {
2024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  e2 = IRExpr_Const(IRConst_V256(0));
2025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               } else {
2026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  goto unhandled;
2027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
2028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
2029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* -- V128 stuff -- */
2032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_InterleaveLO8x16: {
2033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* This turns up a lot in Memcheck instrumentation of
2034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Icc generated code.  I don't know why. */
2035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               UShort arg1 =  e->Iex.Binop.arg1->Iex.Const.con->Ico.V128;
2036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               UShort arg2 =  e->Iex.Binop.arg2->Iex.Const.con->Ico.V128;
2037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (0 == arg1 && 0 == arg2) {
2038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Const(IRConst_V128(0));
2039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               } else {
2040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  goto unhandled;
2041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled;
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* other cases (identities, etc) */
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
2053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shl32:
2055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shl64:
2056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shr64:
2057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Shl32/Shl64/Shr64(x,0) ==> x */
2058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
2059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Shl32/Shl64/Shr64(0,x) ==> 0 */
2063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg1)) {
2064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shr32:
2070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Shr32(x,0) ==> x */
2071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
2072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or8:
2078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or16:
2079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or32:
2080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or64:
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Max32U:
2082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(x,0) ==> x */
2083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
2084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(0,x) ==> x */
2088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg1)) {
2089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg2;
2090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(x,1---1b) ==> 1---1b */
2093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(1---1b,x) ==> 1---1b */
2094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isOnesU(e->Iex.Binop.arg1) || isOnesU(e->Iex.Binop.arg2)) {
2095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
2096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Or8/Or16/Or32/Or64/Max32U(t,t) ==> t, for some IRTemp t */
2099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = e->Iex.Binop.arg1;
2101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add8:
2106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add8(t,t) ==> t << 1.
2107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Memcheck doesn't understand that
2108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  x+x produces a defined least significant bit, and it seems
2109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  simplest just to get rid of the problem by rewriting it
2110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  out, since the opportunity to do so exists. */
2111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Binop(Iop_Shl8, e->Iex.Binop.arg1,
2113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    IRExpr_Const(IRConst_U8(1)));
2114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* NB no Add16(t,t) case yet as no known test case exists */
2119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add32:
2121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add64:
2122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add32/Add64(x,0) ==> x */
2123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg2)) {
2124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add32/Add64(0,x) ==> x */
2128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (isZeroU(e->Iex.Binop.arg1)) {
2129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg2;
2130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Add32/Add64(t,t) ==> t << 1. Same rationale as for Add8. */
2133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = IRExpr_Binop(
2135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          e->Iex.Binop.op == Iop_Add32 ? Iop_Shl32 : Iop_Shl64,
2136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          e->Iex.Binop.arg1, IRExpr_Const(IRConst_U8(1)));
2137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Sub32:
2142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sub64:
2143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Sub32/Sub64(x,0) ==> x */
2144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isZeroU(e->Iex.Binop.arg2)) {
2145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Sub32/Sub64(t,t) ==> 0, for some IRTemp t */
2149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2154eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov            case Iop_Sub8x16:
2155eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               /* Sub8x16(x,0) ==> x */
2156eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               if (isZeroV128(e->Iex.Binop.arg2)) {
2157eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                  e2 = e->Iex.Binop.arg1;
2158eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                  break;
2159eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               }
2160eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               break;
2161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_And64:
2163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And32:
2164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* And32/And64(x,1---1b) ==> x */
2165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isOnesU(e->Iex.Binop.arg2)) {
2166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* And32/And64(x,0) ==> 0 */
2170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isZeroU(e->Iex.Binop.arg2)) {
2171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg2;
2172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* And32/And64(0,x) ==> 0 */
2175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isZeroU(e->Iex.Binop.arg1)) {
2176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* And32/And64(t,t) ==> t, for some IRTemp t */
2180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And8:
2187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And16:
2188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_AndV128:
2189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_AndV256:
2190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* And8/And16/AndV128/AndV256(t,t)
2191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  ==> t, for some IRTemp t */
2192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2196eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               /* Deal with either arg zero.  Could handle other And
2197eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                  cases here too. */
2198eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               if (e->Iex.Binop.op == Iop_And64
2199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   && (isZeroU64(e->Iex.Binop.arg1)
2200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       || isZeroU64(e->Iex.Binop.arg2))) {
2201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  e2 =  mkZeroOfPrimopResultType(e->Iex.Binop.op);
2202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
2203eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               } else if (e->Iex.Binop.op == Iop_AndV128
2204eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                          && (isZeroV128(e->Iex.Binop.arg1)
2205eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                              || isZeroV128(e->Iex.Binop.arg2))) {
2206eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                  e2 =  mkZeroOfPrimopResultType(e->Iex.Binop.op);
2207eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                  break;
2208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
2209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_OrV128:
2212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_OrV256:
2213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* V128/V256(t,t) ==> t, for some IRTemp t */
2214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = e->Iex.Binop.arg1;
2216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* OrV128(t,0) ==> t */
2219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (e->Iex.Binop.op == Iop_OrV128) {
2220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  if (isZeroV128(e->Iex.Binop.arg2)) {
2221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     e2 = e->Iex.Binop.arg1;
2222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     break;
2223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  }
2224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  if (isZeroV128(e->Iex.Binop.arg1)) {
2225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     e2 = e->Iex.Binop.arg2;
2226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     break;
2227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  }
2228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
2229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* OrV256(t,0) ==> t */
2230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (e->Iex.Binop.op == Iop_OrV256) {
2231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  if (isZeroV256(e->Iex.Binop.arg2)) {
2232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     e2 = e->Iex.Binop.arg1;
2233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     break;
2234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  }
2235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  //Disabled because there's no known test case right now.
2236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  //if (isZeroV256(e->Iex.Binop.arg1)) {
2237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  //   e2 = e->Iex.Binop.arg2;
2238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  //   break;
2239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  //}
2240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
2241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
2242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor8:
2244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor16:
2245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor32:
2246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor64:
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_XorV128:
2248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Xor8/16/32/64/V128(t,t) ==> 0, for some IRTemp t */
2249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpNE32:
2256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* CmpNE32(t,t) ==> 0, for some IRTemp t */
2257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* CmpNE32(1Uto32(b), 0) ==> b */
2262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isZeroU32(e->Iex.Binop.arg2)) {
2263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  IRExpr* a1 = chase(env, e->Iex.Binop.arg1);
2264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  if (a1 && a1->tag == Iex_Unop
2265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         && a1->Iex.Unop.op == Iop_1Uto32) {
2266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     e2 = a1->Iex.Unop.arg;
2267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     break;
2268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  }
2269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpEQ32:
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ64:
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8x8:
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8x16:
2276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpEQ16x8:
2277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_CmpEQ32x4:
2278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
2280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
2281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
2289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Iex_ITE:
2291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* ITE */
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* is the discriminant is a constant? */
2293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e->Iex.ITE.cond->tag == Iex_Const) {
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assured us by the IR type rules */
2295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(e->Iex.ITE.cond->Iex.Const.con->tag == Ico_U1);
2296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e2 = e->Iex.ITE.cond->Iex.Const.con->Ico.U1
2297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 ? e->Iex.ITE.iftrue : e->Iex.ITE.iffalse;
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* are the arms identical? (pretty weedy test) */
2301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (sameIRExprs(env, e->Iex.ITE.iftrue,
2302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           e->Iex.ITE.iffalse)) {
2303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         e2 = e->Iex.ITE.iffalse;
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
2306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
2308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* not considered */
2309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Show cases where we've found but not folded 'op(t,t)'.  Be
2313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      careful not to call sameIRExprs with values of different types,
2314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      though, else it will assert (and so it should!).  We can't
2315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      conveniently call typeOfIRExpr on the two args without a whole
2316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bunch of extra plumbing to pass in a type env, so just use a
2317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      hacky test to check the arguments are not anything that might
2318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sameIRExprs to assert.  This is only OK because this kludge is
2319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      only used for debug printing, not for "real" operation.  For
2320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      "real" operation (ie, all other calls to sameIRExprs), it is
2321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      essential that the to args have the same type.
2322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      The "right" solution is to plumb the containing block's
2324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTypeEnv through to here and use typeOfIRExpr to be sure.  But
2325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      that's a bunch of extra parameter passing which will just slow
2326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      down the normal case, for no purpose. */
2327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_control.iropt_verbosity > 0
2328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && e == e2
2329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && e->tag == Iex_Binop
2330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && !debug_only_hack_sameIRExprs_might_assert(e->Iex.Binop.arg1,
2331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                    e->Iex.Binop.arg2)
2332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("vex iropt: fold_Expr: no ident rule for: ");
2334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRExpr(e);
2335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("\n");
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Show the overall results of folding. */
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_IROPT && e2 != e) {
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("FOLD: ");
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e); vex_printf("  ->  ");
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e2); vex_printf("\n");
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e2;
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unhandled:
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n\n");
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("fold_Expr: no rule for the above");
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_verbosity > 0) {
2354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("vex iropt: fold_Expr: no const rule for: ");
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(e);
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e2;
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Apply the subst to a simple 1-level expression -- guaranteed to be
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1-level due to previous flattening pass. */
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex )
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ex->tag) {
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[(Int)ex->Iex.RdTmp.tmp] != NULL) {
2371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr *rhs = env[(Int)ex->Iex.RdTmp.tmp];
2372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (rhs->tag == Iex_RdTmp)
2373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return rhs;
2374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (rhs->tag == Iex_Const
2375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                && rhs->Iex.Const.con->tag != Ico_F64i)
2376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return rhs;
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* not bound in env */
2379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return ex;
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ex;
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.GetI.ix));
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ex->Iex.GetI.descr,
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            subst_Expr(env, ex->Iex.GetI.ix),
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ex->Iex.GetI.bias
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Qop: {
2394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRQop* qop = ex->Iex.Qop.details;
2395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg1));
2396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg2));
2397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg3));
2398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(qop->arg4));
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Qop(
2400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   qop->op,
2401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg1),
2402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg2),
2403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg3),
2404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, qop->arg4)
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Triop: {
2409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTriop* triop = ex->Iex.Triop.details;
2410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(triop->arg1));
2411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(triop->arg2));
2412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(triop->arg3));
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Triop(
2414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   triop->op,
2415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, triop->arg1),
2416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, triop->arg2),
2417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   subst_Expr(env, triop->arg3)
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Binop.arg1));
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Binop.arg2));
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop(
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Binop.op,
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Binop.arg1),
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Binop.arg2)
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Unop.arg));
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Unop.op,
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Unop.arg)
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(ex->Iex.Load.addr));
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Load(
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Load.end,
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.Load.ty,
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   subst_Expr(env, ex->Iex.Load.addr)
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall: {
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int      i;
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args2 = shallowCopyIRExprVec(ex->Iex.CCall.args);
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args2[i]; i++) {
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(args2[i]));
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args2[i] = subst_Expr(env, args2[i]);
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_CCall(
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.CCall.cee,
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ex->Iex.CCall.retty,
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   args2
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
2460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(ex->Iex.ITE.cond));
2461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(ex->Iex.ITE.iftrue));
2462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(ex->Iex.ITE.iffalse));
2463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_ITE(
2464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   subst_Expr(env, ex->Iex.ITE.cond),
2465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   subst_Expr(env, ex->Iex.ITE.iftrue),
2466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   subst_Expr(env, ex->Iex.ITE.iffalse)
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n\n"); ppIRExpr(ex);
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("subst_Expr");
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Apply the subst to stmt, then fold the result as much as possible.
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Much simplified due to stmt being previously flattened.  As a
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result of this, the stmt may wind up being turned into a no-op.
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nsubst and fold stmt\n");
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(st);
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n");
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.base));
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.AbiHint.nia));
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_AbiHint(
2494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.base)),
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.AbiHint.len,
2496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.nia))
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Put.data));
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Put(
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Put.offset,
2502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.Put.data))
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_PutI: {
2506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *puti, *puti2;
2507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti = st->Ist.PutI.details;
2508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(puti->ix));
2509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(puti->data));
2510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti2 = mkIRPutI(puti->descr,
2511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          fold_Expr(env, subst_Expr(env, puti->ix)),
2512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          puti->bias,
2513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          fold_Expr(env, subst_Expr(env, puti->data)));
2514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRStmt_PutI(puti2);
2515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is the one place where an expr (st->Ist.WrTmp.data) is
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            allowed to be more than just a constant or a tmp. */
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_WrTmp(
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.WrTmp.tmp,
2522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.WrTmp.data))
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.addr));
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Store.data));
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Store(
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Store.end,
2530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.Store.addr)),
2531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.Store.data))
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
2535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
2536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(sg->addr));
2537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(sg->data));
2538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(sg->guard));
2539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* faddr  = fold_Expr(env, subst_Expr(env, sg->addr));
2540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* fdata  = fold_Expr(env, subst_Expr(env, sg->data));
2541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* fguard = fold_Expr(env, subst_Expr(env, sg->guard));
2542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (fguard->tag == Iex_Const) {
2543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* The condition on this store has folded down to a constant. */
2544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(fguard->Iex.Const.con->tag == Ico_U1);
2545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (fguard->Iex.Const.con->Ico.U1 == False) {
2546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return IRStmt_NoOp();
2547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
2548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(fguard->Iex.Const.con->Ico.U1 == True);
2549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return IRStmt_Store(sg->end, faddr, fdata);
2550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRStmt_StoreG(sg->end, faddr, fdata, fguard);
2553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
2554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
2556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* This is complicated.  If the guard folds down to 'false',
2557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            we can replace it with an assignment 'dst := alt', but if
2558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            the guard folds down to 'true', we can't conveniently
2559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            replace it with an unconditional load, because doing so
2560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            requires generating a new temporary, and that is not easy
2561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            to do at this point. */
2562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
2563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(lg->addr));
2564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(lg->alt));
2565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(isIRAtom(lg->guard));
2566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* faddr  = fold_Expr(env, subst_Expr(env, lg->addr));
2567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* falt   = fold_Expr(env, subst_Expr(env, lg->alt));
2568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* fguard = fold_Expr(env, subst_Expr(env, lg->guard));
2569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (fguard->tag == Iex_Const) {
2570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* The condition on this load has folded down to a constant. */
2571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(fguard->Iex.Const.con->tag == Ico_U1);
2572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (fguard->Iex.Const.con->Ico.U1 == False) {
2573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* The load is not going to happen -- instead 'alt' is
2574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  assigned to 'dst'.  */
2575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return IRStmt_WrTmp(lg->dst, falt);
2576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
2577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(fguard->Iex.Const.con->Ico.U1 == True);
2578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* The load is always going to happen.  We want to
2579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  convert to an unconditional load and assign to 'dst'
2580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  (IRStmt_WrTmp).  Problem is we need an extra temp to
2581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  hold the loaded value, but none is available.
2582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  Instead, reconstitute the conditional load (with
2583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  folded args, of course) and let the caller of this
2584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  routine deal with the problem. */
2585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRStmt_LoadG(lg->end, lg->cvt, lg->dst, faddr, falt, fguard);
2588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
2589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS: {
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS *cas, *cas2;
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->addr));
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->expdLo));
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(cas->dataLo));
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS(
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->oldHi, cas->oldLo, cas->end,
2600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, cas->addr)),
2601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   cas->expdHi ? fold_Expr(env, subst_Expr(env, cas->expdHi))
2602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               : NULL,
2603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, cas->expdLo)),
2604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   cas->dataHi ? fold_Expr(env, subst_Expr(env, cas->dataHi))
2605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               : NULL,
2606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, cas->dataLo))
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_CAS(cas2);
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.LLSC.addr));
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.LLSC.storedata));
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_LLSC(
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.end,
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.result,
2618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   fold_Expr(env, subst_Expr(env, st->Ist.LLSC.addr)),
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.storedata
2620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      ? fold_Expr(env, subst_Expr(env, st->Ist.LLSC.storedata))
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : NULL
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty: {
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int     i;
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty *d, *d2;
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->args = shallowCopyIRExprVec(d2->args);
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None) {
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d2->mAddr));
2633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            d2->mAddr = fold_Expr(env, subst_Expr(env, d2->mAddr));
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(d2->guard));
2636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         d2->guard = fold_Expr(env, subst_Expr(env, d2->guard));
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d2->args[i]; i++) {
2638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr* arg = d2->args[i];
2639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg))) {
2640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(isIRAtom(arg));
2641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               d2->args[i] = fold_Expr(env, subst_Expr(env, arg));
2642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Dirty(d2);
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
2648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return IRStmt_IMark(st->Ist.IMark.addr,
2649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.len,
2650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.delta);
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_NoOp();
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_MBE(st->Ist.MBE.event);
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit: {
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* fcond;
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(st->Ist.Exit.guard));
2661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fcond = fold_Expr(env, subst_Expr(env, st->Ist.Exit.guard));
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fcond->tag == Iex_Const) {
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Interesting.  The condition on this exit has folded down to
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a constant. */
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(fcond->Iex.Const.con->tag == Ico_U1);
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fcond->Iex.Const.con->Ico.U1 == False) {
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* exit is never going to happen, so dump the statement. */
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return IRStmt_NoOp();
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(fcond->Iex.Const.con->Ico.U1 == True);
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Hmmm.  The exit has become unconditional.  Leave it
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  as it is for now, since we'd have to truncate the BB
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  at this point, which is tricky.  Such truncation is
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  done later by the dead-code elimination pass. */
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* fall out into the reconstruct-the-exit code. */
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (vex_control.iropt_verbosity > 0)
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* really a misuse of vex_control.iropt_verbosity */
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vex_printf("vex iropt: IRStmt_Exit became unconditional\n");
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRStmt_Exit(fcond, st->Ist.Exit.jk,
2682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   st->Ist.Exit.dst, st->Ist.Exit.offsIP);
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n"); ppIRStmt(st);
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("subst_and_fold_Stmt");
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cprop_BB ( IRSB* in )
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*    out;
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st2;
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      n_tmps = in->tyenv->types_used;
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** env = LibVEX_Alloc(n_tmps * sizeof(IRExpr*));
2699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Keep track of IRStmt_LoadGs that we need to revisit after
2700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      processing all the other statements. */
2701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const Int N_FIXUPS = 16;
2702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int fixups[N_FIXUPS]; /* indices in the stmt array of 'out' */
2703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int n_fixups = 0;
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out = emptyIRSB();
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up the env with which travels forward.  This holds a
2709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      substitution, mapping IRTemps to IRExprs. The environment
2710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is to be applied as we move along.  Keys are IRTemps.
2711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Values are IRExpr*s.
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i] = NULL;
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each original SSA-form stmt ... */
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < in->stmts_used; i++) {
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* First apply the substitution to the current stmt.  This
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         propagates in any constants and tmp-tmp assignments
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         accumulated prior to this point.  As part of the subst_Stmt
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         call, also then fold any constant expressions resulting. */
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = in->stmts[i];
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* perhaps st2 is already a no-op? */
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st2->tag == Ist_NoOp) continue;
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = subst_and_fold_Stmt( env, st2 );
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Deal with some post-folding special cases. */
2732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      switch (st2->tag) {
2733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* If the statement has been folded into a no-op, forget
2735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            it. */
2736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_NoOp:
2737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            continue;
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* If the statement assigns to an IRTemp add it to the
2740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            running environment. This is for the benefit of copy
2741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            propagation and to allow sameIRExpr look through
2742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemps. */
2743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_WrTmp: {
2744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(env[(Int)(st2->Ist.WrTmp.tmp)] == NULL);
2745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            env[(Int)(st2->Ist.WrTmp.tmp)] = st2->Ist.WrTmp.data;
2746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* 't1 = t2' -- don't add to BB; will be optimized out */
2748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (st2->Ist.WrTmp.data->tag == Iex_RdTmp)
2749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               continue;
2750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* 't = const' && 'const != F64i' -- don't add to BB
2752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               Note, we choose not to propagate const when const is an
2753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               F64i, so that F64i literals can be CSE'd later.  This
2754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               helps x86 floating point code generation. */
2755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (st2->Ist.WrTmp.data->tag == Iex_Const
2756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                && st2->Ist.WrTmp.data->Iex.Const.con->tag != Ico_F64i) {
2757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               continue;
2758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* else add it to the output, as normal */
2760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_LoadG: {
2764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRLoadG* lg    = st2->Ist.LoadG.details;
2765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*  guard = lg->guard;
2766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (guard->tag == Iex_Const) {
2767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* The guard has folded to a constant, and that
2768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  constant must be 1:I1, since subst_and_fold_Stmt
2769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  folds out the case 0:I1 by itself. */
2770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(guard->Iex.Const.con->tag == Ico_U1);
2771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(guard->Iex.Const.con->Ico.U1 == True);
2772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Add a NoOp here as a placeholder, and make a note of
2773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  where it is in the output block.  Afterwards we'll
2774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  come back here and transform the NoOp and the LoadG
2775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  into a load-convert pair.  The fixups[] entry
2776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  refers to the inserted NoOp, and we expect to find
2777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  the relevant LoadG immediately after it. */
2778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(n_fixups >= 0 && n_fixups <= N_FIXUPS);
2779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (n_fixups < N_FIXUPS) {
2780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  fixups[n_fixups++] = out->stmts_used;
2781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addStmtToIRSB( out, IRStmt_NoOp() );
2782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
2783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* And always add the LoadG to the output, regardless. */
2785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
2789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Not interesting, copy st2 into the output block. */
2793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB( out, st2 );
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  if STATS_IROPT
2797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("sameIRExpr: invoked = %u/%u  equal = %u/%u max_nodes = %u\n",
2798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              invocation_count, recursion_count, success_count,
2799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              recursion_success_count, max_nodes_visited);
2800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  endif
2801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->next     = subst_Expr( env, in->next );
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->jumpkind = in->jumpkind;
2804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   out->offsIP   = in->offsIP;
2805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Process any leftover unconditional LoadGs that we noticed
2807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      in the main pass. */
2808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(n_fixups >= 0 && n_fixups <= N_FIXUPS);
2809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; i < n_fixups; i++) {
2810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int ix = fixups[i];
2811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Carefully verify that the LoadG has the expected form. */
2812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(ix >= 0 && ix+1 < out->stmts_used);
2813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRStmt* nop = out->stmts[ix];
2814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRStmt* lgu = out->stmts[ix+1];
2815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(nop->tag == Ist_NoOp);
2816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(lgu->tag == Ist_LoadG);
2817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRLoadG* lg    = lgu->Ist.LoadG.details;
2818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRExpr*  guard = lg->guard;
2819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(guard->Iex.Const.con->tag == Ico_U1);
2820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(guard->Iex.Const.con->Ico.U1 == True);
2821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Figure out the load and result types, and the implied
2822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         conversion operation. */
2823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRType cvtRes = Ity_INVALID, cvtArg = Ity_INVALID;
2824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      typeOfIRLoadGOp(lg->cvt, &cvtRes, &cvtArg);
2825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IROp cvtOp = Iop_INVALID;
2826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      switch (lg->cvt) {
2827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case ILGop_Ident32: break;
2828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case ILGop_8Uto32:  cvtOp = Iop_8Uto32;  break;
2829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case ILGop_8Sto32:  cvtOp = Iop_8Sto32;  break;
2830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case ILGop_16Uto32: cvtOp = Iop_16Uto32; break;
2831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case ILGop_16Sto32: cvtOp = Iop_16Sto32; break;
2832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default: vpanic("cprop_BB: unhandled ILGOp");
2833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
2834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Replace the placeholder NoOp by the required unconditional
2835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         load. */
2836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRTemp tLoaded = newIRTemp(out->tyenv, cvtArg);
2837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      out->stmts[ix]
2838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         = IRStmt_WrTmp(tLoaded,
2839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        IRExpr_Load(lg->end, cvtArg, lg->addr));
2840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Replace the LoadG by a conversion from the loaded value's
2841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         type to the required result type. */
2842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      out->stmts[ix+1]
2843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         = IRStmt_WrTmp(
2844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              lg->dst, cvtOp == Iop_INVALID
2845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          ? IRExpr_RdTmp(tLoaded)
2846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          : IRExpr_Unop(cvtOp, IRExpr_RdTmp(tLoaded)));
2847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
2848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return out;
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Dead code (t = E) removal                               ---*/
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* As a side effect, also removes all code following an unconditional
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   side exit. */
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The type of the HashHW map is: a map from IRTemp to nothing
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- really just operating a set or IRTemps.
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Temp ( Bool* set, IRTemp tmp )
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set[(Int)tmp] = True;
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Expr ( Bool* set, IRExpr* e )
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.GetI.ix);
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
2878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, e->Iex.ITE.cond);
2879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, e->Iex.ITE.iftrue);
2880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, e->Iex.ITE.iffalse);
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, e->Iex.CCall.args[i]);
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Load.addr);
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
2890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg1);
2891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg2);
2892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg3);
2893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Qop.details->arg4);
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
2896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Triop.details->arg1);
2897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Triop.details->arg2);
2898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, e->Iex.Triop.details->arg3);
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Binop.arg1);
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Binop.arg2);
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, e->Iex.Unop.arg);
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Temp(set, e->Iex.RdTmp.tmp);
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addUses_Expr");
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addUses_Stmt ( Bool* set, IRStmt* st )
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.AbiHint.base);
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.AbiHint.nia);
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
2931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, st->Ist.PutI.details->ix);
2932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addUses_Expr(set, st->Ist.PutI.details->data);
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.WrTmp.data);
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Put.data);
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Store.addr);
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Store.data);
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
2945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
2946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, sg->addr);
2947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, sg->data);
2948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, sg->guard);
2949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return;
2950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
2951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
2952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
2953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, lg->addr);
2954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, lg->alt);
2955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addUses_Expr(set, lg->guard);
2956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return;
2957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->addr);
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->expdHi)
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, cas->expdHi);
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->expdLo);
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->dataHi)
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, cas->dataHi);
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, cas->dataLo);
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.LLSC.addr);
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, st->Ist.LLSC.storedata);
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mFx != Ifx_None)
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addUses_Expr(set, d->mAddr);
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, d->guard);
2978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         for (i = 0; d->args[i] != NULL; i++) {
2979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr* arg = d->args[i];
2980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
2981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addUses_Expr(set, arg);
2982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Expr(set, st->Ist.Exit.guard);
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addUses_Stmt");
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this literally IRExpr_Const(IRConst_U1(False)) ? */
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU1 ( IRExpr* e )
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U1
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U1 == False );
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this literally IRExpr_Const(IRConst_U1(True)) ? */
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isOneU1 ( IRExpr* e )
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool( e->tag == Iex_Const
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->tag == Ico_U1
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  && e->Iex.Const.con->Ico.U1 == True );
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note, this destructively modifies the given IRSB. */
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan backwards through statements, carrying a set of IRTemps which
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are known to be used after the current point.  On encountering 't =
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   E', delete the binding if it is not used.  Otherwise, add any temp
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uses to the set and keep on moving backwards.
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   As an enhancement, the first (backwards) pass searches for IR exits
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with always-taken conditions and notes the location of the earliest
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   one in the block.  If any such are found, a second pass copies the
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exit destination and jump kind to the bb-end.  Then, the exit and
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all statements following it are turned into no-ops.
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* notstatic */ void do_deadcode_BB ( IRSB* bb )
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, i_unconditional_exit;
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     n_tmps = bb->tyenv->types_used;
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool*   set = LibVEX_Alloc(n_tmps * sizeof(Bool));
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set[i] = False;
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* start off by recording IRTemp uses in the next field. */
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addUses_Expr(set, bb->next);
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First pass */
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Work backwards through the stmts */
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_unconditional_exit = -1;
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* take note of any unconditional exits */
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Exit
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isOneU1(st->Ist.Exit.guard))
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i_unconditional_exit = i;
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && set[(Int)(st->Ist.WrTmp.tmp)] == False) {
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* it's an IRTemp which never got used.  Delete it. */
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("DEAD: ");
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.Dirty.details->guard
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isZeroU1(st->Ist.Dirty.details->guard)) {
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is a dirty helper which will never get called.
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Delete it. */
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       else {
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note any IRTemp uses made by the current statement. */
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addUses_Stmt(set, st);
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Optional second pass: if any unconditional exits were found,
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete them and all following statements. */
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i_unconditional_exit != -1) {
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) vex_printf("ZAPPING ALL FORWARDS from %d\n",
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        i_unconditional_exit);
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i_unconditional_exit >= 0
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && i_unconditional_exit < bb->stmts_used);
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->next
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRExpr_Const( bb->stmts[i_unconditional_exit]->Ist.Exit.dst );
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->jumpkind
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = bb->stmts[i_unconditional_exit]->Ist.Exit.jk;
3091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bb->offsIP
3092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         = bb->stmts[i_unconditional_exit]->Ist.Exit.offsIP;
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = i_unconditional_exit; i < bb->stmts_used; i++)
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Specialisation of helper function calls, in             ---*/
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- collaboration with the front end                        ---*/
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* spec_helpers_BB(
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb,
3107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int)
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ex;
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    any = False;
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || st->Ist.WrTmp.data->tag != Iex_CCall)
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ex = (*specHelper)( st->Ist.WrTmp.data->Iex.CCall.cee->name,
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          st->Ist.WrTmp.data->Iex.CCall.args,
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          &bb->stmts[0], i );
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ex)
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* the front end can't think of a suitable replacement */
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        continue;
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We got something better.  Install it in the bb. */
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      any = True;
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->stmts[i]
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRStmt_WrTmp(st->Ist.WrTmp.tmp, ex);
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) {
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("SPEC: ");
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(st->Ist.WrTmp.data);
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("  -->  ");
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ex);
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (any)
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = flatten_BB(bb);
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Determination of guest state aliasing relationships     ---*/
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are helper functions for CSE and GetI/PutI transformations.
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Determine, to the extent possible, the relationship between two
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest state accesses.  The possible outcomes are:
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Exact alias.  These two accesses denote precisely the same
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     piece of the guest state.
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Definitely no alias.  These two accesses are guaranteed not to
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     overlap any part of the guest state.
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Unknown -- if neither of the above can be established.
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If in doubt, return Unknown.  */
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum { ExactAlias, NoAlias, UnknownAlias }
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing;
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces the alias relation between an indexed guest
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state access and a non-indexed access. */
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGSAliasing getAliasingRelation_IC ( IRRegArray* descr1, IRExpr* ix1,
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    Int offset2, IRType ty2 )
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff1, maxoff1, minoff2, maxoff2;
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr1, &minoff1, &maxoff1 );
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   minoff2 = offset2;
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   maxoff2 = minoff2 + sizeofIRType(ty2) - 1;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff1 < minoff2 || maxoff2 < minoff1)
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NoAlias;
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Could probably do better here if required.  For the moment
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      however just claim not to know anything more. */
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return UnknownAlias;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces the alias relation between two indexed guest state
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accesses. */
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGSAliasing getAliasingRelation_II (
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRRegArray* descr1, IRExpr* ix1, Int bias1,
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              IRRegArray* descr2, IRExpr* ix2, Int bias2
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           )
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt minoff1, maxoff1, minoff2, maxoff2;
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  iters;
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First try hard to show they don't alias. */
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr1, &minoff1, &maxoff1 );
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   getArrayBounds( descr2, &minoff2, &maxoff2 );
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (maxoff1 < minoff2 || maxoff2 < minoff1)
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NoAlias;
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So the two arrays at least partially overlap.  To get any
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      further we'll have to be sure that the descriptors are
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      identical. */
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!eqIRRegArray(descr1, descr2))
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return UnknownAlias;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The descriptors are identical.  Now the only difference can be
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in the index expressions.  If they cannot be shown to be
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      identical, we have to say we don't know what the aliasing
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      relation will be.  Now, since the IR is flattened, the index
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expressions should be atoms -- either consts or tmps.  So that
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      makes the comparison simple. */
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isIRAtom(ix1));
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isIRAtom(ix2));
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!eqIRAtom(ix1,ix2))
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return UnknownAlias;
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, the index expressions are identical.  So now the only way
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      they can be different is in the bias.  Normalise this
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      paranoidly, to reliably establish equality/non-equality. */
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So now we know that the GetI and PutI index the same array
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      with the same base.  Are the offsets the same, modulo the
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      array size?  Do this paranoidly. */
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->nElems == descr2->nElems);
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->elemTy == descr2->elemTy);
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(descr1->base   == descr2->base);
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iters = 0;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (bias1 < 0 || bias2 < 0) {
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bias1 += descr1->nElems;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bias2 += descr1->nElems;
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters++;
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (iters > 10)
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("getAliasingRelation: iters");
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias1 >= 0 && bias2 >= 0);
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias1 %= descr1->nElems;
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias2 %= descr1->nElems;
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias1 >= 0 && bias1 < descr1->nElems);
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bias2 >= 0 && bias2 < descr1->nElems);
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, biasP and biasG are normalised into the range
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0 .. descrP/G->nElems - 1.  And so we can establish
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      equality/non-equality. */
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bias1==bias2 ? ExactAlias : NoAlias;
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Common Subexpression Elimination                        ---*/
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expensive in time and space. */
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Uses two environments:
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a IRTemp -> IRTemp mapping
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a mapping from AvailExpr* to IRTemp
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
3275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      enum { TCc, TCt } tag;
3276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      union { IRTemp tmp; IRConst* con; } u;
3277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   TmpOrConst;
3279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool eqTmpOrConst ( TmpOrConst* tc1, TmpOrConst* tc2 )
3281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (tc1->tag != tc2->tag)
3283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return False;
3284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (tc1->tag) {
3285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case TCc:
3286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return eqIRConst(tc1->u.con, tc2->u.con);
3287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case TCt:
3288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return tc1->u.tmp == tc2->u.tmp;
3289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
3290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("eqTmpOrConst");
3291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool eqIRCallee ( IRCallee* cee1, IRCallee* cee2 )
3295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool eq = cee1->addr == cee2->addr;
3297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (eq) {
3298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cee1->regparms == cee2->regparms);
3299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cee1->mcx_mask == cee2->mcx_mask);
3300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Names should be the same too, but we don't bother to
3301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         check. */
3302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return eq;
3304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Convert a NULL terminated IRExpr* vector to an array of
3307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   TmpOrConsts, and a length. */
3308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void irExprVec_to_TmpOrConsts ( /*OUT*/TmpOrConst** outs,
3309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       /*OUT*/Int* nOuts,
3310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       IRExpr** ins )
3311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int i, n;
3313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* We have to make two passes, one to count, one to copy. */
3314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (n = 0; ins[n]; n++)
3315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ;
3316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *outs  = LibVEX_Alloc(n * sizeof(TmpOrConst));
3317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *nOuts = n;
3318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* and now copy .. */
3319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < n; i++) {
3320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr*       arg = ins[i];
3321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      TmpOrConst* dst = &(*outs)[i];
3322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (arg->tag == Iex_RdTmp) {
3323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->tag   = TCt;
3324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->u.tmp = arg->Iex.RdTmp.tmp;
3325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else if (arg->tag == Iex_Const) {
3327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->tag   = TCc;
3328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dst->u.con = arg->Iex.Const.con;
3329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else {
3331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Failure of this is serious; it means that the presented arg
3332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            isn't an IR atom, as it should be. */
3333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("irExprVec_to_TmpOrConsts");
3334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef
3339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   struct {
3340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      enum { Ut, Btt, Btc, Bct, Cf64i, Ittt, Itct, Ittc, Itcc, GetIt,
3341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             CCall
3342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      } tag;
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union {
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unop(tmp) */
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   op;
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg;
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Ut;
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(tmp,tmp) */
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   op;
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg1;
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp arg2;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Btt;
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(tmp,const) */
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp    op;
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp  arg1;
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst con2;
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Btc;
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* binop(const,tmp) */
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp    op;
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst con1;
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp  arg2;
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bct;
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* F64i-style const */
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong f64i;
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Cf64i;
3371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* ITE(tmp,tmp,tmp) */
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp co;
3374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemp e1;
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp e0;
3376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } Ittt;
3377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* ITE(tmp,tmp,const) */
3378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         struct {
3379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemp  co;
3380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemp  e1;
3381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRConst con0;
3382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } Ittc;
3383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* ITE(tmp,const,tmp) */
3384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         struct {
3385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemp  co;
3386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRConst con1;
3387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemp  e0;
3388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } Itct;
3389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* ITE(tmp,const,const) */
3390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         struct {
3391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRTemp  co;
3392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRConst con1;
3393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRConst con0;
3394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } Itcc;
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* GetI(descr,tmp,bias)*/
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRRegArray* descr;
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp      ix;
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int         bias;
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } GetIt;
3401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Clean helper call */
3402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         struct {
3403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRCallee*   cee;
3404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            TmpOrConst* args;
3405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int         nArgs;
3406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRType      retty;
3407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } CCall;
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } u;
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr;
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool eq_AvailExpr ( AvailExpr* a1, AvailExpr* a2 )
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (LIKELY(a1->tag != a2->tag))
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (a1->tag) {
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Ut.op == a2->u.Ut.op
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Ut.arg == a2->u.Ut.arg);
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Btt.op == a2->u.Btt.op
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btt.arg1 == a2->u.Btt.arg1
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btt.arg2 == a2->u.Btt.arg2);
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Btc.op == a2->u.Btc.op
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Btc.arg1 == a2->u.Btc.arg1
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && eqIRConst(&a1->u.Btc.con2, &a2->u.Btc.con2));
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a1->u.Bct.op == a2->u.Bct.op
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && a1->u.Bct.arg2 == a2->u.Bct.arg2
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && eqIRConst(&a1->u.Bct.con1, &a2->u.Bct.con1));
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(a1->u.Cf64i.f64i == a2->u.Cf64i.f64i);
3438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ittt:
3439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return toBool(a1->u.Ittt.co == a2->u.Ittt.co
3440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && a1->u.Ittt.e1 == a2->u.Ittt.e1
3441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && a1->u.Ittt.e0 == a2->u.Ittt.e0);
3442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ittc:
3443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return toBool(a1->u.Ittc.co == a2->u.Ittc.co
3444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && a1->u.Ittc.e1 == a2->u.Ittc.e1
3445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && eqIRConst(&a1->u.Ittc.con0, &a2->u.Ittc.con0));
3446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Itct:
3447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return toBool(a1->u.Itct.co == a2->u.Itct.co
3448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && eqIRConst(&a1->u.Itct.con1, &a2->u.Itct.con1)
3449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && a1->u.Itct.e0 == a2->u.Itct.e0);
3450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Itcc:
3451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return toBool(a1->u.Itcc.co == a2->u.Itcc.co
3452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && eqIRConst(&a1->u.Itcc.con1, &a2->u.Itcc.con1)
3453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && eqIRConst(&a1->u.Itcc.con0, &a2->u.Itcc.con0));
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return toBool(eqIRRegArray(a1->u.GetIt.descr, a2->u.GetIt.descr)
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.GetIt.ix == a2->u.GetIt.ix
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       && a1->u.GetIt.bias == a2->u.GetIt.bias);
3458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case CCall: {
3459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int  i, n;
3460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool eq = a1->u.CCall.nArgs == a2->u.CCall.nArgs
3461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   && eqIRCallee(a1->u.CCall.cee, a2->u.CCall.cee);
3462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (eq) {
3463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            n = a1->u.CCall.nArgs;
3464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (i = 0; i < n; i++) {
3465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (!eqTmpOrConst( &a1->u.CCall.args[i],
3466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  &a2->u.CCall.args[i] )) {
3467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  eq = False;
3468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
3470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (eq) vassert(a1->u.CCall.retty == a2->u.CCall.retty);
3473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return eq;
3474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("eq_AvailExpr");
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* availExpr_to_IRExpr ( AvailExpr* ae )
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRConst *con, *con0, *con1;
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ae->tag) {
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( ae->u.Ut.op, IRExpr_RdTmp(ae->u.Ut.arg) );
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Btt.op,
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btt.arg1),
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btt.arg2) );
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con = LibVEX_Alloc(sizeof(IRConst));
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *con = ae->u.Btc.con2;
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Btc.op,
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Btc.arg1),
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(con) );
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con = LibVEX_Alloc(sizeof(IRConst));
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *con = ae->u.Bct.con1;
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Binop( ae->u.Bct.op,
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Const(con),
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_RdTmp(ae->u.Bct.arg2) );
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Const(IRConst_F64i(ae->u.Cf64i.f64i));
3503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ittt:
3504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Ittt.co),
3505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_RdTmp(ae->u.Ittt.e1),
3506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_RdTmp(ae->u.Ittt.e0));
3507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ittc:
3508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         con0 = LibVEX_Alloc(sizeof(IRConst));
3509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *con0 = ae->u.Ittc.con0;
3510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Ittc.co),
3511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_RdTmp(ae->u.Ittc.e1),
3512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_Const(con0));
3513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Itct:
3514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         con1 = LibVEX_Alloc(sizeof(IRConst));
3515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *con1 = ae->u.Itct.con1;
3516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Itct.co),
3517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_Const(con1),
3518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_RdTmp(ae->u.Itct.e0));
3519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Itcc:
3521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         con0 = LibVEX_Alloc(sizeof(IRConst));
3522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         con1 = LibVEX_Alloc(sizeof(IRConst));
3523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *con0 = ae->u.Itcc.con0;
3524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *con1 = ae->u.Itcc.con1;
3525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Itcc.co),
3526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_Const(con1),
3527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           IRExpr_Const(con0));
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(ae->u.GetIt.descr,
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRExpr_RdTmp(ae->u.GetIt.ix),
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            ae->u.GetIt.bias);
3532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case CCall: {
3533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int i, n = ae->u.CCall.nArgs;
3534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(n >= 0);
3535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr** vec = LibVEX_Alloc((n+1) * sizeof(IRExpr*));
3536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vec[n] = NULL;
3537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < n; i++) {
3538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            TmpOrConst* tc = &ae->u.CCall.args[i];
3539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (tc->tag == TCc) {
3540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vec[i] = IRExpr_Const(tc->u.con);
3541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else if (tc->tag == TCt) {
3543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vec[i] = IRExpr_RdTmp(tc->u.tmp);
3544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            else vpanic("availExpr_to_IRExpr:CCall-arg");
3546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRExpr_CCall(ae->u.CCall.cee,
3548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             ae->u.CCall.retty,
3549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             vec);
3550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("availExpr_to_IRExpr");
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp subst_AvailExpr_Temp ( HashHW* env, IRTemp tmp )
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord res;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* env :: IRTemp -> IRTemp */
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (lookupHHW( env, &res, (HWord)tmp ))
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (IRTemp)res;
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return tmp;
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void subst_AvailExpr ( HashHW* env, AvailExpr* ae )
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* env :: IRTemp -> IRTemp */
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ae->tag) {
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ut:
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Ut.arg = subst_AvailExpr_Temp( env, ae->u.Ut.arg );
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btt:
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btt.arg1 = subst_AvailExpr_Temp( env, ae->u.Btt.arg1 );
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btt.arg2 = subst_AvailExpr_Temp( env, ae->u.Btt.arg2 );
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Btc:
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Btc.arg1 = subst_AvailExpr_Temp( env, ae->u.Btc.arg1 );
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Bct:
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.Bct.arg2 = subst_AvailExpr_Temp( env, ae->u.Bct.arg2 );
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cf64i:
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ittt:
3587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Ittt.co = subst_AvailExpr_Temp( env, ae->u.Ittt.co );
3588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Ittt.e1 = subst_AvailExpr_Temp( env, ae->u.Ittt.e1 );
3589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Ittt.e0 = subst_AvailExpr_Temp( env, ae->u.Ittt.e0 );
3590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ittc:
3592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Ittc.co = subst_AvailExpr_Temp( env, ae->u.Ittc.co );
3593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Ittc.e1 = subst_AvailExpr_Temp( env, ae->u.Ittc.e1 );
3594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Itct:
3596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Itct.co = subst_AvailExpr_Temp( env, ae->u.Itct.co );
3597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Itct.e0 = subst_AvailExpr_Temp( env, ae->u.Itct.e0 );
3598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Itcc:
3600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.Itcc.co = subst_AvailExpr_Temp( env, ae->u.Itcc.co );
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case GetIt:
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ae->u.GetIt.ix = subst_AvailExpr_Temp( env, ae->u.GetIt.ix );
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case CCall: {
3606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int i, n = ae->u.CCall.nArgs;;
3607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < n; i++) {
3608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            TmpOrConst* tc = &ae->u.CCall.args[i];
3609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (tc->tag == TCt) {
3610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               tc->u.tmp = subst_AvailExpr_Temp( env, tc->u.tmp );
3611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("subst_AvailExpr");
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AvailExpr* irExpr_to_AvailExpr ( IRExpr* e )
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* ae;
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (e->tag) {
3625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_Unop:
3626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.Unop.arg->tag == Iex_RdTmp) {
3627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae = LibVEX_Alloc(sizeof(AvailExpr));
3628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->tag      = Ut;
3629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.Ut.op  = e->Iex.Unop.op;
3630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.Ut.arg = e->Iex.Unop.arg->Iex.RdTmp.tmp;
3631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return ae;
3632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_Binop:
3636436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.Binop.arg1->tag == Iex_RdTmp) {
3637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (e->Iex.Binop.arg2->tag == Iex_RdTmp) {
3638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae = LibVEX_Alloc(sizeof(AvailExpr));
3639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->tag        = Btt;
3640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->u.Btt.op   = e->Iex.Binop.op;
3641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->u.Btt.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->u.Btt.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
3643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return ae;
3644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (e->Iex.Binop.arg2->tag == Iex_Const) {
3646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae = LibVEX_Alloc(sizeof(AvailExpr));
3647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->tag        = Btc;
3648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->u.Btc.op   = e->Iex.Binop.op;
3649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->u.Btc.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ae->u.Btc.con2 = *(e->Iex.Binop.arg2->Iex.Const.con);
3651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return ae;
3652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else if (e->Iex.Binop.arg1->tag == Iex_Const
3654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    && e->Iex.Binop.arg2->tag == Iex_RdTmp) {
3655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae = LibVEX_Alloc(sizeof(AvailExpr));
3656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->tag        = Bct;
3657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.Bct.op   = e->Iex.Binop.op;
3658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.Bct.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
3659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.Bct.con1 = *(e->Iex.Binop.arg1->Iex.Const.con);
3660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return ae;
3661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_Const:
3665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.Const.con->tag == Ico_F64i) {
3666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae = LibVEX_Alloc(sizeof(AvailExpr));
3667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->tag          = Cf64i;
3668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.Cf64i.f64i = e->Iex.Const.con->Ico.F64i;
3669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return ae;
3670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
3674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.ITE.cond->tag == Iex_RdTmp) {
3675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (e->Iex.ITE.iffalse->tag == Iex_RdTmp) {
3676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (e->Iex.ITE.iftrue->tag == Iex_RdTmp) {
3677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae = LibVEX_Alloc(sizeof(AvailExpr));
3678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->tag       = Ittt;
3679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Ittt.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Ittt.e1 = e->Iex.ITE.iftrue->Iex.RdTmp.tmp;
3681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Ittt.e0 = e->Iex.ITE.iffalse->Iex.RdTmp.tmp;
3682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return ae;
3683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
3684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (e->Iex.ITE.iftrue->tag == Iex_Const) {
3685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae = LibVEX_Alloc(sizeof(AvailExpr));
3686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->tag       = Itct;
3687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Itct.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Itct.con1 = *(e->Iex.ITE.iftrue->Iex.Const.con);
3689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Itct.e0 = e->Iex.ITE.iffalse->Iex.RdTmp.tmp;
3690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return ae;
3691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
3692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else if (e->Iex.ITE.iffalse->tag == Iex_Const) {
3693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (e->Iex.ITE.iftrue->tag == Iex_RdTmp) {
3694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae = LibVEX_Alloc(sizeof(AvailExpr));
3695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->tag       = Ittc;
3696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Ittc.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Ittc.e1 = e->Iex.ITE.iftrue->Iex.RdTmp.tmp;
3698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Ittc.con0 = *(e->Iex.ITE.iffalse->Iex.Const.con);
3699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return ae;
3700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
3701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (e->Iex.ITE.iftrue->tag == Iex_Const) {
3702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae = LibVEX_Alloc(sizeof(AvailExpr));
3703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->tag       = Itcc;
3704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Itcc.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Itcc.con1 = *(e->Iex.ITE.iftrue->Iex.Const.con);
3706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ae->u.Itcc.con0 = *(e->Iex.ITE.iffalse->Iex.Const.con);
3707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return ae;
3708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
3709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_GetI:
3714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.GetI.ix->tag == Iex_RdTmp) {
3715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae = LibVEX_Alloc(sizeof(AvailExpr));
3716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->tag           = GetIt;
3717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.GetIt.descr = e->Iex.GetI.descr;
3718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.GetIt.ix    = e->Iex.GetI.ix->Iex.RdTmp.tmp;
3719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ae->u.GetIt.bias  = e->Iex.GetI.bias;
3720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return ae;
3721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_CCall:
3725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae = LibVEX_Alloc(sizeof(AvailExpr));
3726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->tag = CCall;
3727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Ok to share only the cee, since it is immutable. */
3728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.CCall.cee   = e->Iex.CCall.cee;
3729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ae->u.CCall.retty = e->Iex.CCall.retty;
3730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* irExprVec_to_TmpOrConsts will assert if the args are
3731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            neither tmps nor constants, but that's ok .. that's all they
3732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            should be. */
3733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         irExprVec_to_TmpOrConsts(
3734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  &ae->u.CCall.args, &ae->u.CCall.nArgs,
3735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  e->Iex.CCall.args
3736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 );
3737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return ae;
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
3740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The BB is modified in-place.  Returns True if any changes were
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   made. */
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool do_cse_BB ( IRSB* bb )
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, j, paranoia;
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp     t, q;
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* eprime;
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AvailExpr* ae;
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       invalidate;
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       anyDone = False;
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* tenv = newHHW(); /* :: IRTemp -> IRTemp */
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HashHW* aenv = newHHW(); /* :: AvailExpr* -> IRTemp */
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sizeof(IRTemp) <= sizeof(HWord));
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) { ppIRSB(bb); vex_printf("\n\n"); }
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate forwards over the stmts.
3768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      On seeing "t = E", where E is one of the AvailExpr forms:
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         let E' = apply tenv substitution to E
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         search aenv for E'
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if a mapping E' -> q is found,
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               replace this stmt by "t = q"
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and add binding t -> q to tenv
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add binding E' -> t to aenv
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               replace this stmt by "t = E'"
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Other statements are only interesting to the extent that they
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      might invalidate some of the expressions in aenv.  So there is
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an invalidate-bindings check for each statement seen.
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ BEGIN invalidate aenv bindings ------ */
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is critical: remove from aenv any E' -> .. bindings
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         which might be invalidated by this statement.  The only
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vulnerable kind of bindings are the GetI kind.
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Dirty call - dump (paranoia level -> 2)
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Store      - dump (ditto)
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Put, PutI  - dump unless no-overlap is proven (.. -> 1)
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Uses getAliasingRelation_IC and getAliasingRelation_II
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to do the no-overlap assessments needed for Put/PutI.
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty: case Ist_Store: case Ist_MBE:
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS: case Ist_LLSC:
3798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_StoreG:
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 2; break;
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put: case Ist_PutI:
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 1; break;
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp: case Ist_IMark: case Ist_AbiHint:
3803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_WrTmp: case Ist_Exit: case Ist_LoadG:
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            paranoia = 0; break;
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("do_cse_BB(1)");
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (paranoia > 0) {
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < aenv->used; j++) {
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!aenv->inuse[j])
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ae = (AvailExpr*)aenv->key[j];
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ae->tag != GetIt)
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalidate = False;
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (paranoia >= 2) {
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               invalidate = True;
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(paranoia == 1);
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (st->tag == Ist_Put) {
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (getAliasingRelation_IC(
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.descr,
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(ae->u.GetIt.ix),
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         st->Ist.Put.offset,
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         typeOfIRExpr(bb->tyenv,st->Ist.Put.data)
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ) != NoAlias)
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     invalidate = True;
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (st->tag == Ist_PutI) {
3832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRPutI *puti = st->Ist.PutI.details;
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (getAliasingRelation_II(
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.descr,
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_RdTmp(ae->u.GetIt.ix),
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ae->u.GetIt.bias,
3837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         puti->descr,
3838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         puti->ix,
3839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         puti->bias
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ) != NoAlias)
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     invalidate = True;
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vpanic("do_cse_BB(2)");
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (invalidate) {
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               aenv->inuse[j] = False;
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               aenv->key[j]   = (HWord)NULL;  /* be sure */
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } /* for j */
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* paranoia > 0 */
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ ENV invalidate aenv bindings ------ */
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore not-interestings */
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp)
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t = st->Ist.WrTmp.tmp;
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eprime = irExpr_to_AvailExpr(st->Ist.WrTmp.data);
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore if not of AvailExpr form */
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!eprime)
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("considering: " ); ppIRStmt(st); vex_printf("\n"); */
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* apply tenv */
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subst_AvailExpr( tenv, eprime );
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* search aenv for eprime, unfortunately the hard way */
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = 0; j < aenv->used; j++)
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (aenv->inuse[j] && eq_AvailExpr(eprime, (AvailExpr*)aenv->key[j]))
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (j < aenv->used) {
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A binding E' -> q was found.  Replace stmt by "t = q" and
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            note the t->q binding in tenv. */
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* (this is the core of the CSE action) */
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         q = (IRTemp)aenv->val[j];
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_WrTmp( t, IRExpr_RdTmp(q) );
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( tenv, (HWord)t, (HWord)q );
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         anyDone = True;
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No binding was found, so instead we add E' -> t to our
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            collection of available expressions, replace this stmt
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            with "t = E'", and move on. */
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_WrTmp( t, availExpr_to_IRExpr(eprime) );
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToHHW( aenv, (HWord)eprime, (HWord)t );
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRSB(bb);
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sanityCheckIRSB(bb, Ity_I32);
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n\n");
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return anyDone;
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Add32/Sub32 chain collapsing                            ---*/
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ----- Helper functions for Add32/Sub32 chain collapsing ----- */
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this expression "Add32(tmp,const)" or "Sub32(tmp,const)" ?  If
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   yes, set *tmp and *i32 appropriately.  *i32 is set as if the
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   root node is Add32, not Sub32. */
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isAdd32OrSub32 ( IRExpr* e, IRTemp* tmp, Int* i32 )
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag != Iex_Binop)
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.op != Iop_Add32 && e->Iex.Binop.op != Iop_Sub32)
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.arg1->tag != Iex_RdTmp)
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.arg2->tag != Iex_Const)
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *tmp = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i32 = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32);
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->Iex.Binop.op == Iop_Sub32)
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *i32 = -*i32;
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if tmp can be expressed as tmp2 +32 const, for some
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   other tmp2.  Scan backwards from the specified start point -- an
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisation. */
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool collapseChain ( IRSB* bb, Int startHere,
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp tmp,
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRTemp* tmp2, Int* i32 )
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     j, ii;
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  vv;
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* the (var, con) pair contain the current 'representation' for
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'tmp'.  We start with 'tmp + 0'.  */
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp var = tmp;
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    con = 0;
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan backwards to see if tmp can be replaced by some other tmp
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     +/- a constant. */
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = startHere; j >= 0; j--) {
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[j];
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_WrTmp)
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->Ist.WrTmp.tmp != var)
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = st->Ist.WrTmp.data;
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isAdd32OrSub32(e, &vv, &ii))
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      var = vv;
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con += ii;
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (j == -1)
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no earlier binding for var .. ill-formed IR */
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("collapseChain");
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* so, did we find anything interesting? */
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (var == tmp)
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; /* no .. */
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *tmp2 = var;
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i32  = con;
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------- Main function for Add32/Sub32 chain collapsing ------ */
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void collapse_AddSub_chains_BB ( IRSB* bb )
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt *st;
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp var, var2;
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, con, con2;
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Try to collapse 't1 = Add32/Sub32(t2, con)'. */
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && isAdd32OrSub32(st->Ist.WrTmp.data, &var, &con)) {
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* So e1 is of the form Add32(var,con) or Sub32(var,-con).
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Find out if var can be expressed as var2 + con2. */
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (collapseChain(bb, i-1, var, &var2, &con2)) {
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("replacing1 ");
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRStmt(st);
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf(" with ");
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            con2 += con;
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i]
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = IRStmt_WrTmp(
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    st->Ist.WrTmp.tmp,
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (con2 >= 0)
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? IRExpr_Binop(Iop_Add32,
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_RdTmp(var2),
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Const(IRConst_U32(con2)))
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : IRExpr_Binop(Iop_Sub32,
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_RdTmp(var2),
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Const(IRConst_U32(-con2)))
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRStmt(bb->stmts[i]);
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Try to collapse 't1 = GetI[t2, con]'. */
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_GetI
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && collapseChain(bb, i-1, st->Ist.WrTmp.data->Iex.GetI.ix
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ->Iex.RdTmp.tmp, &var2, &con2)) {
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("replacing3 ");
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" with ");
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         con2 += st->Ist.WrTmp.data->Iex.GetI.bias;
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i]
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_WrTmp(
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.WrTmp.tmp,
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_GetI(st->Ist.WrTmp.data->Iex.GetI.descr,
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_RdTmp(var2),
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             con2));
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(bb->stmts[i]);
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perhaps st is PutI[t, con] ? */
4050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRPutI *puti = st->Ist.PutI.details;
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_PutI
4052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && puti->ix->tag == Iex_RdTmp
4053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && collapseChain(bb, i-1, puti->ix->Iex.RdTmp.tmp,
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               &var2, &con2)) {
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("replacing2 ");
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" with ");
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         con2 += puti->bias;
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i]
4062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            = IRStmt_PutI(mkIRPutI(puti->descr,
4063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   IRExpr_RdTmp(var2),
4064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   con2,
4065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   puti->data));
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(bb->stmts[i]);
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for */
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PutI/GetI transformations                               ---*/
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given the parts (descr, tmp, bias) for a GetI, scan backwards from
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the given starting point to find, if any, a PutI which writes
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exactly the same piece of guest state, and so return the expression
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that the PutI writes.  This is the core of PutI-GetI forwarding. */
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* findPutI ( IRSB* bb, Int startHere,
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRRegArray* descrG, IRExpr* ixG, Int biasG )
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        j;
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing relation;
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\nfindPutI ");
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRRegArray(descrG);
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" ");
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(ixG);
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(" %d\n", biasG);
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan backwards in bb from startHere to find a suitable PutI
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binding for (descrG, ixG, biasG), if any. */
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = startHere; j >= 0; j--) {
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[j];
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Put) {
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Non-indexed Put.  This can't give a binding, but we do
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            need to check it doesn't invalidate the search by
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            overlapping any part of the indexed guest state. */
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_IC(
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 descrG, ixG,
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.Put.offset,
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == NoAlias) {
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we're OK; keep going */
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relation == UnknownAlias || relation == ExactAlias */
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* If this assertion fails, we've found a Put which writes
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               an area of guest state which is read by a GetI.  Which
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               is unlikely (although not per se wrong). */
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(relation != ExactAlias);
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This Put potentially writes guest state that the GetI
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reads; we must fail. */
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_PutI) {
4137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *puti = st->Ist.PutI.details;
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation = getAliasingRelation_II(
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       descrG, ixG, biasG,
4141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       puti->descr,
4142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       puti->ix,
4143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       puti->bias
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    );
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == NoAlias) {
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This PutI definitely doesn't overlap.  Ignore it and
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               keep going. */
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue; /* the for j loop */
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (relation == UnknownAlias) {
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We don't know if this PutI writes to the same guest
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state that the GetI, or not.  So we have to give up. */
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Otherwise, we've found what we're looking for.  */
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(relation == ExactAlias);
4160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return puti->data;
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* if (st->tag == Ist_PutI) */
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_Dirty) {
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Be conservative.  If the dirty call has any guest effects at
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            all, give up.  We could do better -- only give up if there
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            are any guest writes/modifies. */
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.Dirty.details->nFxState > 0)
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for */
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No valid replacement was found. */
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assuming pi is a PutI stmt, is s2 identical to it (in the sense
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that it writes exactly the same piece of guest state) ?  Safe
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   answer: False. */
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool identicalPutIs ( IRStmt* pi, IRStmt* s2 )
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pi->tag == Ist_PutI);
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s2->tag != Ist_PutI)
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI *p1 = pi->Ist.PutI.details;
4191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI *p2 = s2->Ist.PutI.details;
4192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getAliasingRelation_II(
4195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             p1->descr, p1->ix, p1->bias,
4196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             p2->descr, p2->ix, p2->bias
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          )
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          == ExactAlias
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assuming pi is a PutI stmt, is s2 a Get/GetI/Put/PutI which might
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overlap it?  Safe answer: True.  Note, we could do a lot better
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   than this if needed. */
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool guestAccessWhichMightOverlapPutI (
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTypeEnv* tyenv, IRStmt* pi, IRStmt* s2
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     )
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GSAliasing relation;
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       minoffP, maxoffP;
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(pi->tag == Ist_PutI);
4216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI *p1 = pi->Ist.PutI.details;
4218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   getArrayBounds(p1->descr, &minoffP, &maxoffP);
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (s2->tag) {
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* just be paranoid ... these should be rare. */
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is unbelievably lame, but it's probably not
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            significant from a performance point of view.  Really, a
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CAS is a load-store op, so it should be safe to say False.
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            However .. */
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If the dirty call has any guest effects at all, give up.
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Probably could do better. */
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.Dirty.details->nFxState > 0)
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Put.data));
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_IC(
4249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 p1->descr, p1->ix,
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 s2->Ist.Put.offset,
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(tyenv,s2->Ist.Put.data)
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto have_relation;
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_PutI: {
4256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *p2 = s2->Ist.PutI.details;
4257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(p2->ix));
4259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(isIRAtom(p2->data));
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relation
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = getAliasingRelation_II(
4262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 p1->descr, p1->ix, p1->bias,
4263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 p2->descr, p2->ix, p2->bias
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto have_relation;
4266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.WrTmp.data->tag == Iex_GetI) {
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relation
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = getAliasingRelation_II(
4272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    p1->descr, p1->ix, p1->bias,
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.descr,
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.ix,
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.GetI.bias
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto have_relation;
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (s2->Ist.WrTmp.data->tag == Iex_Get) {
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relation
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = getAliasingRelation_IC(
4282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    p1->descr, p1->ix,
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.Get.offset,
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s2->Ist.WrTmp.data->Iex.Get.ty
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto have_relation;
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Store.addr));
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(isIRAtom(s2->Ist.Store.data));
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(s2); vex_printf("\n");
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("guestAccessWhichMightOverlapPutI");
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  have_relation:
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (relation == NoAlias)
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True; /* ExactAlias or UnknownAlias */
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------- PutI/GetI transformations main functions --------- */
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remove redundant GetIs, to the extent that they can be detected.
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb is modified in-place. */
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_redundant_GetI_elimination ( IRSB* bb )
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb->stmts_used-1; i >= 0; i--) {
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->tag == Iex_GetI
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp) {
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr = st->Ist.WrTmp.data->Iex.GetI.descr;
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr*     ix    = st->Ist.WrTmp.data->Iex.GetI.ix;
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int         bias  = st->Ist.WrTmp.data->Iex.GetI.bias;
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr*     replacement = findPutI(bb, i-1, descr, ix, bias);
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (replacement
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && isIRAtom(replacement)
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* Make sure we're doing a type-safe transformation! */
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && typeOfIRExpr(bb->tyenv, replacement) == descr->elemTy) {
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (DEBUG_IROPT) {
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("rGI:  ");
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(st->Ist.WrTmp.data);
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf(" -> ");
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(replacement);
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, replacement);
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remove redundant PutIs, to the extent which they can be detected.
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb is modified in-place. */
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_redundant_PutI_elimination ( IRSB* bb )
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, j;
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   delete;
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt *st, *stj;
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn);
4362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_PutI)
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, search forwards from here to see if we can find another
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PutI which makes this one redundant, and dodging various
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         hazards.  Search forwards:
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If conditional exit, give up (because anything after that
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           does not postdominate this put).
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Get which might overlap, give up (because this PutI
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           not necessarily dead).
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which is identical, stop with success.
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which might overlap, but is not identical, give up.
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a dirty helper call which might write guest state, give up.
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * If a Put which definitely doesn't overlap, or any other
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           kind of stmt, continue.
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete = False;
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = i+1; j < bb->stmts_used; j++) {
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stj = bb->stmts[j];
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stj->tag == Ist_NoOp)
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (identicalPutIs(st, stj)) {
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* success! */
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete = True;
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stj->tag == Ist_Exit)
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up */
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag == Ist_Dirty)
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up; could do better here */
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (guestAccessWhichMightOverlapPutI(bb->tyenv, st, stj))
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* give up */
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (delete) {
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT) {
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("rPI:  ");
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[i] = IRStmt_NoOp();
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Loop unrolling                                          ---*/
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust all tmp values (names) in e by delta.  e is destructively
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified. */
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deltaIRExpr ( IRExpr* e, Int delta )
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e->Iex.RdTmp.tmp += delta;
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.GetI.ix, delta);
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg1, delta);
4436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg2, delta);
4437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg3, delta);
4438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Qop.details->arg4, delta);
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Triop.details->arg1, delta);
4442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Triop.details->arg2, delta);
4443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(e->Iex.Triop.details->arg3, delta);
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Binop.arg1, delta);
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Binop.arg2, delta);
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Unop.arg, delta);
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(e->Iex.Load.addr, delta);
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(e->Iex.CCall.args[i], delta);
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
4460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(e->Iex.ITE.cond, delta);
4461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(e->Iex.ITE.iftrue, delta);
4462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(e->Iex.ITE.iffalse, delta);
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("deltaIRExpr");
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adjust all tmp values (names) in st by delta.  st is destructively
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified. */
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deltaIRStmt ( IRStmt* st, Int delta )
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.AbiHint.base, delta);
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.AbiHint.nia, delta);
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Put.data, delta);
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
4490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(st->Ist.PutI.details->ix, delta);
4491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         deltaIRExpr(st->Ist.PutI.details->data, delta);
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.WrTmp.tmp += delta;
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.WrTmp.data, delta);
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Exit.guard, delta);
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Store.addr, delta);
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.Store.data, delta);
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
4505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
4506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(sg->addr, delta);
4507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(sg->data, delta);
4508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(sg->guard, delta);
4509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
4510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
4511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
4512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
4513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         lg->dst += delta;
4514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(lg->addr, delta);
4515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(lg->alt, delta);
4516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         deltaIRExpr(lg->guard, delta);
4517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
4518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->oldHi != IRTemp_INVALID)
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            st->Ist.CAS.details->oldHi += delta;
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.CAS.details->oldLo += delta;
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->addr, delta);
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->expdHi)
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.CAS.details->expdHi, delta);
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->expdLo, delta);
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.CAS.details->dataHi)
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.CAS.details->dataHi, delta);
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.CAS.details->dataLo, delta);
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         st->Ist.LLSC.result += delta;
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(st->Ist.LLSC.addr, delta);
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(st->Ist.LLSC.storedata, delta);
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRExpr(d->guard, delta);
4540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         for (i = 0; d->args[i]; i++) {
4541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr* arg = d->args[i];
4542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
4543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               deltaIRExpr(arg, delta);
4544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->tmp != IRTemp_INVALID)
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d->tmp += delta;
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mAddr)
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            deltaIRExpr(d->mAddr, delta);
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("deltaIRStmt");
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If possible, return a loop-unrolled version of bb0.  The original
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is changed.  If not possible, return NULL.  */
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The two schemas considered are:
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     X: BODY; goto X
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     which unrolls to (eg)  X: BODY;BODY; goto X
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       X: BODY; if (c) goto X; goto Y
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which trivially transforms to
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       X: BODY; if (!c) goto Y; goto X;
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so it falls in the scope of the first case.
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X and Y must be literal (guest) addresses.
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int calc_unroll_factor( IRSB* bb )
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int n_stmts, i;
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_stmts = 0;
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb->stmts[i]->tag != Ist_NoOp)
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_stmts++;
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/8) {
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 8 x unrolling (%d sts -> %d sts)\n",
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 8* n_stmts);
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 8;
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/4) {
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 4 x unrolling (%d sts -> %d sts)\n",
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 4* n_stmts);
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 4;
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_stmts <= vex_control.iropt_unroll_thresh/2) {
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_control.iropt_verbosity > 0)
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("vex iropt: 2 x unrolling (%d sts -> %d sts)\n",
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_stmts, 2* n_stmts);
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 2;
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_verbosity > 0)
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("vex iropt: not unrolling (%d sts)\n", n_stmts);
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 1;
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* maybe_loop_unroll_BB ( IRSB* bb0, Addr64 my_addr )
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j, jmax, n_vars;
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     xxx_known;
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64   xxx_value, yyy_value;
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  udst;
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB     *bb1, *bb2;
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      unroll_factor;
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_unroll_thresh <= 0)
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First off, figure out if we can unroll this loop.  Do this
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      without modifying bb0. */
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bb0->jumpkind != Ijk_Boring)
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_known = False;
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_value = 0;
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Extract the next-guest address.  If it isn't a literal, we
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to give up. */
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = bb0->next;
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (udst->tag == Iex_Const
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (udst->Iex.Const.con->tag == Ico_U32
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || udst->Iex.Const.con->tag == Ico_U64)) {
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The BB ends in a jump to a literal location. */
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xxx_known = True;
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xxx_value = udst->Iex.Const.con->tag == Ico_U64
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ?  udst->Iex.Const.con->Ico.U64
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    : (Addr64)(udst->Iex.Const.con->Ico.U32);
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!xxx_known)
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we know the BB ends to a jump to a literal location.  If
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it's a jump to itself (viz, idiom #1), move directly to the
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrolling stage, first cloning the bb so the original isn't
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      modified. */
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xxx_value == my_addr) {
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unroll_factor = calc_unroll_factor( bb0 );
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (unroll_factor < 2)
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return NULL;
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb1 = deepCopyIRSB( bb0 );
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb0 = NULL;
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst = NULL; /* is now invalid */
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto do_unroll;
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Search for the second idiomatic form:
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        X: BODY; if (c) goto X; goto Y
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      We know Y, but need to establish that the last stmt
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is 'if (c) goto X'.
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   yyy_value = xxx_value;
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb0->stmts_used-1; i >= 0; i--)
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb0->stmts[i])
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i < 0)
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL; /* block with no stmts.  Strange. */
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = bb0->stmts[i];
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (st->tag != Ist_Exit)
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (st->Ist.Exit.jk != Ijk_Boring)
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = st->Ist.Exit.dst;
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xxx_value = con->tag == Ico_U64
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ? st->Ist.Exit.dst->Ico.U64
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  : (Addr64)(st->Ist.Exit.dst->Ico.U32);
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this assertion fails, we have some kind of type error. */
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == udst->Iex.Const.con->tag);
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xxx_value != my_addr)
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We didn't find either idiom.  Give up. */
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, we found idiom #2.  Copy the BB, switch around the xxx and
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      yyy values (which makes it look like idiom #1), and go into
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrolling proper.  This means finding (again) the last stmt, in
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the copied BB. */
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unroll_factor = calc_unroll_factor( bb0 );
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (unroll_factor < 2)
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb1 = deepCopyIRSB( bb0 );
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb0 = NULL;
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = NULL; /* is now invalid */
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = bb1->stmts_used-1; i >= 0; i--)
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb1->stmts[i])
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The next bunch of assertions should be true since we already
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      found and checked the last stmt in the original bb. */
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i >= 0);
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = bb1->stmts[i];
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(st->tag == Ist_Exit);
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = st->Ist.Exit.dst;
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   udst = bb1->next;
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(udst->tag == Iex_Const);
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(udst->Iex.Const.con->tag == Ico_U32
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || udst->Iex.Const.con->tag == Ico_U64);
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(con->tag == udst->Iex.Const.con->tag);
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* switch the xxx and yyy fields around */
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (con->tag == Ico_U64) {
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst->Iex.Const.con->Ico.U64 = xxx_value;
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con->Ico.U64 = yyy_value;
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      udst->Iex.Const.con->Ico.U32 = (UInt)xxx_value;
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      con->Ico.U32 = (UInt)yyy_value;
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* negate the test condition */
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st->Ist.Exit.guard
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = IRExpr_Unop(Iop_Not1,deepCopyIRExpr(st->Ist.Exit.guard));
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- The unroller proper.  Both idioms are by now --- */
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- now converted to idiom 1. --- */
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do_unroll:
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(unroll_factor == 2
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || unroll_factor == 4
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || unroll_factor == 8);
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   jmax = unroll_factor==8 ? 3 : (unroll_factor==4 ? 2 : 1);
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 1; j <= jmax; j++) {
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_vars = bb1->tyenv->types_used;
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb2 = deepCopyIRSB(bb1);
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_vars; i++)
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void)newIRTemp(bb1->tyenv, bb2->tyenv->types[i]);
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < bb2->stmts_used; i++) {
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* deltaIRStmt destructively modifies the stmt, but
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that's OK since bb2 is a complete fresh copy of bb1. */
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         deltaIRStmt(bb2->stmts[i], n_vars);
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb1, bb2->stmts[i]);
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_IROPT) {
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\nUNROLLED (%llx)\n", my_addr);
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb1);
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flattening; sigh.  The unroller succeeds in breaking flatness
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by negating the test condition.  This should be fixed properly.
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      For the moment use this shotgun approach.  */
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return flatten_BB(bb1);
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The tree builder                                        ---*/
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This isn't part of IR optimisation.  Really it's a pass done prior
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to instruction selection, which improves the code that the
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction selector can produce. */
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- The 'tmp' environment is the central data structure here --- */
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The number of outstanding bindings we're prepared to track.
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The number of times the env becomes full and we have to dump
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the oldest binding (hence reducing code quality) falls very
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rapidly as the env size increases.  8 gives reasonable performance
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   under most circumstances. */
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define A_NENV 10
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* An interval. Used to record the bytes in the guest state accessed
4803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   by a Put[I] statement or by (one or more) Get[I] expression(s). In
4804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case of several Get[I] expressions, the lower/upper bounds are recorded.
4805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This is conservative but cheap.
4806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   E.g. a Put of 8 bytes at address 100 would be recorded as [100,107].
4807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   E.g. an expression that reads 8 bytes at offset 100 and 4 bytes at
4808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   offset 200 would be recorded as [100,203] */
4809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef
4810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct {
4811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool present;
4812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int  low;
4813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int  high;
4814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
4815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Interval;
4816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic inline Bool
4818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovintervals_overlap(Interval i1, Interval i2)
4819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
4820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return (i1.low >= i2.low && i1.low <= i2.high) ||
4821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          (i2.low >= i1.low && i2.low <= i1.high);
4822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
4823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic inline void
4825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovupdate_interval(Interval *i, Int low, Int high)
4826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
4827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(low <= high);
4828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (i->present) {
4830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (low  < i->low)  i->low  = low;
4831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (high > i->high) i->high = high;
4832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
4833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      i->present = True;
4834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      i->low  = low;
4835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      i->high = high;
4836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
4837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
4838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bindee == NULL   ===  slot is not in use
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bindee != NULL   ===  slot is in use
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  binder;
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* bindee;
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    doesLoad;
4848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Record the bytes of the guest state BINDEE reads from. */
4849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Interval getInterval;
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ATmpInfo;
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused))
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppAEnv ( ATmpInfo* env )
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%d  tmp %d  val ", i, (Int)env[i].binder);
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[i].bindee)
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(env[i].bindee);
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("(null)");
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Tree-traversal fns --- */
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Traverse an expr, and detect if any part of it reads memory or does
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a Get.  Be careful ... this really controls how much the
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tree-builder can reorder the code, so getting it right is critical.
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void setHints_Expr (Bool* doesLoad, Interval* getInterval, IRExpr* e )
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
4879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            setHints_Expr(doesLoad, getInterval, e->Iex.CCall.args[i]);
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
4882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.ITE.cond);
4883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.ITE.iftrue);
4884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.ITE.iffalse);
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4887436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg1);
4888436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg2);
4889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg3);
4890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg4);
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4893436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Triop.details->arg1);
4894436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Triop.details->arg2);
4895436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Triop.details->arg3);
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4898436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Binop.arg1);
4899436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Binop.arg2);
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4902436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Unop.arg);
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *doesLoad = True;
4906436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.Load.addr);
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_Get: {
4909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int low = e->Iex.Get.offset;
4910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int high = low + sizeofIRType(e->Iex.Get.ty) - 1;
4911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         update_interval(getInterval, low, high);
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4913436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
4914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_GetI: {
4915436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRRegArray *descr = e->Iex.GetI.descr;
4916436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int size = sizeofIRType(descr->elemTy);
4917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int low  = descr->base;
4918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int high = low + descr->nElems * size - 1;
4919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         update_interval(getInterval, low, high);
4920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(doesLoad, getInterval, e->Iex.GetI.ix);
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("setHints_Expr");
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a binding to the front of the env and slide all the rest
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   backwards.  It should be the case that the last slot is free. */
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addToEnvFront ( ATmpInfo* env, IRTemp binder, IRExpr* bindee )
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env[A_NENV-1].bindee == NULL);
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = A_NENV-1; i >= 1; i--)
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i] = env[i-1];
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].binder   = binder;
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].bindee   = bindee;
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env[0].doesLoad = False; /* filled in later */
4944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   env[0].getInterval.present  = False; /* filled in later */
4945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   env[0].getInterval.low  = -1; /* filled in later */
4946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   env[0].getInterval.high = -1; /* filled in later */
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given uses :: array of UShort, indexed by IRTemp
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Add the use-occurrences of temps in this expression
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the env.
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void aoccCount_Expr ( UShort* uses, IRExpr* e )
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp: /* the only interesting case */
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uses[e->Iex.RdTmp.tmp]++;
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
4964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, e->Iex.ITE.cond);
4965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, e->Iex.ITE.iftrue);
4966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, e->Iex.ITE.iffalse);
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg1);
4971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg2);
4972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg3);
4973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Qop.details->arg4);
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Triop.details->arg1);
4978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Triop.details->arg2);
4979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, e->Iex.Triop.details->arg3);
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Binop.arg1);
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Binop.arg2);
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Unop.arg);
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.Load.addr);
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; e->Iex.CCall.args[i]; i++)
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, e->Iex.CCall.args[i]);
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, e->Iex.GetI.ix);
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("aoccCount_Expr");
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given uses :: array of UShort, indexed by IRTemp
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Add the use-occurrences of temps in this statement
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the env.
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void aoccCount_Stmt ( UShort* uses, IRStmt* st )
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.AbiHint.base);
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.AbiHint.nia);
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.WrTmp.data);
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Put.data);
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
5036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, st->Ist.PutI.details->ix);
5037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         aoccCount_Expr(uses, st->Ist.PutI.details->data);
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Store.addr);
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Store.data);
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
5044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
5045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, sg->addr);
5046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, sg->data);
5047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, sg->guard);
5048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return;
5049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
5051436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
5052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, lg->addr);
5053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, lg->alt);
5054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         aoccCount_Expr(uses, lg->guard);
5055436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return;
5056436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->addr);
5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->expdHi)
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, cas->expdHi);
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->expdLo);
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cas->dataHi)
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, cas->dataHi);
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, cas->dataLo);
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.LLSC.addr);
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata)
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, st->Ist.LLSC.storedata);
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mFx != Ifx_None)
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aoccCount_Expr(uses, d->mAddr);
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, d->guard);
5077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         for (i = 0; d->args[i]; i++) {
5078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr* arg = d->args[i];
5079436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
5080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               aoccCount_Expr(uses, arg);
5081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aoccCount_Expr(uses, st->Ist.Exit.guard);
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("aoccCount_Stmt");
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up a binding for tmp in the env.  If found, return the bound
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, and set the env's binding to NULL so it is marked as
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used.  If not found, return NULL. */
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* atbSubst_Temp ( ATmpInfo* env, IRTemp tmp )
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[i].binder == tmp && env[i].bindee != NULL) {
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* bindee = env[i].bindee;
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[i].bindee = NULL;
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return bindee;
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Traverse e, looking for temps.  For each observed temp, see if env
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   contains a binding for the temp, and if so return the bound value.
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The env has the property that any binding it holds is
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'single-shot', so once a binding is used, it is marked as no longer
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   available, by setting its .bindee field to NULL. */
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool is_Unop ( IRExpr* e, IROp op ) {
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Unop && e->Iex.Unop.op == op;
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool is_Binop ( IRExpr* e, IROp op ) {
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Binop && e->Iex.Binop.op == op;
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_IRExpr_Binop ( IROp op, IRExpr* a1, IRExpr* a2 )
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_Or32:
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Or32( CmpwNEZ32(x), CmpwNEZ32(y) ) --> CmpwNEZ32( Or32( x, y ) )  */
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(a1, Iop_CmpwNEZ32) && is_Unop(a2, Iop_CmpwNEZ32))
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32,
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Binop( Iop_Or32, a1->Iex.Unop.arg,
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     a2->Iex.Unop.arg ) );
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
5137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Iop_CmpNE32:
5138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Since X has type Ity_I1 we can simplify:
5139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         CmpNE32(1Uto32(X),0)) ==> X */
5140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(a1, Iop_1Uto32) && isZeroU32(a2))
5141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return a1->Iex.Unop.arg;
5142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
5143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no reduction rule applies */
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop( op, a1, a2 );
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* fold_IRExpr_Unop ( IROp op, IRExpr* aa )
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpwNEZ64:
5155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* CmpwNEZ64( CmpwNEZ64 ( x ) ) --> CmpwNEZ64 ( x ) */
5156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (is_Unop(aa, Iop_CmpwNEZ64))
5157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_Unop( Iop_CmpwNEZ64, aa->Iex.Unop.arg );
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64( Or64 ( CmpwNEZ64(x), y ) ) --> CmpwNEZ64( Or64( x, y ) ) */
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Binop(aa, Iop_Or64)
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Binop.arg1, Iop_CmpwNEZ64))
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Iop_CmpwNEZ64,
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Binop(Iop_Or64,
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg1->Iex.Unop.arg,
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg2));
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64( Or64 ( x, CmpwNEZ64(y) ) ) --> CmpwNEZ64( Or64( x, y ) ) */
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Binop(aa, Iop_Or64)
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Binop.arg2, Iop_CmpwNEZ64))
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Iop_CmpwNEZ64,
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRExpr_Binop(Iop_Or64,
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg1,
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                aa->Iex.Binop.arg2->Iex.Unop.arg));
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpNEZ64:
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpNEZ64( Left64(x) ) --> CmpNEZ64(x) */
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left64))
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_CmpNEZ64, aa->Iex.Unop.arg);
5179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* CmpNEZ64( 1Uto64(X) ) --> X */
5180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (is_Unop(aa, Iop_1Uto64))
5181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return aa->Iex.Unop.arg;
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpwNEZ32:
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ32( CmpwNEZ32 ( x ) ) --> CmpwNEZ32 ( x ) */
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ32))
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32, aa->Iex.Unop.arg );
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_CmpNEZ32:
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpNEZ32( Left32(x) ) --> CmpNEZ32(x) */
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left32))
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_CmpNEZ32, aa->Iex.Unop.arg);
5192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* CmpNEZ32( 1Uto32(X) ) --> X */
5193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(aa, Iop_1Uto32))
5194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return aa->Iex.Unop.arg;
5195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* CmpNEZ32( 64to32( CmpwNEZ64(X) ) ) --> CmpNEZ64(X) */
5196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (is_Unop(aa, Iop_64to32) && is_Unop(aa->Iex.Unop.arg, Iop_CmpwNEZ64))
5197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_Unop(Iop_CmpNEZ64, aa->Iex.Unop.arg->Iex.Unop.arg);
5198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
5199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Iop_CmpNEZ8:
5200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* CmpNEZ8( 1Uto8(X) ) --> X */
5201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_Unop(aa, Iop_1Uto8))
5202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return aa->Iex.Unop.arg;
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_Left32:
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Left32( Left32(x) ) --> Left32(x) */
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_Left32))
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_Left32, aa->Iex.Unop.arg );
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Iop_Left64:
5210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Left64( Left64(x) ) --> Left64(x) */
5211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (is_Unop(aa, Iop_Left64))
5212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_Unop( Iop_Left64, aa->Iex.Unop.arg );
5213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      break;
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_32to1:
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32to1( 1Uto32 ( x ) ) --> x */
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_1Uto32))
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32to1( CmpwNEZ32 ( x )) --> CmpNEZ32(x) */
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ32))
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpNEZ32, aa->Iex.Unop.arg );
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_64to1:
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to1( 1Uto64 ( x ) ) --> x */
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_1Uto64))
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to1( CmpwNEZ64 ( x )) --> CmpNEZ64(x) */
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpwNEZ64))
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpNEZ64, aa->Iex.Unop.arg );
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_64to32:
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to32( 32Uto64 ( x )) --> x */
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_32Uto64))
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return aa->Iex.Unop.arg;
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64to32( 8Uto64 ( x )) --> 8Uto32(x) */
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_8Uto64))
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_8Uto32, aa->Iex.Unop.arg);
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_32Uto64:
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64( 8Uto32( x )) --> 8Uto64(x) */
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_8Uto32))
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_8Uto64, aa->Iex.Unop.arg);
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64( 16Uto32( x )) --> 16Uto64(x) */
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_16Uto32))
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop(Iop_16Uto64, aa->Iex.Unop.arg);
5246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* 32Uto64(64to32( Shr64( 32Uto64(64to32(x)), sh ))
5247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     --> Shr64( 32Uto64(64to32(x)), sh )) */
5248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (is_Unop(aa, Iop_64to32)
5249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Binop(aa->Iex.Unop.arg, Iop_Shr64)
5250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1, Iop_32Uto64)
5251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg,
5252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Iop_64to32)) {
5253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return aa->Iex.Unop.arg;
5254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /*     32Uto64(64to32( Shl64( 32Uto64(64to32(x)), sh ))
5256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         --> 32Uto64(64to32( Shl64(                x,   sh )) */
5257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (is_Unop(aa, Iop_64to32)
5258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Binop(aa->Iex.Unop.arg, Iop_Shl64)
5259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1, Iop_32Uto64)
5260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg,
5261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Iop_64to32)) {
5262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return
5263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr_Unop(
5264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Iop_32Uto64,
5265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr_Unop(
5266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  Iop_64to32,
5267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRExpr_Binop(
5268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     Iop_Shl64,
5269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg->Iex.Unop.arg,
5270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     aa->Iex.Unop.arg->Iex.Binop.arg2
5271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            )));
5272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iop_1Sto32:
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Sto32( CmpNEZ8( 32to8( 1Uto32( CmpNEZ32( x ))))) -> CmpwNEZ32(x) */
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_Unop(aa, Iop_CmpNEZ8)
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg, Iop_32to8)
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg, Iop_1Uto32)
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg->Iex.Unop.arg,
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_CmpNEZ32)) {
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Unop( Iop_CmpwNEZ32,
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             aa->Iex.Unop.arg->Iex.Unop.arg
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ->Iex.Unop.arg->Iex.Unop.arg);
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no reduction rule applies */
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop( op, aa );
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* atbSubst_Expr ( ATmpInfo* env, IRExpr* e )
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  e2;
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args2;
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         args2 = shallowCopyIRExprVec(e->Iex.CCall.args);
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args2[i]; i++)
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args2[i] = atbSubst_Expr(env,args2[i]);
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_CCall(
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.CCall.cee,
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.CCall.retty,
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   args2
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = atbSubst_Temp(env, e->Iex.RdTmp.tmp);
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e2 ? e2 : e;
5315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
5316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRExpr_ITE(
5317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   atbSubst_Expr(env, e->Iex.ITE.cond),
5318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   atbSubst_Expr(env, e->Iex.ITE.iftrue),
5319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   atbSubst_Expr(env, e->Iex.ITE.iffalse)
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Qop(
5323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Qop.details->op,
5324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg1),
5325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg2),
5326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg3),
5327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Qop.details->arg4)
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Triop(
5331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Triop.details->op,
5332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Triop.details->arg1),
5333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Triop.details->arg2),
5334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   atbSubst_Expr(env, e->Iex.Triop.details->arg3)
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Binop(
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.op,
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Binop.arg1),
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Binop.arg2)
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fold_IRExpr_Unop(
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Unop.op,
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Unop.arg)
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_Load(
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Load.end,
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Load.ty,
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.Load.addr)
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_GetI(
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.descr,
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, e->Iex.GetI.ix),
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.bias
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e;
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("atbSubst_Expr");
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same deal as atbSubst_Expr, except for stmts. */
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty *d, *d2;
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS   *cas, *cas2;
5375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRPutI  *puti, *puti2;
5376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_AbiHint(
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.AbiHint.base),
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.AbiHint.len,
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.AbiHint.nia)
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Store(
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Store.end,
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Store.addr),
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Store.data)
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
5391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
5392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRStmt_StoreG(sg->end,
5393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              atbSubst_Expr(env, sg->addr),
5394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              atbSubst_Expr(env, sg->data),
5395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              atbSubst_Expr(env, sg->guard));
5396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
5398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
5399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return IRStmt_LoadG(lg->end, lg->cvt, lg->dst,
5400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             atbSubst_Expr(env, lg->addr),
5401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             atbSubst_Expr(env, lg->alt),
5402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             atbSubst_Expr(env, lg->guard));
5403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_WrTmp(
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.WrTmp.tmp,
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.WrTmp.data)
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Put(
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Put.offset,
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Put.data)
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
5415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti  = st->Ist.PutI.details;
5416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         puti2 = mkIRPutI(puti->descr,
5417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          atbSubst_Expr(env, puti->ix),
5418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          puti->bias,
5419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          atbSubst_Expr(env, puti->data));
5420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return IRStmt_PutI(puti2);
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Exit(
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.Exit.guard),
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.Exit.jk,
5426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   st->Ist.Exit.dst,
5427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   st->Ist.Exit.offsIP
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
5430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return IRStmt_IMark(st->Ist.IMark.addr,
5431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.len,
5432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             st->Ist.IMark.delta);
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_NoOp();
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_MBE(st->Ist.MBE.event);
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas  = st->Ist.CAS.details;
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas2 = mkIRCAS(
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->oldHi, cas->oldLo, cas->end,
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->addr),
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->expdHi ? atbSubst_Expr(env, cas->expdHi) : NULL,
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->expdLo),
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cas->dataHi ? atbSubst_Expr(env, cas->dataHi) : NULL,
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, cas->dataLo)
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_CAS(cas2);
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_LLSC(
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.end,
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.result,
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   atbSubst_Expr(env, st->Ist.LLSC.addr),
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   st->Ist.LLSC.storedata
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? atbSubst_Expr(env, st->Ist.LLSC.storedata) : NULL
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d  = st->Ist.Dirty.details;
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2 = emptyIRDirty();
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *d2 = *d;
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d2->mFx != Ifx_None)
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d2->mAddr = atbSubst_Expr(env, d2->mAddr);
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d2->guard = atbSubst_Expr(env, d2->guard);
5463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         for (i = 0; d2->args[i]; i++) {
5464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr* arg = d2->args[i];
5465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
5466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               d2->args[i] = atbSubst_Expr(env, arg);
5467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRStmt_Dirty(d2);
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("atbSubst_Stmt");
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovinline
5476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool dirty_helper_stores ( const IRDirty *d )
5477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
5478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return d->mFx == Ifx_Write || d->mFx == Ifx_Modify;
5479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
5480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovinline
5482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Interval dirty_helper_puts ( const IRDirty *d,
5483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    Bool (*preciseMemExnsFn)(Int, Int),
5484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    Bool *requiresPreciseMemExns )
5485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
5486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int i;
5487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Interval interval;
5488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Passing the guest state pointer opens the door to modifying the
5490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      guest state under the covers.  It's not allowed, but let's be
5491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      extra conservative and assume the worst. */
5492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; d->args[i]; i++) {
5493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (UNLIKELY(d->args[i]->tag == Iex_BBPTR)) {
5494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *requiresPreciseMemExns = True;
5495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Assume all guest state is written. */
5496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         interval.present = True;
5497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         interval.low  = 0;
5498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         interval.high = 0x7FFFFFFF;
5499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return interval;
5500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
5502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Check the side effects on the guest state */
5504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   interval.present = False;
5505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   interval.low = interval.high = -1;
5506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   *requiresPreciseMemExns = False;
5507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; i < d->nFxState; ++i) {
5509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (d->fxState[i].fx != Ifx_Read) {
5510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int offset = d->fxState[i].offset;
5511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int size = d->fxState[i].size;
5512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int nRepeats = d->fxState[i].nRepeats;
5513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int repeatLen = d->fxState[i].repeatLen;
5514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (preciseMemExnsFn(offset,
5516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              offset + nRepeats * repeatLen + size - 1)) {
5517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *requiresPreciseMemExns = True;
5518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
5519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         update_interval(&interval, offset,
5520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         offset + nRepeats * repeatLen + size - 1);
5521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
5523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return interval;
5525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
5526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Return an interval if st modifies the guest state. Via requiresPreciseMemExns
5528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return whether or not that modification requires precise exceptions. */
5529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Interval stmt_modifies_guest_state ( IRSB *bb, const IRStmt *st,
5530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                            Bool (*preciseMemExnsFn)(Int,Int),
5531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                            Bool *requiresPreciseMemExns )
5532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
5533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Interval interval;
5534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (st->tag) {
5536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Ist_Put: {
5537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int offset = st->Ist.Put.offset;
5538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int size = sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Put.data));
5539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      *requiresPreciseMemExns = preciseMemExnsFn(offset, offset + size - 1);
5541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.present = True;
5542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.low  = offset;
5543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.high = offset + size - 1;
5544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return interval;
5545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
5546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Ist_PutI: {
5548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRRegArray *descr = st->Ist.PutI.details->descr;
5549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int offset = descr->base;
5550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int size = sizeofIRType(descr->elemTy);
5551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* We quietly assume here that all segments are contiguous and there
5553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         are no holes. This is to avoid a loop. The assumption is conservative
5554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         in the sense that we might report that precise memory exceptions are
5555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         needed when in fact they are not. */
5556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      *requiresPreciseMemExns =
5557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         preciseMemExnsFn(offset, offset + descr->nElems * size - 1);
5558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.present = True;
5559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.low  = offset;
5560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.high = offset + descr->nElems * size - 1;
5561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return interval;
5562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
5563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Ist_Dirty:
5565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return dirty_helper_puts(st->Ist.Dirty.details, preciseMemExnsFn,
5566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                               requiresPreciseMemExns);
5567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   default:
5569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      *requiresPreciseMemExns = False;
5570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.present = False;
5571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.low  = -1;
5572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      interval.high = -1;
5573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return interval;
5574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
5575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
5576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* notstatic */ Addr64 ado_treebuild_BB ( IRSB* bb,
5578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          Bool (*preciseMemExnsFn)(Int,Int) )
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j, k, m;
5581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Bool     stmtStores, invalidateMe;
5582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Interval putInterval;
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st2;
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ATmpInfo env[A_NENV];
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool   max_ga_known = False;
5588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Addr64 max_ga       = 0;
5589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       n_tmps = bb->tyenv->types_used;
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort*   uses   = LibVEX_Alloc(n_tmps * sizeof(UShort));
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Phase 1.  Scan forwards in bb, counting use occurrences of each
5594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      temp.  Also count occurrences in the bb->next field.  Take the
5595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      opportunity to also find the maximum guest address in the block,
5596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      since that will be needed later for deciding when we can safely
5597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      elide event checks. */
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++)
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uses[i] = 0;
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
5604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (st->tag) {
5605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ist_NoOp:
5606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
5607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ist_IMark: {
5608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int    len = st->Ist.IMark.len;
5609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Addr64 mga = st->Ist.IMark.addr + (len < 1 ? 1 : len) - 1;
5610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            max_ga_known = True;
5611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (mga > max_ga)
5612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               max_ga = mga;
5613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
5614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
5616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
5617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aoccCount_Stmt( uses, st );
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   aoccCount_Expr(uses, bb->next );
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_tmps; i++) {
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uses[i] == 0)
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        continue;
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRTemp( (IRTemp)i );
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("  used %d\n", (Int)uses[i] );
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Phase 2.  Scan forwards in bb.  For each statement in turn:
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         If the env is full, emit the end element.  This guarantees
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         there is at least one free slot in the following.
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         On seeing 't = E', occ(t)==1,
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let E'=env(E)
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete this stmt
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add t -> E' to the front of the env
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Examine E' and set the hints for E' appropriately
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (doesLoad? doesGet?)
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         On seeing any other stmt,
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let stmt' = env(stmt)
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove from env any 't=E' binds invalidated by stmt
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                emit the invalidated stmts
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit stmt'
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compact any holes in env
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              by sliding entries towards the front
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Finally, apply env to bb->next.
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < A_NENV; i++) {
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i].bindee = NULL;
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env[i].binder = IRTemp_INVALID;
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The stmts in bb are being reordered, and we are guaranteed to
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      end up with no more than the number we started with.  Use i to
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be the cursor of the current stmt examined and j <= i to be that
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for the current stmt being written.
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_NoOp)
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ensure there's at least one space in the env, by emitting
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the oldest binding if necessary. */
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (env[A_NENV-1].bindee != NULL) {
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb->stmts[j] = IRStmt_WrTmp( env[A_NENV-1].binder,
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      env[A_NENV-1].bindee );
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j++;
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(j <= i);
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[A_NENV-1].bindee = NULL;
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Consider current stmt. */
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag == Ist_WrTmp && uses[st->Ist.WrTmp.tmp] <= 1) {
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr *e, *e2;
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* optional extra: dump dead bindings as we find them.
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Removes the need for a prior dead-code removal pass. */
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (uses[st->Ist.WrTmp.tmp] == 0) {
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (0) vex_printf("DEAD binding\n");
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(uses[st->Ist.WrTmp.tmp] == 1);
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ok, we have 't = E', occ(t)==1.  Do the abovementioned
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            actions. */
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e  = st->Ist.WrTmp.data;
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e2 = atbSubst_Expr(env, e);
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addToEnvFront(env, st->Ist.WrTmp.tmp, e2);
5698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         setHints_Expr(&env[0].doesLoad, &env[0].getInterval, e2);
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* don't advance j, as we are deleting this stmt and instead
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            holding it temporarily in the env. */
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we get here for any other kind of statement. */
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 'use up' any bindings required by the current statement. */
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st2 = atbSubst_Stmt(env, st);
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, before this stmt, dump any bindings in env that it
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidates.  These need to be dumped in the order in which
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         they originally entered env -- that means from oldest to
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         youngest. */
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* putInterval/stmtStores characterise what the stmt under
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consideration does, or might do (sidely safe @ True). */
5715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool putRequiresPreciseMemExns;
5717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      putInterval = stmt_modifies_guest_state( bb, st, preciseMemExnsFn,
5718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                               &putRequiresPreciseMemExns);
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be True if this stmt writes memory or might do (==> we don't
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         want to reorder other loads or stores relative to it).  Also,
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         both LL and SC fall under this classification, since we
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         really ought to be conservative and not reorder any other
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memory transactions relative to them. */
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmtStores
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toBool( st->tag == Ist_Store
5727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   || (st->tag == Ist_Dirty
5728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       && dirty_helper_stores(st->Ist.Dirty.details))
5729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || st->tag == Ist_LLSC
5730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || st->tag == Ist_CAS );
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = A_NENV-1; k >= 0; k--) {
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[k].bindee == NULL)
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compare the actions of this stmt with the actions of
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binding 'k', to see if they invalidate the binding. */
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         invalidateMe
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = toBool(
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* a store invalidates loaded data */
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (env[k].doesLoad && stmtStores)
5741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              /* a put invalidates get'd data, if they overlap */
5742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              || ((env[k].getInterval.present && putInterval.present) &&
5743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  intervals_overlap(env[k].getInterval, putInterval))
5744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              /* a put invalidates loaded data. That means, in essense, that
5745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 a load expression cannot be substituted into a statement
5746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 that follows the put. But there is nothing wrong doing so
5747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 except when the put statement requries precise exceptions.
5748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 Think of a load that is moved past a put where the put
5749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 updates the IP in the guest state. If the load generates
5750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 a segfault, the wrong address (line number) would be
5751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 reported. */
5752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              || (env[k].doesLoad && putInterval.present &&
5753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  putRequiresPreciseMemExns)
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* probably overly conservative: a memory bus event
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 invalidates absolutely everything, so that all
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 computation prior to it is forced to complete before
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 proceeding with the event (fence,lock,unlock). */
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || st->tag == Ist_MBE
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* also be (probably overly) paranoid re AbiHints */
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || st->tag == Ist_AbiHint
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (invalidateMe) {
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb->stmts[j] = IRStmt_WrTmp( env[k].binder, env[k].bindee );
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            j++;
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(j <= i);
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env[k].bindee = NULL;
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Slide in-use entries in env up to the front */
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      m = 0;
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = 0; k < A_NENV; k++) {
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (env[k].bindee != NULL) {
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            env[m] = env[k];
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            m++;
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (m = m; m < A_NENV; m++) {
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         env[m].bindee = NULL;
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* finally, emit the substituted statement */
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb->stmts[j] = st2;
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vex_printf("**2  "); ppIRStmt(bb->stmts[j]); vex_printf("\n"); */
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      j++;
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(j <= i+1);
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* for each stmt in the original bb ... */
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally ... substitute the ->next field as much as possible, and
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dump any left-over bindings.  Hmm.  Perhaps there should be no
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      left over bindings?  Or any left-over bindings are
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by definition dead? */
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->next = atbSubst_Expr(env, bb->next);
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->stmts_used = j;
5796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return max_ga_known ? max_ga : ~(Addr64)0;
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- iropt main                                              ---*/
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool iropt_verbose = False; /* True; */
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a simple cleanup pass on bb.  This is: redundant Get removal,
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant Put removal, constant propagation, dead code removal,
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clean helper specialisation, and dead code removal (again).
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cheap_transformations (
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb,
5817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool (*preciseMemExnsFn)(Int,Int)
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   redundant_get_removal_BB ( bb );
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= REDUNDANT GET\n\n" );
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) {
5828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      redundant_put_removal_BB ( bb, preciseMemExnsFn );
5829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= REDUNDANT PUT\n\n" );
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = cprop_BB ( bb );
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= CPROPD\n\n" );
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB ( bb );
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= DEAD\n\n" );
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = spec_helpers_BB ( bb, specHelper );
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB ( bb );
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= SPECd \n\n" );
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do some more expensive transformations on bb, which are aimed at
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimising as much as possible in the presence of GetI and PutI.  */
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* expensive_transformations( IRSB* bb )
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (void)do_cse_BB( bb );
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   collapse_AddSub_chains_BB( bb );
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_redundant_GetI_elimination( bb );
5867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) {
5868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_redundant_PutI_elimination( bb );
5869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_deadcode_BB( bb );
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan a flattened BB to look for signs that more expensive
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisations might be useful:
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - find out if there are any GetIs and PutIs
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - find out if there are any floating or vector-typed temporaries
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void considerExpensives ( /*OUT*/Bool* hasGetIorPutI,
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/Bool* hasVorFtemps,
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRSB* bb )
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j;
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *hasGetIorPutI = False;
5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *hasVorFtemps  = False;
5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++) {
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = bb->stmts[i];
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_AbiHint:
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.AbiHint.base));
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.AbiHint.nia));
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *hasGetIorPutI = True;
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp:
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.WrTmp.data->tag == Iex_GetI)
5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *hasGetIorPutI = True;
5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp)) {
5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I1: case Ity_I8: case Ity_I16:
5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I32: case Ity_I64: case Ity_I128:
5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
5910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Ity_F32: case Ity_F64: case Ity_F128:
5911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Ity_V128: case Ity_V256:
5912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  *hasVorFtemps = True;
5913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
5914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Ity_D32: case Ity_D64: case Ity_D128:
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *hasVorFtemps = True;
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  goto bad;
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Put.data));
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Store:
5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Store.addr));
5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Store.data));
5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_StoreG: {
5929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRStoreG* sg = st->Ist.StoreG.details;
5930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(isIRAtom(sg->addr));
5931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(isIRAtom(sg->data));
5932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(isIRAtom(sg->guard));
5933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
5934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
5935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_LoadG: {
5936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRLoadG* lg = st->Ist.LoadG.details;
5937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(isIRAtom(lg->addr));
5938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(isIRAtom(lg->alt));
5939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(isIRAtom(lg->guard));
5940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
5941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS:
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cas = st->Ist.CAS.details;
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->addr));
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->expdLo));
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(cas->dataLo));
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC:
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.LLSC.addr));
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.LLSC.storedata)
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(st->Ist.LLSC.storedata));
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty:
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d = st->Ist.Dirty.details;
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(d->guard));
5958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            for (j = 0; d->args[j]; j++) {
5959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               IRExpr* arg = d->args[j];
5960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
5961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(isIRAtom(arg));
5962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->mFx != Ifx_None)
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(isIRAtom(d->mAddr));
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp:
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_IMark:
5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_MBE:
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Exit:
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(isIRAtom(st->Ist.Exit.guard));
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bad:
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("considerExpensives");
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- The main iropt entry point. ---------------- */
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* exported from this file */
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Rules of the game:
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - IRExpr/IRStmt trees should be treated as immutable, as they
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     may get shared.  So never change a field of such a tree node;
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     instead construct and return a new one if needed.
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* do_iropt_BB(
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB* bb0,
5995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool (*preciseMemExnsFn)(Int,Int),
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr64 guest_addr,
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VexArch guest_arch
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_total     = 0;
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_expensive = 0;
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool hasGetIorPutI, hasVorFtemps;
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB *bb, *bb2;
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_total++;
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First flatten the block out, since all other
6010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      phases assume flat code. */
6011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = flatten_BB ( bb0 );
6013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iropt_verbose) {
6015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n========= FLAT\n\n" );
6016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRSB(bb);
6017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If at level 0, stop now. */
6020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_level <= 0) return bb;
6021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now do a preliminary cleanup pass, and figure out if we also
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need to do 'expensive' optimisations.  Expensive optimisations
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are deemed necessary if the block contains any GetIs or PutIs.
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If needed, do expensive transformations and then another cheap
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cleanup pass. */
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guest_arch == VexArchARM) {
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Translating Thumb2 code produces a lot of chaff.  We have to
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         work extra hard to get rid of it. */
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = cprop_BB(bb);
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb = spec_helpers_BB ( bb, specHelper );
6035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) {
6036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         redundant_put_removal_BB ( bb, preciseMemExnsFn );
6037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
6038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      do_cse_BB( bb );
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_deadcode_BB( bb );
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_control.iropt_level > 1) {
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Peer at what we have, to decide how much more effort to throw
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at it. */
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      considerExpensives( &hasGetIorPutI, &hasVorFtemps, bb );
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (hasVorFtemps && !hasGetIorPutI) {
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If any evidence of FP or Vector activity, CSE, as that
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tends to mop up all manner of lardy code to do with
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rounding modes.  Don't bother if hasGetIorPutI since that
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case leads into the expensive transformations, which do
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CSE anyway. */
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (void)do_cse_BB( bb );
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_deadcode_BB( bb );
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (hasGetIorPutI) {
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool cses;
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_expensive++;
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (DEBUG_IROPT)
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive);
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = expensive_transformations( bb );
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Potentially common up GetIs */
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cses = do_cse_BB( bb );
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cses)
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now have a go at unrolling simple (single-BB) loops.  If
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         successful, clean up the results as much as possible. */
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bb2 = maybe_loop_unroll_BB( bb, guest_addr );
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb2) {
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn );
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (hasGetIorPutI) {
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = expensive_transformations( bb );
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* at least do CSE and dead code removal */
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_cse_BB( bb );
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_deadcode_BB( bb );
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) vex_printf("vex iropt: unrolled a loop\n");
6086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                            ir_opt.c ---*/
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
6097