1f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian/* -*- mode: C; c-basic-offset: 3; -*- */
2a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
3a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*---------------------------------------------------------------*/
4752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                                          ir_opt.c ---*/
5a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*---------------------------------------------------------------*/
6a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
7f8ed9d874a7b8651654591c68c6d431c758d787csewardj/*
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
9752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
10f8ed9d874a7b8651654591c68c6d431c758d787csewardj
11ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2004-2017 OpenWorks LLP
12752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
137bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
17752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
187bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
26752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
287bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
29752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
30f8ed9d874a7b8651654591c68c6d431c758d787csewardj
31f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Neither the names of the U.S. Department of Energy nor the
32f8ed9d874a7b8651654591c68c6d431c758d787csewardj   University of California nor the names of its contributors may be
33f8ed9d874a7b8651654591c68c6d431c758d787csewardj   used to endorse or promote products derived from this software
34f8ed9d874a7b8651654591c68c6d431c758d787csewardj   without prior written permission.
35f8ed9d874a7b8651654591c68c6d431c758d787csewardj*/
36f8ed9d874a7b8651654591c68c6d431c758d787csewardj
37a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj#include "libvex_basictypes.h"
38edf4d69c8477cad95851d0f6ccf91ab323e5a446sewardj#include "libvex_ir.h"
39a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj#include "libvex.h"
40a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
41cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
42cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_globals.h"
43cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "ir_opt.h"
44a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
45d0863fff7ceb51db619fea835df0dc9c0ac7cd5bsewardj
46088bcb4521e94c60c1d8a4dd46151e0cd2e06475sewardj/* Set to 1 for lots of debugging output. */
47088bcb4521e94c60c1d8a4dd46151e0cd2e06475sewardj#define DEBUG_IROPT 0
48088bcb4521e94c60c1d8a4dd46151e0cd2e06475sewardj
49cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Set to 1 to gather some statistics. Currently only for sameIRExprs. */
50cdb5feebd7e817c8207471ef734b43c51c14dee3florian#define STATS_IROPT 0
51cdb5feebd7e817c8207471ef734b43c51c14dee3florian
52a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* What iropt does, 29 Dec 04.
540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
55f6c8ebf1294fea43756683ba7089b746168abb8esewardj   It takes an IRSB and produces a new one with the same meaning,
560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   defined thus:
570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   After execution of the new BB, all guest state and guest memory is
590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   the same as after execution of the original.  This is true
600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   regardless of how the block was exited (at the end vs side exit).
610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   In addition, parts of the guest state will be identical to that
630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   created by execution of the original at the following observation
640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   points:
650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   * In a dirty helper call, any parts of the guest state that the
670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     helper states that it reads or modifies will be up to date.
680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     Also, guest memory will be up to date.  Parts of the guest state
690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     not marked as being read or modified by the helper cannot be
700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     assumed to be up-to-date at the point where the helper is called.
710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
726c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   * If iropt_register_updates == VexRegUpdSpAtMemAccess :
736c46befd9eb90c1b6e739926c1fa335cba75bf46philippe     The guest state is only up to date only as explained above
746c46befd9eb90c1b6e739926c1fa335cba75bf46philippe     (i.e. at SB exits and as specified by dirty helper call).
756c46befd9eb90c1b6e739926c1fa335cba75bf46philippe     Also, the stack pointer register is up to date at memory
766c46befd9eb90c1b6e739926c1fa335cba75bf46philippe     exception points (as this is needed for the stack extension
776c46befd9eb90c1b6e739926c1fa335cba75bf46philippe     logic in m_signals.c).
786c46befd9eb90c1b6e739926c1fa335cba75bf46philippe
79c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe   * If iropt_register_updates == VexRegUpdUnwindregsAtMemAccess :
80c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe     Immediately prior to any load or store, those parts of the guest
810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     state marked as requiring precise exceptions will be up to date.
820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     Also, guest memory will be up to date.  Parts of the guest state
830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     not marked as requiring precise exceptions cannot be assumed to
840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     be up-to-date at the point of the load/store.
850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
866c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   * If iropt_register_updates == VexRegUpdAllregsAtMemAccess:
87c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe     Same as minimal, but all the guest state is up to date at memory
88c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe     exception points.
89c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe
906c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   * If iropt_register_updates == VexRegUpdAllregsAtEachInsn :
91c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe     Guest state is up to date at each instruction.
92c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe
930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   The relative order of loads and stores (including loads/stores of
940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   guest memory done by dirty helpers annotated as such) is not
950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   changed.  However, the relative order of loads with no intervening
960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   stores/modifies may be changed.
970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Transformation order
990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   ~~~~~~~~~~~~~~~~~~~~
1000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   There are three levels of optimisation, controlled by
1020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vex_control.iropt_level.  Define first:
1030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   "Cheap transformations" are the following sequence:
1050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Redundant-Get removal
1060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Redundant-Put removal
1070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Constant propagation/folding
1080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Dead code removal
1090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Specialisation of clean helper functions
1100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Dead code removal
1110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   "Expensive transformations" are the following sequence:
1130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * CSE
1140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Folding of add/sub chains
1150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Redundant-GetI removal
1160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Redundant-PutI removal
1170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Dead code removal
1180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Then the transformations are as follows, as defined by
1200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vex_control.iropt_level:
1210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Level 0:
1230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Flatten into atomic form.
1240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Level 1: the following sequence:
1260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Flatten into atomic form.
1270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Cheap transformations.
1280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
1290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Level 2: the following sequence
1300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Flatten into atomic form.
1310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Cheap transformations.
132b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      * If block contains any floating or vector types, CSE.
1330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * If block contains GetI or PutI, Expensive transformations.
1340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      * Try unrolling loops.  Three possible outcomes:
1350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        - No effect: do nothing more.
1360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        - Unrolled a loop, and block does not contain GetI or PutI:
1370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          Do: * CSE
1380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj              * Dead code removal
1390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        - Unrolled a loop, and block contains GetI or PutI:
1400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          Do: * Expensive transformations
1410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj              * Cheap transformations
1420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj*/
1430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
14498430295cf4900160346bfdeea2833bd024b0117sewardj/* Implementation notes, 29 Dec 04.
14598430295cf4900160346bfdeea2833bd024b0117sewardj
14698430295cf4900160346bfdeea2833bd024b0117sewardj   TODO (important): I think rPutI removal ignores precise exceptions
14798430295cf4900160346bfdeea2833bd024b0117sewardj   and is therefore in a sense, wrong.  In the sense that PutIs are
14898430295cf4900160346bfdeea2833bd024b0117sewardj   assumed not to write parts of the guest state that we need to have
14998430295cf4900160346bfdeea2833bd024b0117sewardj   up-to-date at loads/stores.  So far on x86 guest that has not
15098430295cf4900160346bfdeea2833bd024b0117sewardj   mattered since indeed only the x87 FP registers and tags are
15198430295cf4900160346bfdeea2833bd024b0117sewardj   accessed using GetI/PutI, and there is no need so far for them to
15298430295cf4900160346bfdeea2833bd024b0117sewardj   be up to date at mem exception points.  The rPutI pass should be
15398430295cf4900160346bfdeea2833bd024b0117sewardj   fixed.
154fb44d55a331b6e97d7ba7b18969efec939420707sewardj
1554c5f6d54fa43a98e29a50af85c92720ee61e33c1sewardj   TODO: improve pessimistic handling of precise exceptions
1564c5f6d54fa43a98e29a50af85c92720ee61e33c1sewardj     in the tree builder.
1574c5f6d54fa43a98e29a50af85c92720ee61e33c1sewardj
158fb44d55a331b6e97d7ba7b18969efec939420707sewardj   TODO: check interaction of rGetI and dirty helpers.
159c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj
160c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj   F64i constants are treated differently from other constants.
161c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj   They are not regarded as atoms, and instead lifted off and
162c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj   bound to temps.  This allows them to participate in CSE, which
163c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj   is important for getting good performance for x86 guest code.
164695cff9303ef5dc8079117acfd632b44edb1f010sewardj
165a5aa9cf3566d1842730cdcbc62a47a344c2944absewardj   CSE up F64 literals (already doing F64is)
1664c5f6d54fa43a98e29a50af85c92720ee61e33c1sewardj
1674c5f6d54fa43a98e29a50af85c92720ee61e33c1sewardj   CSE: consider carefully the requirement for precise exns
16898430295cf4900160346bfdeea2833bd024b0117sewardj        prior to making CSE any more aggressive.  */
169c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj
170c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj
171a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*---------------------------------------------------------------*/
172a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*--- Finite mappery, of a sort                               ---*/
173a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*---------------------------------------------------------------*/
174a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
1750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* General map from HWord-sized thing HWord-sized thing.  Could be by
1760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   hashing, but it's not clear whether or not this would really be any
1770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   faster. */
178a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
179a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardjtypedef
180a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   struct {
181a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      Bool*  inuse;
182ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardj      HWord* key;
183ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardj      HWord* val;
184a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      Int    size;
185a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      Int    used;
186a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   }
187ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardj   HashHW;
188a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
189ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardjstatic HashHW* newHHW ( void )
190a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj{
191d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   HashHW* h = LibVEX_Alloc_inline(sizeof(HashHW));
1922963239357452b96dbe6de1b3f8b626ea3305780sewardj   h->size   = 8;
193a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   h->used   = 0;
194d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   h->inuse  = LibVEX_Alloc_inline(h->size * sizeof(Bool));
195d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   h->key    = LibVEX_Alloc_inline(h->size * sizeof(HWord));
196d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   h->val    = LibVEX_Alloc_inline(h->size * sizeof(HWord));
197a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   return h;
198a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj}
199a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
200a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
20184be73746586afb2ea1f197907fd7271c8d1e2ffsewardj/* Look up key in the map. */
202a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
203ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardjstatic Bool lookupHHW ( HashHW* h, /*OUT*/HWord* val, HWord key )
204a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj{
205a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   Int i;
2060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* vex_printf("lookupHHW(%llx)\n", key ); */
207a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   for (i = 0; i < h->used; i++) {
208a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      if (h->inuse[i] && h->key[i] == key) {
20939e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj         if (val)
21039e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj            *val = h->val[i];
211a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         return True;
212a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      }
213a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   }
214a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   return False;
215a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj}
216a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
217a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
218a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/* Add key->val to the map.  Replaces any existing binding for key. */
219a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
220ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardjstatic void addToHHW ( HashHW* h, HWord key, HWord val )
221a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj{
222a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   Int i, j;
2230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* vex_printf("addToHHW(%llx, %llx)\n", key, val); */
224a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
225a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   /* Find and replace existing binding, if any. */
226a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   for (i = 0; i < h->used; i++) {
227a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      if (h->inuse[i] && h->key[i] == key) {
228a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         h->val[i] = val;
229a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         return;
230a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      }
231a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   }
232a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
233a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   /* Ensure a space is available. */
234a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   if (h->used == h->size) {
235a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      /* Copy into arrays twice the size. */
236d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian      Bool*  inuse2 = LibVEX_Alloc_inline(2 * h->size * sizeof(Bool));
237d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian      HWord* key2   = LibVEX_Alloc_inline(2 * h->size * sizeof(HWord));
238d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian      HWord* val2   = LibVEX_Alloc_inline(2 * h->size * sizeof(HWord));
239a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      for (i = j = 0; i < h->size; i++) {
240a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         if (!h->inuse[i]) continue;
241a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         inuse2[j] = True;
242a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         key2[j] = h->key[i];
243a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         val2[j] = h->val[i];
244a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj         j++;
245a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      }
246a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      h->used = j;
247a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      h->size *= 2;
248a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      h->inuse = inuse2;
249a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      h->key = key2;
250a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj      h->val = val2;
251a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   }
252a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
253a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   /* Finally, add it. */
254a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   vassert(h->used < h->size);
255a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   h->inuse[h->used] = True;
256a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   h->key[h->used] = key;
25784be73746586afb2ea1f197907fd7271c8d1e2ffsewardj   h->val[h->used] = val;
258a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj   h->used++;
259a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj}
260a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj
26184be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
262d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj/*---------------------------------------------------------------*/
2630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Flattening out a BB into atomic SSA form                ---*/
264d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj/*---------------------------------------------------------------*/
265d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
266e80679ab932e23632e2143788217e02e2a59959fsewardj/* Non-critical helper, heuristic for reducing the number of tmp-tmp
267e80679ab932e23632e2143788217e02e2a59959fsewardj   copies made by flattening.  If in doubt return False. */
268e80679ab932e23632e2143788217e02e2a59959fsewardj
269e80679ab932e23632e2143788217e02e2a59959fsewardjstatic Bool isFlat ( IRExpr* e )
270e80679ab932e23632e2143788217e02e2a59959fsewardj{
271695cff9303ef5dc8079117acfd632b44edb1f010sewardj   if (e->tag == Iex_Get)
272695cff9303ef5dc8079117acfd632b44edb1f010sewardj      return True;
273e80679ab932e23632e2143788217e02e2a59959fsewardj   if (e->tag == Iex_Binop)
274496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj      return toBool( isIRAtom(e->Iex.Binop.arg1)
275496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj                     && isIRAtom(e->Iex.Binop.arg2) );
276af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj   if (e->tag == Iex_Load)
277af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      return isIRAtom(e->Iex.Load.addr);
278e80679ab932e23632e2143788217e02e2a59959fsewardj   return False;
279e80679ab932e23632e2143788217e02e2a59959fsewardj}
280e80679ab932e23632e2143788217e02e2a59959fsewardj
281d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj/* Flatten out 'ex' so it is atomic, returning a new expression with
282d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   the same value, after having appended extra IRTemp assignments to
283d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   the end of 'bb'. */
284d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
285dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic IRExpr* flatten_Expr ( IRSB* bb, IRExpr* ex )
286d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj{
287d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   Int i;
288d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   IRExpr** newargs;
289d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   IRType ty = typeOfIRExpr(bb->tyenv, ex);
290d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   IRTemp t1;
291d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
292d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   switch (ex->tag) {
293d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
294d721703a7a904a66c49d0e6318c184d0076b40b0sewardj      case Iex_GetI:
295d721703a7a904a66c49d0e6318c184d0076b40b0sewardj         t1 = newIRTemp(bb->tyenv, ty);
296dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
2972d3f77c12d2911173fd182d0b6e954196dee9135sewardj            IRExpr_GetI(ex->Iex.GetI.descr,
298eeac841fbfcadbc19e97c7ef56bfa3354ba78637sewardj                        flatten_Expr(bb, ex->Iex.GetI.ix),
2992d3f77c12d2911173fd182d0b6e954196dee9135sewardj                        ex->Iex.GetI.bias)));
300dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
301d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
302d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Iex_Get:
303d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         t1 = newIRTemp(bb->tyenv, ty);
304dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb,
305dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            IRStmt_WrTmp(t1, ex));
306dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
307d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
30896d7cc3e7d54ad5af2af2821223b21f9a8516a59florian      case Iex_Qop: {
30996d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         IRQop* qop = ex->Iex.Qop.details;
31040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         t1 = newIRTemp(bb->tyenv, ty);
311dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
31296d7cc3e7d54ad5af2af2821223b21f9a8516a59florian            IRExpr_Qop(qop->op,
31396d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                         flatten_Expr(bb, qop->arg1),
31496d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                         flatten_Expr(bb, qop->arg2),
31596d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                         flatten_Expr(bb, qop->arg3),
31696d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                         flatten_Expr(bb, qop->arg4))));
317dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
31896d7cc3e7d54ad5af2af2821223b21f9a8516a59florian      }
31940c802659108a96bb87cbc1a30b7b77e2abd0829sewardj
320420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian      case Iex_Triop: {
321420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         IRTriop* triop = ex->Iex.Triop.details;
322b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         t1 = newIRTemp(bb->tyenv, ty);
323dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
324420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian            IRExpr_Triop(triop->op,
325420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                         flatten_Expr(bb, triop->arg1),
326420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                         flatten_Expr(bb, triop->arg2),
327420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                         flatten_Expr(bb, triop->arg3))));
328dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
329420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian      }
330b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
331d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Iex_Binop:
332d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         t1 = newIRTemp(bb->tyenv, ty);
333dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
334d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj            IRExpr_Binop(ex->Iex.Binop.op,
335d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj                         flatten_Expr(bb, ex->Iex.Binop.arg1),
336d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj                         flatten_Expr(bb, ex->Iex.Binop.arg2))));
337dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
338d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
339d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Iex_Unop:
340d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         t1 = newIRTemp(bb->tyenv, ty);
341dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
342d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj            IRExpr_Unop(ex->Iex.Unop.op,
343d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj                        flatten_Expr(bb, ex->Iex.Unop.arg))));
344dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
345d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
346af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Iex_Load:
347d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         t1 = newIRTemp(bb->tyenv, ty);
348dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
349e768e92e054cde495849a5c842a477d287677f78sewardj            IRExpr_Load(ex->Iex.Load.end,
350af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                        ex->Iex.Load.ty,
351af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                        flatten_Expr(bb, ex->Iex.Load.addr))));
352dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
353d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
354d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Iex_CCall:
355dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         newargs = shallowCopyIRExprVec(ex->Iex.CCall.args);
356d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         for (i = 0; newargs[i]; i++)
357d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj            newargs[i] = flatten_Expr(bb, newargs[i]);
358d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         t1 = newIRTemp(bb->tyenv, ty);
359dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
3608ea867b06de73d909c29e243407713c291c8414esewardj            IRExpr_CCall(ex->Iex.CCall.cee,
361d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj                         ex->Iex.CCall.retty,
362d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj                         newargs)));
363dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
364d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
36599dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
366d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         t1 = newIRTemp(bb->tyenv, ty);
367dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_WrTmp(t1,
36899dd03e04a6914d90d5fee727d61d76905334becflorian            IRExpr_ITE(flatten_Expr(bb, ex->Iex.ITE.cond),
36999dd03e04a6914d90d5fee727d61d76905334becflorian                       flatten_Expr(bb, ex->Iex.ITE.iftrue),
37099dd03e04a6914d90d5fee727d61d76905334becflorian                       flatten_Expr(bb, ex->Iex.ITE.iffalse))));
371dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_RdTmp(t1);
372d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
373d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Iex_Const:
374c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj         /* Lift F64i constants out onto temps so they can be CSEd
375c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj            later. */
376c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj         if (ex->Iex.Const.con->tag == Ico_F64i) {
377c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj            t1 = newIRTemp(bb->tyenv, ty);
378dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            addStmtToIRSB(bb, IRStmt_WrTmp(t1,
379c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj               IRExpr_Const(ex->Iex.Const.con)));
380dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            return IRExpr_RdTmp(t1);
381c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj         } else {
382c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj            /* Leave all other constants alone. */
383c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj            return ex;
384c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj         }
385c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj
386dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp:
387d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         return ex;
388d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
389d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      default:
390d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         vex_printf("\n");
391d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         ppIRExpr(ex);
392d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         vex_printf("\n");
393d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         vpanic("flatten_Expr");
394d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   }
395d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj}
396d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
397d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
398d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj/* Append a completely flattened form of 'st' to the end of 'bb'. */
399d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
400dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic void flatten_Stmt ( IRSB* bb, IRStmt* st )
401d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj{
40217442fe8094d0f82266e5a05509f62cac8f7539esewardj   Int i;
403cfe046e178666280b87da998b1b52ecda03ecd89sewardj   IRExpr   *e1, *e2, *e3, *e4, *e5;
404cfe046e178666280b87da998b1b52ecda03ecd89sewardj   IRDirty  *d,  *d2;
405cfe046e178666280b87da998b1b52ecda03ecd89sewardj   IRCAS    *cas, *cas2;
406cfe046e178666280b87da998b1b52ecda03ecd89sewardj   IRPutI   *puti, *puti2;
407cfe046e178666280b87da998b1b52ecda03ecd89sewardj   IRLoadG  *lg;
408cfe046e178666280b87da998b1b52ecda03ecd89sewardj   IRStoreG *sg;
409d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   switch (st->tag) {
410d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Ist_Put:
411496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         if (isIRAtom(st->Ist.Put.data)) {
41249651f4b59b1ab7e0e70cccd34001630eafbe957sewardj            /* optimisation to reduce the amount of heap wasted
41349651f4b59b1ab7e0e70cccd34001630eafbe957sewardj               by the flattener */
414dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            addStmtToIRSB(bb, st);
41549651f4b59b1ab7e0e70cccd34001630eafbe957sewardj         } else {
41649651f4b59b1ab7e0e70cccd34001630eafbe957sewardj            /* general case, always correct */
41749651f4b59b1ab7e0e70cccd34001630eafbe957sewardj            e1 = flatten_Expr(bb, st->Ist.Put.data);
418dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            addStmtToIRSB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
41949651f4b59b1ab7e0e70cccd34001630eafbe957sewardj         }
420d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         break;
421d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Ist_PutI:
422d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         puti = st->Ist.PutI.details;
423d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         e1 = flatten_Expr(bb, puti->ix);
424d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         e2 = flatten_Expr(bb, puti->data);
425d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         puti2 = mkIRPutI(puti->descr, e1, puti->bias, e2);
426d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         addStmtToIRSB(bb, IRStmt_PutI(puti2));
427d721703a7a904a66c49d0e6318c184d0076b40b0sewardj         break;
428dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
429dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (isFlat(st->Ist.WrTmp.data)) {
430e80679ab932e23632e2143788217e02e2a59959fsewardj            /* optimisation, to reduce the number of tmp-tmp
431e80679ab932e23632e2143788217e02e2a59959fsewardj               copies generated */
432dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            addStmtToIRSB(bb, st);
433e80679ab932e23632e2143788217e02e2a59959fsewardj         } else {
434e80679ab932e23632e2143788217e02e2a59959fsewardj            /* general case, always correct */
435dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            e1 = flatten_Expr(bb, st->Ist.WrTmp.data);
436dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            addStmtToIRSB(bb, IRStmt_WrTmp(st->Ist.WrTmp.tmp, e1));
437e80679ab932e23632e2143788217e02e2a59959fsewardj         }
438d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         break;
439af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
440af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         e1 = flatten_Expr(bb, st->Ist.Store.addr);
441af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         e2 = flatten_Expr(bb, st->Ist.Store.data);
442e768e92e054cde495849a5c842a477d287677f78sewardj         addStmtToIRSB(bb, IRStmt_Store(st->Ist.Store.end, e1,e2));
443e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
444cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG:
445cfe046e178666280b87da998b1b52ecda03ecd89sewardj         sg = st->Ist.StoreG.details;
446cfe046e178666280b87da998b1b52ecda03ecd89sewardj         e1 = flatten_Expr(bb, sg->addr);
447cfe046e178666280b87da998b1b52ecda03ecd89sewardj         e2 = flatten_Expr(bb, sg->data);
448cfe046e178666280b87da998b1b52ecda03ecd89sewardj         e3 = flatten_Expr(bb, sg->guard);
449cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addStmtToIRSB(bb, IRStmt_StoreG(sg->end, e1, e2, e3));
450cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
451cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG:
452cfe046e178666280b87da998b1b52ecda03ecd89sewardj         lg = st->Ist.LoadG.details;
453cfe046e178666280b87da998b1b52ecda03ecd89sewardj         e1 = flatten_Expr(bb, lg->addr);
454cfe046e178666280b87da998b1b52ecda03ecd89sewardj         e2 = flatten_Expr(bb, lg->alt);
455cfe046e178666280b87da998b1b52ecda03ecd89sewardj         e3 = flatten_Expr(bb, lg->guard);
456cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addStmtToIRSB(bb, IRStmt_LoadG(lg->end, lg->cvt, lg->dst,
457cfe046e178666280b87da998b1b52ecda03ecd89sewardj                                        e1, e2, e3));
458cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
459e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
460e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas  = st->Ist.CAS.details;
461e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         e1   = flatten_Expr(bb, cas->addr);
462e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         e2   = cas->expdHi ? flatten_Expr(bb, cas->expdHi) : NULL;
463e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         e3   = flatten_Expr(bb, cas->expdLo);
464e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         e4   = cas->dataHi ? flatten_Expr(bb, cas->dataHi) : NULL;
465e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         e5   = flatten_Expr(bb, cas->dataLo);
466e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas2 = mkIRCAS( cas->oldHi, cas->oldLo, cas->end,
467e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                         e1, e2, e3, e4, e5 );
468e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addStmtToIRSB(bb, IRStmt_CAS(cas2));
469d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         break;
470e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
471e768e92e054cde495849a5c842a477d287677f78sewardj         e1 = flatten_Expr(bb, st->Ist.LLSC.addr);
472e768e92e054cde495849a5c842a477d287677f78sewardj         e2 = st->Ist.LLSC.storedata
473e768e92e054cde495849a5c842a477d287677f78sewardj                 ? flatten_Expr(bb, st->Ist.LLSC.storedata)
474e768e92e054cde495849a5c842a477d287677f78sewardj                 : NULL;
475e768e92e054cde495849a5c842a477d287677f78sewardj         addStmtToIRSB(bb, IRStmt_LLSC(st->Ist.LLSC.end,
476e768e92e054cde495849a5c842a477d287677f78sewardj                                       st->Ist.LLSC.result, e1, e2));
477e768e92e054cde495849a5c842a477d287677f78sewardj         break;
47817442fe8094d0f82266e5a05509f62cac8f7539esewardj      case Ist_Dirty:
47917442fe8094d0f82266e5a05509f62cac8f7539esewardj         d = st->Ist.Dirty.details;
48017442fe8094d0f82266e5a05509f62cac8f7539esewardj         d2 = emptyIRDirty();
48117442fe8094d0f82266e5a05509f62cac8f7539esewardj         *d2 = *d;
482dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         d2->args = shallowCopyIRExprVec(d2->args);
48317442fe8094d0f82266e5a05509f62cac8f7539esewardj         if (d2->mFx != Ifx_None) {
48417442fe8094d0f82266e5a05509f62cac8f7539esewardj            d2->mAddr = flatten_Expr(bb, d2->mAddr);
48517442fe8094d0f82266e5a05509f62cac8f7539esewardj         } else {
48617442fe8094d0f82266e5a05509f62cac8f7539esewardj            vassert(d2->mAddr == NULL);
48717442fe8094d0f82266e5a05509f62cac8f7539esewardj         }
488b8385d891bddf9016250435f47c06ac44ec921bfsewardj         d2->guard = flatten_Expr(bb, d2->guard);
48974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         for (i = 0; d2->args[i]; i++) {
49074142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            IRExpr* arg = d2->args[i];
491ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
49274142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               d2->args[i] = flatten_Expr(bb, arg);
49374142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         }
494dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_Dirty(d2));
49517442fe8094d0f82266e5a05509f62cac8f7539esewardj         break;
496d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
497c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
498d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_IMark:
499dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, st);
5003e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj         break;
5015a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
5025a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         e1 = flatten_Expr(bb, st->Ist.AbiHint.base);
503478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         e2 = flatten_Expr(bb, st->Ist.AbiHint.nia);
504478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         addStmtToIRSB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len, e2));
5055a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         break;
506d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      case Ist_Exit:
5070276d4b776bf2152d2ba6bbaec9b150e65d926eesewardj         e1 = flatten_Expr(bb, st->Ist.Exit.guard);
508dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb, IRStmt_Exit(e1, st->Ist.Exit.jk,
509c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                       st->Ist.Exit.dst,
510c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                       st->Ist.Exit.offsIP));
511d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         break;
512d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj      default:
513d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         vex_printf("\n");
514d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         ppIRStmt(st);
515d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         vex_printf("\n");
516d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj         vpanic("flatten_Stmt");
517d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   }
518d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj}
519d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
5200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
521dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic IRSB* flatten_BB ( IRSB* in )
522d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj{
523d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   Int   i;
524dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   IRSB* out;
525dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   out = emptyIRSB();
526dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
527d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   for (i = 0; i < in->stmts_used; i++)
5284345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj      if (in->stmts[i])
5294345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj         flatten_Stmt( out, in->stmts[i] );
530d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   out->next     = flatten_Expr( out, in->next );
531d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   out->jumpkind = in->jumpkind;
532c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   out->offsIP   = in->offsIP;
533d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj   return out;
534d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj}
535d7cb8538d814660fe68ea7100571fd3ed1de8082sewardj
536edf4d69c8477cad95851d0f6ccf91ab323e5a446sewardj
53784be73746586afb2ea1f197907fd7271c8d1e2ffsewardj/*---------------------------------------------------------------*/
5380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- In-place removal of redundant GETs                      ---*/
53984be73746586afb2ea1f197907fd7271c8d1e2ffsewardj/*---------------------------------------------------------------*/
54084be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
5410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Scan forwards, building up an environment binding (min offset, max
5420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   offset) pairs to values, which will either be temps or constants.
543f6501996bf1f0e2a8ce6817efe9edf6b619bc85bsewardj
5440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   On seeing 't = Get(minoff,maxoff)', look up (minoff,maxoff) in the
5450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   env and if it matches, replace the Get with the stored value.  If
5460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   there is no match, add a (minoff,maxoff) :-> t binding.
5470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   On seeing 'Put (minoff,maxoff) = t or c', first remove in the env
5490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   any binding which fully or partially overlaps with (minoff,maxoff).
5500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Then add a new (minoff,maxoff) :-> t or c binding.  */
5510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Extract the min/max offsets from a guest state array descriptor. */
5530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjinline
555dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic void getArrayBounds ( IRRegArray* descr,
556dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                             UInt* minoff, UInt* maxoff )
557f672901e88dc8635f4ce834ee5a81edf7079f7edsewardj{
5580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   *minoff = descr->base;
5590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   *maxoff = *minoff + descr->nElems*sizeofIRType(descr->elemTy) - 1;
5600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert((*minoff & ~0xFFFF) == 0);
5610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert((*maxoff & ~0xFFFF) == 0);
5620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(*minoff <= *maxoff);
563f672901e88dc8635f4ce834ee5a81edf7079f7edsewardj}
564f672901e88dc8635f4ce834ee5a81edf7079f7edsewardj
5650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Create keys, of the form ((minoffset << 16) | maxoffset). */
5660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic UInt mk_key_GetPut ( Int offset, IRType ty )
568e1d45dace452a557a65efe5419903e8746f93fe3sewardj{
5690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* offset should fit in 16 bits. */
5700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt minoff = offset;
5710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt maxoff = minoff + sizeofIRType(ty) - 1;
5720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert((minoff & ~0xFFFF) == 0);
5730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert((maxoff & ~0xFFFF) == 0);
5740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return (minoff << 16) | maxoff;
575e1d45dace452a557a65efe5419903e8746f93fe3sewardj}
576e1d45dace452a557a65efe5419903e8746f93fe3sewardj
577dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic UInt mk_key_GetIPutI ( IRRegArray* descr )
57884be73746586afb2ea1f197907fd7271c8d1e2ffsewardj{
5790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt minoff, maxoff;
5800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   getArrayBounds( descr, &minoff, &maxoff );
5810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert((minoff & ~0xFFFF) == 0);
5820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert((maxoff & ~0xFFFF) == 0);
5830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return (minoff << 16) | maxoff;
5840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
58584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
5860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Supposing h has keys of the form generated by mk_key_GetPut and
5870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   mk_key_GetIPutI, invalidate any key which overlaps (k_lo
5880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   .. k_hi).
5890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj*/
5900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void invalidateOverlaps ( HashHW* h, UInt k_lo, UInt k_hi )
5910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
5920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int  j;
5930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt e_lo, e_hi;
5940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(k_lo <= k_hi);
5950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* invalidate any env entries which in any way overlap (k_lo
5960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      .. k_hi) */
5970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* vex_printf("invalidate %d .. %d\n", k_lo, k_hi ); */
598e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
5990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (j = 0; j < h->used; j++) {
6000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (!h->inuse[j])
6010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
6020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      e_lo = (((UInt)h->key[j]) >> 16) & 0xFFFF;
6030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      e_hi = ((UInt)h->key[j]) & 0xFFFF;
6040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vassert(e_lo <= e_hi);
6050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (e_hi < k_lo || k_hi < e_lo)
6060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue; /* no overlap possible */
6070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      else
6080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* overlap; invalidate */
6090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         h->inuse[j] = False;
6100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
6110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
612e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
613e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
614dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic void redundant_get_removal_BB ( IRSB* bb )
6150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
6160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   HashHW* env = newHHW();
6170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt    key = 0; /* keep gcc -O happy */
6180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     i, j;
6190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   HWord   val;
620e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
6210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < bb->stmts_used; i++) {
6220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      IRStmt* st = bb->stmts[i];
623e1d45dace452a557a65efe5419903e8746f93fe3sewardj
6248bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
6250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
6260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
6270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Deal with Gets */
628dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag == Ist_WrTmp
629dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && st->Ist.WrTmp.data->tag == Iex_Get) {
6300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* st is 't = Get(...)'.  Look up in the environment and see
6310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if the Get can be replaced. */
632dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         IRExpr* get = st->Ist.WrTmp.data;
6330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         key = (HWord)mk_key_GetPut( get->Iex.Get.offset,
6340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                                     get->Iex.Get.ty );
6350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (lookupHHW(env, &val, (HWord)key)) {
6360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* found it */
6370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* Note, we could do better here.  If the types are
6380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               different we don't do the substitution, since doing so
6390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               could lead to invalidly-typed IR.  An improvement would
6400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               be to stick in a reinterpret-style cast, although that
6410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               would make maintaining flatness more difficult. */
6420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRExpr* valE    = (IRExpr*)val;
6439d2e769a9368d2b22c32a4764a70e9da38769628sewardj            Bool    typesOK = toBool( typeOfIRExpr(bb->tyenv,valE)
644dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                                      == st->Ist.WrTmp.data->Iex.Get.ty );
6450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (typesOK && DEBUG_IROPT) {
6460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("rGET: "); ppIRExpr(get);
6470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("  ->  "); ppIRExpr(valE);
6480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("\n");
6490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            }
6500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (typesOK)
651dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj               bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, valE);
6520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } else {
6530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* Not found, but at least we know that t and the Get(...)
6540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               are now associated.  So add a binding to reflect that
6550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               fact. */
6560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            addToHHW( env, (HWord)key,
657dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                           (HWord)(void*)(IRExpr_RdTmp(st->Ist.WrTmp.tmp)) );
6581d8ce20698148cd658ab21909c844c2afee20153sewardj         }
6590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
6601d8ce20698148cd658ab21909c844c2afee20153sewardj
6610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Deal with Puts: invalidate any env entries overlapped by this
6620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         Put */
6630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Put || st->tag == Ist_PutI) {
6640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         UInt k_lo, k_hi;
6650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (st->tag == Ist_Put) {
6660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            key = mk_key_GetPut( st->Ist.Put.offset,
6670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
6680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } else {
6690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vassert(st->tag == Ist_PutI);
670d6f38b3f822f7d57adfc0da3410995d85d6a4597florian            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
6711d8ce20698148cd658ab21909c844c2afee20153sewardj         }
6723701059741f3daf3b926e203311319710ff9cb6fsewardj
6730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         k_lo = (key >> 16) & 0xFFFF;
6740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         k_hi = key & 0xFFFF;
6750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         invalidateOverlaps(env, k_lo, k_hi);
6760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
6770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      else
6780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Dirty) {
6790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* Deal with dirty helpers which write or modify guest state.
6800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            Invalidate the entire env.  We could do a lot better
6810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            here. */
6820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         IRDirty* d      = st->Ist.Dirty.details;
6830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         Bool     writes = False;
6840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (j = 0; j < d->nFxState; j++) {
6850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (d->fxState[j].fx == Ifx_Modify
6860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                || d->fxState[j].fx == Ifx_Write)
6870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            writes = True;
6880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
6890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (writes) {
6900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* dump the entire env (not clever, but correct ...) */
6910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            for (j = 0; j < env->used; j++)
6920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               env->inuse[j] = False;
6930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (0) vex_printf("rGET: trash env due to dirty helper\n");
6940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
69584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj      }
69684be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
6970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* add this one to the env, if appropriate */
6980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Put) {
699496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(st->Ist.Put.data));
7000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addToHHW( env, (HWord)key, (HWord)(st->Ist.Put.data));
7010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
702e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
7030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   } /* for (i = 0; i < bb->stmts_used; i++) */
704e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
7050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
706e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
7077447b5b3355ac4201e3bd717989232cf7a0d748csewardj
7080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
7090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- In-place removal of redundant PUTs                      ---*/
7100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
711e6b3993279fc50b64b1486546a49643eacf9f45fsewardj
7120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Find any Get uses in st and invalidate any partially or fully
7130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   overlapping ranges listed in env.  Due to the flattening phase, the
714dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   only stmt kind we expect to find a Get on is IRStmt_WrTmp. */
715d9997880a74d96928f3a5154f69df425c9640ab8sewardj
7160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void handle_gets_Stmt (
7170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               HashHW* env,
7180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               IRStmt* st,
719ca2c3c75784d35d136fc7c952717cdee5063c193sewardj               Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
720ca2c3c75784d35d136fc7c952717cdee5063c193sewardj               VexRegisterUpdates pxControl
7210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            )
7220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
7230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     j;
7240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt    key = 0; /* keep gcc -O happy */
7250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Bool    isGet;
7260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Bool    memRW = False;
7270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr* e;
728e1d45dace452a557a65efe5419903e8746f93fe3sewardj
7290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (st->tag) {
7300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
7310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* This is the only interesting case.  Deal with Gets in the RHS
7320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         expression. */
733dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
734dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         e = st->Ist.WrTmp.data;
7350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         switch (e->tag) {
7360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iex_Get:
7370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               isGet = True;
7380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               key = mk_key_GetPut ( e->Iex.Get.offset, e->Iex.Get.ty );
7399bdd2658ffb33e1d9bac768936fae7840af723e6sewardj               break;
7400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iex_GetI:
7410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               isGet = True;
7420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               key = mk_key_GetIPutI ( e->Iex.GetI.descr );
743e1d45dace452a557a65efe5419903e8746f93fe3sewardj               break;
744af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj            case Iex_Load:
7450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               isGet = False;
7460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               memRW = True;
747088bcb4521e94c60c1d8a4dd46151e0cd2e06475sewardj               break;
7480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            default:
7490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               isGet = False;
750d721703a7a904a66c49d0e6318c184d0076b40b0sewardj         }
7510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (isGet) {
7520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            UInt k_lo, k_hi;
7530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            k_lo = (key >> 16) & 0xFFFF;
7540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            k_hi = key & 0xFFFF;
7550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            invalidateOverlaps(env, k_lo, k_hi);
7560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
7570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
758f672901e88dc8635f4ce834ee5a81edf7079f7edsewardj
7590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Be very conservative for dirty helper calls; dump the entire
7600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         environment.  The helper might read guest state, in which
7610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case it needs to be flushed first.  Also, the helper might
7620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         access guest memory, in which case all parts of the guest
7630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         state requiring precise exceptions needs to be flushed.  The
7640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         crude solution is just to flush everything; we could easily
7650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         enough do a lot better if needed. */
7663e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj      /* Probably also overly-conservative, but also dump everything
767c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         if we hit a memory bus event (fence, lock, unlock).  Ditto
768e768e92e054cde495849a5c842a477d287677f78sewardj         AbiHints, CASs, LLs and SCs. */
7695a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
7705a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         vassert(isIRAtom(st->Ist.AbiHint.base));
771478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         vassert(isIRAtom(st->Ist.AbiHint.nia));
7725a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         /* fall through */
773c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
7740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Dirty:
775e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
776e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
7770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (j = 0; j < env->used; j++)
7780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            env->inuse[j] = False;
7790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
780832853b4d71ec6b55031f81bfb1ef49344378068sewardj
7810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* all other cases are boring. */
782af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
783af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(st->Ist.Store.addr));
784af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(st->Ist.Store.data));
7850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         memRW = True;
7860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
787cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG: {
788cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRStoreG* sg = st->Ist.StoreG.details;
789cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(sg->addr));
790cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(sg->data));
791cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(sg->guard));
792cfe046e178666280b87da998b1b52ecda03ecd89sewardj         memRW = True;
793cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
794cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
795cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG: {
796cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRLoadG* lg = st->Ist.LoadG.details;
797cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(lg->addr));
798cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(lg->alt));
799cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(lg->guard));
800cfe046e178666280b87da998b1b52ecda03ecd89sewardj         memRW = True;
801cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
802cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
8030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Exit:
804496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(st->Ist.Exit.guard));
8050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
806f672901e88dc8635f4ce834ee5a81edf7079f7edsewardj
807e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian      case Ist_Put:
808e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian         vassert(isIRAtom(st->Ist.Put.data));
809e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian         break;
810e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian
8110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_PutI:
812d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         vassert(isIRAtom(st->Ist.PutI.details->ix));
813d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         vassert(isIRAtom(st->Ist.PutI.details->data));
8140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
81584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
816d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
817f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
818f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj         break;
819f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj
8200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
8210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n");
8220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ppIRStmt(st);
8230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n");
8240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("handle_gets_Stmt");
82584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj   }
82684be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
8270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (memRW) {
8286c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* This statement accesses memory.  So we might need to dump all parts
8290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         of the environment corresponding to guest state that may not
8300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         be reordered with respect to memory references.  That means
8310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         at least the stack pointer. */
832ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      switch (pxControl) {
833c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe         case VexRegUpdAllregsAtMemAccess:
834c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            /* Precise exceptions required at mem access.
835c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe               Flush all guest state. */
836c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            for (j = 0; j < env->used; j++)
8370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               env->inuse[j] = False;
838c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            break;
8396c46befd9eb90c1b6e739926c1fa335cba75bf46philippe         case VexRegUpdSpAtMemAccess:
8406c46befd9eb90c1b6e739926c1fa335cba75bf46philippe            /* We need to dump the stack pointer
8416c46befd9eb90c1b6e739926c1fa335cba75bf46philippe               (needed for stack extension in m_signals.c).
8426c46befd9eb90c1b6e739926c1fa335cba75bf46philippe               preciseMemExnsFn will use vex_control.iropt_register_updates
8436c46befd9eb90c1b6e739926c1fa335cba75bf46philippe               to verify only the sp is to be checked. */
8446c46befd9eb90c1b6e739926c1fa335cba75bf46philippe            /* fallthrough */
845c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe         case VexRegUpdUnwindregsAtMemAccess:
846c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            for (j = 0; j < env->used; j++) {
847c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe               if (!env->inuse[j])
848c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe                  continue;
849c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe               /* Just flush the minimal amount required, as computed by
850c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe                  preciseMemExnsFn. */
851c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe               HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
852c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe               HWord k_hi = env->key[j] & 0xFFFF;
853ca2c3c75784d35d136fc7c952717cdee5063c193sewardj               if (preciseMemExnsFn( k_lo, k_hi, pxControl ))
854c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe                  env->inuse[j] = False;
855c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            }
856c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            break;
857e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian         case VexRegUpdAllregsAtEachInsn:
858c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            // VexRegUpdAllregsAtEachInsn cannot happen here.
859e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian            // fall through
860ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         case VexRegUpd_INVALID:
861e74ce2eac51a090a67d28d4801aa51ec52efc7dfflorian         default:
862c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe            vassert(0);
8630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
8640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   } /* if (memRW) */
86584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
86684be73746586afb2ea1f197907fd7271c8d1e2ffsewardj}
86784be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
86884be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
8690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Scan backwards, building up a set of (min offset, max
8700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   offset) pairs, indicating those parts of the guest state
8710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for which the next event is a write.
87284be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
8730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   On seeing a conditional exit, empty the set.
87484be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
8750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   On seeing 'Put (minoff,maxoff) = t or c', if (minoff,maxoff) is
8760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   completely within the set, remove the Put.  Otherwise, add
8770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   (minoff,maxoff) to the set.
878d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
8790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   On seeing 'Get (minoff,maxoff)', remove any part of the set
88098430295cf4900160346bfdeea2833bd024b0117sewardj   overlapping (minoff,maxoff).  The same has to happen for any events
88198430295cf4900160346bfdeea2833bd024b0117sewardj   which implicitly read parts of the guest state: dirty helper calls
88298430295cf4900160346bfdeea2833bd024b0117sewardj   and loads/stores.
8830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj*/
88484be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
8850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void redundant_put_removal_BB (
886dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj               IRSB* bb,
887ca2c3c75784d35d136fc7c952717cdee5063c193sewardj               Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
888ca2c3c75784d35d136fc7c952717cdee5063c193sewardj               VexRegisterUpdates pxControl
8890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            )
8900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
8910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     i, j;
8920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Bool    isPut;
8930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt* st;
8940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt    key = 0; /* keep gcc -O happy */
89584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
896ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   vassert(pxControl < VexRegUpdAllregsAtEachInsn);
897c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe
8980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   HashHW* env = newHHW();
899c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
900c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* Initialise the running env with the fact that the final exit
901c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      writes the IP (or, whatever it claims to write.  We don't
902c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      care.) */
903c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   key = mk_key_GetPut(bb->offsIP, typeOfIRExpr(bb->tyenv, bb->next));
904c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   addToHHW(env, (HWord)key, 0);
905c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
906c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* And now scan backwards through the statements. */
9070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = bb->stmts_used-1; i >= 0; i--) {
9080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
9098bee6d15808653a71717c256a3abe96993439d25sewardj
9108bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
9110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
91284be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
9130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Deal with conditional exits. */
9140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Exit) {
915c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //Bool re_add;
916c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* Need to throw out from the env, any part of it which
917c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            doesn't overlap with the guest state written by this exit.
918c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            Since the exit only writes one section, it's simplest to
919c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            do this: (1) check whether env contains a write that
920c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            completely overlaps the write done by this exit; (2) empty
921c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            out env; and (3) if (1) was true, add the write done by
922c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            this exit.
923c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
924c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            To make (1) a bit simpler, merely search for a write that
925c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            exactly matches the one done by this exit.  That's safe
926c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            because it will fail as often or more often than a full
927c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            overlap check, and failure to find an overlapping write in
928c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            env is the safe case (we just nuke env if that
929c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            happens). */
930c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //vassert(isIRAtom(st->Ist.Exit.guard));
931c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* (1) */
932c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //key = mk_key_GetPut(st->Ist.Exit.offsIP,
933c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //                    typeOfIRConst(st->Ist.Exit.dst));
934c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //re_add = lookupHHW(env, NULL, key);
935c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* (2) */
9360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (j = 0; j < env->used; j++)
9370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            env->inuse[j] = False;
938c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* (3) */
939c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //if (0 && re_add)
940c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         //   addToHHW(env, (HWord)key, 0);
9410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
9420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
94362617eff4fd50854f2b36afeafee10ca28b606f1sewardj
9440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Deal with Puts */
9450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      switch (st->tag) {
9460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Ist_Put:
9470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            isPut = True;
9480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            key = mk_key_GetPut( st->Ist.Put.offset,
9490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
950496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj            vassert(isIRAtom(st->Ist.Put.data));
9510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
9520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Ist_PutI:
9530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            isPut = True;
954d6f38b3f822f7d57adfc0da3410995d85d6a4597florian            key = mk_key_GetIPutI( st->Ist.PutI.details->descr );
955d6f38b3f822f7d57adfc0da3410995d85d6a4597florian            vassert(isIRAtom(st->Ist.PutI.details->ix));
956d6f38b3f822f7d57adfc0da3410995d85d6a4597florian            vassert(isIRAtom(st->Ist.PutI.details->data));
9570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
9580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         default:
9590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            isPut = False;
9600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
9610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (isPut && st->tag != Ist_PutI) {
9620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* See if any single entry in env overlaps this Put.  This is
9630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            simplistic in that the transformation is valid if, say, two
9640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            or more entries in the env overlap this Put, but the use of
9650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            lookupHHW will only find a single entry which exactly
9660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            overlaps this Put.  This is suboptimal but safe. */
9670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (lookupHHW(env, NULL, (HWord)key)) {
9680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* This Put is redundant because a later one will overwrite
9690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               it.  So NULL (nop) it out. */
9700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (DEBUG_IROPT) {
9710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("rPUT: "); ppIRStmt(st);
9720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("\n");
9730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            }
974d2445f60726580b450eca68ab40c568f9df338e2sewardj            bb->stmts[i] = IRStmt_NoOp();
9750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } else {
9760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* We can't demonstrate that this Put is redundant, so add it
9770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               to the running collection. */
9780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            addToHHW(env, (HWord)key, 0);
97962617eff4fd50854f2b36afeafee10ca28b606f1sewardj         }
9800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
98184be73746586afb2ea1f197907fd7271c8d1e2ffsewardj      }
98284be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
9830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Deal with Gets.  These remove bits of the environment since
9840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         appearance of a Get means that the next event for that slice
98598430295cf4900160346bfdeea2833bd024b0117sewardj         of the guest state is no longer a write, but a read.  Also
98698430295cf4900160346bfdeea2833bd024b0117sewardj         deals with implicit reads of guest state needed to maintain
98798430295cf4900160346bfdeea2833bd024b0117sewardj         precise exceptions. */
988ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      handle_gets_Stmt( env, st, preciseMemExnsFn, pxControl );
98962617eff4fd50854f2b36afeafee10ca28b606f1sewardj   }
99084be73746586afb2ea1f197907fd7271c8d1e2ffsewardj}
99184be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
99284be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
9930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
9940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Constant propagation and folding                        ---*/
9950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
99684be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
997cdb5feebd7e817c8207471ef734b43c51c14dee3florian#if STATS_IROPT
998cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* How often sameIRExprs was invoked */
999cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic UInt invocation_count;
1000cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* How often sameIRExprs recursed through IRTemp assignments */
1001cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic UInt recursion_count;
1002cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* How often sameIRExprs found identical IRExprs */
1003cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic UInt success_count;
1004cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* How often recursing through assignments to IRTemps helped
1005cdb5feebd7e817c8207471ef734b43c51c14dee3florian   establishing equality. */
1006cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic UInt recursion_success_count;
1007cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Whether or not recursing through an IRTemp assignment helped
1008cdb5feebd7e817c8207471ef734b43c51c14dee3florian   establishing IRExpr equality for a given sameIRExprs invocation. */
1009cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic Bool recursion_helped;
1010cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Whether or not a given sameIRExprs invocation recursed through an
1011cdb5feebd7e817c8207471ef734b43c51c14dee3florian   IRTemp assignment */
1012cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic Bool recursed;
1013cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Maximum number of nodes ever visited when comparing two IRExprs. */
1014cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic UInt max_nodes_visited;
1015cdb5feebd7e817c8207471ef734b43c51c14dee3florian#endif /* STATS_IROPT */
1016cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1017cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Count the number of nodes visited for a given sameIRExprs invocation. */
1018cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic UInt num_nodes_visited;
1019cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1020cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Do not visit more than NODE_LIMIT nodes when comparing two IRExprs.
1021cdb5feebd7e817c8207471ef734b43c51c14dee3florian   This is to guard against performance degradation by visiting large
1022cdb5feebd7e817c8207471ef734b43c51c14dee3florian   trees without success. */
1023cdb5feebd7e817c8207471ef734b43c51c14dee3florian#define NODE_LIMIT 30
1024cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1025cdb5feebd7e817c8207471ef734b43c51c14dee3florian
10260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* The env in this section is a map from IRTemp to IRExpr*,
10270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   that is, an array indexed by IRTemp. */
102884be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
1029cdb5feebd7e817c8207471ef734b43c51c14dee3florian/* Do both expressions compute the same value? The answer is generally
1030cdb5feebd7e817c8207471ef734b43c51c14dee3florian   conservative, i.e. it will report that the expressions do not compute
1031cdb5feebd7e817c8207471ef734b43c51c14dee3florian   the same value when in fact they do. The reason is that we do not
1032cdb5feebd7e817c8207471ef734b43c51c14dee3florian   keep track of changes in the guest state and memory. Thusly, two
1033cdb5feebd7e817c8207471ef734b43c51c14dee3florian   Get's, GetI's or Load's, even when accessing the same location, will be
1034cdb5feebd7e817c8207471ef734b43c51c14dee3florian   assumed to compute different values. After all the accesses may happen
1035cdb5feebd7e817c8207471ef734b43c51c14dee3florian   at different times and the guest state / memory can have changed in
1036a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   the meantime.
1037a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj
1038a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   XXX IMPORTANT XXX the two expressions must have the same IR type.
1039a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   DO NOT CALL HERE WITH DIFFERENTLY-TYPED EXPRESSIONS. */
1040c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
1041c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj/* JRS 20-Mar-2012: split sameIRExprs_aux into a fast inlineable
1042c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   wrapper that deals with the common tags-don't-match case, and a
1043c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   slower out of line general case.  Saves a few insns. */
1044c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
1045c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj__attribute__((noinline))
1046c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjstatic Bool sameIRExprs_aux2 ( IRExpr** env, IRExpr* e1, IRExpr* e2 );
1047c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
1048c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjinline
1049cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic Bool sameIRExprs_aux ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
10500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
1051cdb5feebd7e817c8207471ef734b43c51c14dee3florian   if (e1->tag != e2->tag) return False;
1052c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return sameIRExprs_aux2(env, e1, e2);
1053c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
1054d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
1055c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj__attribute__((noinline))
1056c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjstatic Bool sameIRExprs_aux2 ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1057c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj{
1058cdb5feebd7e817c8207471ef734b43c51c14dee3florian   if (num_nodes_visited++ > NODE_LIMIT) return False;
10596c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
10606c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   switch (e1->tag) {
10616c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case Iex_RdTmp:
1062cdb5feebd7e817c8207471ef734b43c51c14dee3florian         if (e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp) return True;
1063cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1064cdb5feebd7e817c8207471ef734b43c51c14dee3florian         if (env[e1->Iex.RdTmp.tmp] && env[e2->Iex.RdTmp.tmp]) {
1065cdb5feebd7e817c8207471ef734b43c51c14dee3florian            Bool same = sameIRExprs_aux(env, env[e1->Iex.RdTmp.tmp],
1066cdb5feebd7e817c8207471ef734b43c51c14dee3florian                                        env[e2->Iex.RdTmp.tmp]);
1067cdb5feebd7e817c8207471ef734b43c51c14dee3florian#if STATS_IROPT
1068cdb5feebd7e817c8207471ef734b43c51c14dee3florian            recursed = True;
1069cdb5feebd7e817c8207471ef734b43c51c14dee3florian            if (same) recursion_helped = True;
1070cdb5feebd7e817c8207471ef734b43c51c14dee3florian#endif
1071cdb5feebd7e817c8207471ef734b43c51c14dee3florian            return same;
1072cdb5feebd7e817c8207471ef734b43c51c14dee3florian         }
10736c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return False;
1074cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1075cdb5feebd7e817c8207471ef734b43c51c14dee3florian      case Iex_Get:
1076cdb5feebd7e817c8207471ef734b43c51c14dee3florian      case Iex_GetI:
1077cdb5feebd7e817c8207471ef734b43c51c14dee3florian      case Iex_Load:
1078cdb5feebd7e817c8207471ef734b43c51c14dee3florian         /* Guest state / memory could have changed in the meantime. */
1079cdb5feebd7e817c8207471ef734b43c51c14dee3florian         return False;
1080cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1081cdb5feebd7e817c8207471ef734b43c51c14dee3florian      case Iex_Binop:
1082cdb5feebd7e817c8207471ef734b43c51c14dee3florian         return toBool( e1->Iex.Binop.op == e2->Iex.Binop.op
10836399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                        && sameIRExprs_aux( env, e1->Iex.Binop.arg1,
10846399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                                                 e2->Iex.Binop.arg1 )
10856399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                        && sameIRExprs_aux( env, e1->Iex.Binop.arg2,
10866399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                                                 e2->Iex.Binop.arg2 ));
1087cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1088cdb5feebd7e817c8207471ef734b43c51c14dee3florian      case Iex_Unop:
1089cdb5feebd7e817c8207471ef734b43c51c14dee3florian         return toBool( e1->Iex.Unop.op == e2->Iex.Unop.op
10906399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                        && sameIRExprs_aux( env, e1->Iex.Unop.arg,
10916399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                                                 e2->Iex.Unop.arg ));
1092cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1093cdb5feebd7e817c8207471ef734b43c51c14dee3florian      case Iex_Const: {
1094cdb5feebd7e817c8207471ef734b43c51c14dee3florian         IRConst *c1 = e1->Iex.Const.con;
1095cdb5feebd7e817c8207471ef734b43c51c14dee3florian         IRConst *c2 = e2->Iex.Const.con;
1096cdb5feebd7e817c8207471ef734b43c51c14dee3florian         vassert(c1->tag == c2->tag);
1097cdb5feebd7e817c8207471ef734b43c51c14dee3florian         switch (c1->tag) {
1098cdb5feebd7e817c8207471ef734b43c51c14dee3florian            case Ico_U1:   return toBool( c1->Ico.U1  == c2->Ico.U1 );
1099cdb5feebd7e817c8207471ef734b43c51c14dee3florian            case Ico_U8:   return toBool( c1->Ico.U8  == c2->Ico.U8 );
1100cdb5feebd7e817c8207471ef734b43c51c14dee3florian            case Ico_U16:  return toBool( c1->Ico.U16 == c2->Ico.U16 );
1101cdb5feebd7e817c8207471ef734b43c51c14dee3florian            case Ico_U32:  return toBool( c1->Ico.U32 == c2->Ico.U32 );
1102cdb5feebd7e817c8207471ef734b43c51c14dee3florian            case Ico_U64:  return toBool( c1->Ico.U64 == c2->Ico.U64 );
1103cdb5feebd7e817c8207471ef734b43c51c14dee3florian            default: break;
1104cdb5feebd7e817c8207471ef734b43c51c14dee3florian         }
1105cdb5feebd7e817c8207471ef734b43c51c14dee3florian         return False;
1106cdb5feebd7e817c8207471ef734b43c51c14dee3florian      }
1107cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1108420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian      case Iex_Triop: {
1109420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         IRTriop *tri1 = e1->Iex.Triop.details;
1110420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         IRTriop *tri2 = e2->Iex.Triop.details;
1111420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         return toBool( tri1->op == tri2->op
1112420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                        && sameIRExprs_aux( env, tri1->arg1, tri2->arg1 )
1113420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                        && sameIRExprs_aux( env, tri1->arg2, tri2->arg2 )
1114420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                        && sameIRExprs_aux( env, tri1->arg3, tri2->arg3 ));
1115420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian      }
1116cdb5feebd7e817c8207471ef734b43c51c14dee3florian
111799dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
111899dd03e04a6914d90d5fee727d61d76905334becflorian         return toBool(    sameIRExprs_aux( env, e1->Iex.ITE.cond,
111999dd03e04a6914d90d5fee727d61d76905334becflorian                                                 e2->Iex.ITE.cond )
112099dd03e04a6914d90d5fee727d61d76905334becflorian                        && sameIRExprs_aux( env, e1->Iex.ITE.iftrue,
112199dd03e04a6914d90d5fee727d61d76905334becflorian                                                 e2->Iex.ITE.iftrue )
112299dd03e04a6914d90d5fee727d61d76905334becflorian                        && sameIRExprs_aux( env, e1->Iex.ITE.iffalse,
112399dd03e04a6914d90d5fee727d61d76905334becflorian                                                 e2->Iex.ITE.iffalse ));
1124cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1125cdb5feebd7e817c8207471ef734b43c51c14dee3florian      default:
1126cdb5feebd7e817c8207471ef734b43c51c14dee3florian         /* Not very likely to be "same". */
1127cdb5feebd7e817c8207471ef734b43c51c14dee3florian         break;
11286c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   }
1129cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1130cdb5feebd7e817c8207471ef734b43c51c14dee3florian   return False;
1131cdb5feebd7e817c8207471ef734b43c51c14dee3florian}
1132cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1133c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjinline
1134cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic Bool sameIRExprs ( IRExpr** env, IRExpr* e1, IRExpr* e2 )
1135cdb5feebd7e817c8207471ef734b43c51c14dee3florian{
1136cdb5feebd7e817c8207471ef734b43c51c14dee3florian   Bool same;
1137cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1138cdb5feebd7e817c8207471ef734b43c51c14dee3florian   num_nodes_visited = 0;
1139cdb5feebd7e817c8207471ef734b43c51c14dee3florian   same = sameIRExprs_aux(env, e1, e2);
1140cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1141cdb5feebd7e817c8207471ef734b43c51c14dee3florian#if STATS_IROPT
1142cdb5feebd7e817c8207471ef734b43c51c14dee3florian   ++invocation_count;
1143cdb5feebd7e817c8207471ef734b43c51c14dee3florian   if (recursed) ++recursion_count;
1144cdb5feebd7e817c8207471ef734b43c51c14dee3florian   success_count += same;
1145cdb5feebd7e817c8207471ef734b43c51c14dee3florian   if (same && recursion_helped)
1146cdb5feebd7e817c8207471ef734b43c51c14dee3florian      ++recursion_success_count;
1147cdb5feebd7e817c8207471ef734b43c51c14dee3florian   if (num_nodes_visited > max_nodes_visited)
1148cdb5feebd7e817c8207471ef734b43c51c14dee3florian      max_nodes_visited = num_nodes_visited;
1149cdb5feebd7e817c8207471ef734b43c51c14dee3florian   recursed = False; /* reset */
1150cdb5feebd7e817c8207471ef734b43c51c14dee3florian   recursion_helped = False;  /* reset */
1151cdb5feebd7e817c8207471ef734b43c51c14dee3florian#endif /* STATS_IROPT */
1152cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1153cdb5feebd7e817c8207471ef734b43c51c14dee3florian   return same;
11546c299f3acab617581ea504e45fbb6cab24c2b29fsewardj}
11556c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
1156cdb5feebd7e817c8207471ef734b43c51c14dee3florian
1157a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj/* Debugging-only hack (not used in production runs): make a guess
1158a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   whether sameIRExprs might assert due to the two args being of
1159a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   different types.  If in doubt return False.  Is only used when
1160a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   --vex-iropt-level > 0, that is, vex_control.iropt_verbosity > 0.
1161a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   Bad because it duplicates functionality from typeOfIRExpr.  See
1162a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   comment on the single use point below for rationale. */
1163a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardjstatic
1164a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardjBool debug_only_hack_sameIRExprs_might_assert ( IRExpr* e1, IRExpr* e2 )
1165a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj{
1166a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   if (e1->tag != e2->tag) return False;
1167a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   switch (e1->tag) {
1168a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      case Iex_Const: {
1169a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj         /* The only interesting case */
1170a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj         IRConst *c1 = e1->Iex.Const.con;
1171a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj         IRConst *c2 = e2->Iex.Const.con;
1172a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj         return c1->tag != c2->tag;
1173a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      }
1174a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      default:
1175a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj         break;
1176a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   }
1177a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   return False;
1178a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj}
1179a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj
1180a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj
1181ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian/* Is this literally IRExpr_Const(IRConst_U32(0)) ? */
1182ea7eab702d1aab9dae54bf323cef4fc7c91e0025florianstatic Bool isZeroU32 ( IRExpr* e )
1183ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian{
1184ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian   return toBool( e->tag == Iex_Const
1185ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian                  && e->Iex.Const.con->tag == Ico_U32
1186ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian                  && e->Iex.Const.con->Ico.U32 == 0);
1187ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian}
1188ea7eab702d1aab9dae54bf323cef4fc7c91e0025florian
118940226d12a7e6563e74cda5349e72d88f74160a0bflorian/* Is this literally IRExpr_Const(IRConst_U64(0)) ?
119040226d12a7e6563e74cda5349e72d88f74160a0bflorian   Currently unused; commented out to avoid compiler warning */
119140226d12a7e6563e74cda5349e72d88f74160a0bflorian#if 0
1192bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardjstatic Bool isZeroU64 ( IRExpr* e )
1193bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj{
1194bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj   return toBool( e->tag == Iex_Const
1195bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj                  && e->Iex.Const.con->tag == Ico_U64
1196bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj                  && e->Iex.Const.con->Ico.U64 == 0);
1197bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj}
119840226d12a7e6563e74cda5349e72d88f74160a0bflorian#endif
1199bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj
12009571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj/* Is this literally IRExpr_Const(IRConst_V128(0)) ? */
12019571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardjstatic Bool isZeroV128 ( IRExpr* e )
12029571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj{
12039571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj   return toBool( e->tag == Iex_Const
12049571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  && e->Iex.Const.con->tag == Ico_V128
12059571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  && e->Iex.Const.con->Ico.V128 == 0x0000);
12069571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj}
12079571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj
12089571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj/* Is this literally IRExpr_Const(IRConst_V256(0)) ? */
12099571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardjstatic Bool isZeroV256 ( IRExpr* e )
12109571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj{
12119571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj   return toBool( e->tag == Iex_Const
12129571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  && e->Iex.Const.con->tag == Ico_V256
12139571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  && e->Iex.Const.con->Ico.V256 == 0x00000000);
12149571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj}
12159571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj
1216f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian/* Is this an integer constant with value 0 ? */
1217f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorianstatic Bool isZeroU ( IRExpr* e )
1218f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian{
1219f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian   if (e->tag != Iex_Const) return False;
1220f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian   switch (e->Iex.Const.con->tag) {
1221f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian      case Ico_U1:    return toBool( e->Iex.Const.con->Ico.U1  == 0);
1222f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian      case Ico_U8:    return toBool( e->Iex.Const.con->Ico.U8  == 0);
1223f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian      case Ico_U16:   return toBool( e->Iex.Const.con->Ico.U16 == 0);
1224f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian      case Ico_U32:   return toBool( e->Iex.Const.con->Ico.U32 == 0);
1225f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian      case Ico_U64:   return toBool( e->Iex.Const.con->Ico.U64 == 0);
1226a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      case Ico_V256:  return toBool( e->Iex.Const.con->Ico.V256 == 0x00000000);
1227f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian      default: vpanic("isZeroU");
1228f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian   }
1229f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian}
1230f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
1231cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj/* Is this an integer constant with value 1---1b ? */
1232cf4be4a70cb7393839b68fad19e3660e2c053b57sewardjstatic Bool isOnesU ( IRExpr* e )
1233cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj{
1234cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj   if (e->tag != Iex_Const) return False;
1235cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj   switch (e->Iex.Const.con->tag) {
1236cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Ico_U8:    return toBool( e->Iex.Const.con->Ico.U8  == 0xFF);
1237cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Ico_U16:   return toBool( e->Iex.Const.con->Ico.U16 == 0xFFFF);
1238cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Ico_U32:   return toBool( e->Iex.Const.con->Ico.U32
1239cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj                                     == 0xFFFFFFFF);
1240cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Ico_U64:   return toBool( e->Iex.Const.con->Ico.U64
1241cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj                                     == 0xFFFFFFFFFFFFFFFFULL);
1242cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      default: ppIRExpr(e); vpanic("isOnesU");
1243cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj   }
1244cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj}
1245cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj
12460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic Bool notBool ( Bool b )
12470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
12480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (b == True) return False;
12490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (b == False) return True;
12500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vpanic("notBool");
12510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
125284be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
12530033ddccac6f90789fe2e78e86b8a649931d77b4sewardj/* Make a zero which has the same type as the result of the given
12540033ddccac6f90789fe2e78e86b8a649931d77b4sewardj   primop. */
125564d776c37f5dcb3475b0ca99aaafa448ba98b717sewardjstatic IRExpr* mkZeroOfPrimopResultType ( IROp op )
12560033ddccac6f90789fe2e78e86b8a649931d77b4sewardj{
12570033ddccac6f90789fe2e78e86b8a649931d77b4sewardj   switch (op) {
1258a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      case Iop_CmpNE32: return IRExpr_Const(IRConst_U1(toBool(0)));
12590033ddccac6f90789fe2e78e86b8a649931d77b4sewardj      case Iop_Xor8:  return IRExpr_Const(IRConst_U8(0));
12600033ddccac6f90789fe2e78e86b8a649931d77b4sewardj      case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));
1261be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      case Iop_Sub32:
12620033ddccac6f90789fe2e78e86b8a649931d77b4sewardj      case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));
1263bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj      case Iop_And64:
126464d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj      case Iop_Sub64:
12650033ddccac6f90789fe2e78e86b8a649931d77b4sewardj      case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));
126636a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj      case Iop_XorV128:
126736a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj      case Iop_AndV128: return IRExpr_Const(IRConst_V128(0));
126870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Iop_XorV256:
12691b7c4719bc445c8e71230e58e62050d67aaf0109florian      case Iop_AndV256: return IRExpr_Const(IRConst_V256(0));
127064d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj      default: vpanic("mkZeroOfPrimopResultType: bad primop");
127164d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj   }
127264d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj}
127364d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj
127464d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj/* Make a value containing all 1-bits, which has the same type as the
127564d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj   result of the given primop. */
127664d776c37f5dcb3475b0ca99aaafa448ba98b717sewardjstatic IRExpr* mkOnesOfPrimopResultType ( IROp op )
127764d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj{
127864d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj   switch (op) {
1279a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      case Iop_CmpEQ32:
128064d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj      case Iop_CmpEQ64:
128164d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj         return IRExpr_Const(IRConst_U1(toBool(1)));
1282cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Iop_Or8:
1283cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj         return IRExpr_Const(IRConst_U8(0xFF));
1284cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Iop_Or16:
1285cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj         return IRExpr_Const(IRConst_U16(0xFFFF));
1286cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Iop_Or32:
1287cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj         return IRExpr_Const(IRConst_U32(0xFFFFFFFF));
128864d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj      case Iop_CmpEQ8x8:
1289cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj      case Iop_Or64:
129064d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj         return IRExpr_Const(IRConst_U64(0xFFFFFFFFFFFFFFFFULL));
129164d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj      case Iop_CmpEQ8x16:
1292899d1838d6fd60b141a3d808b02dc04be5901681sewardj      case Iop_CmpEQ16x8:
1293ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj      case Iop_CmpEQ32x4:
129464d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj         return IRExpr_Const(IRConst_V128(0xFFFF));
129564d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj      default:
1296cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj         ppIROp(op);
129764d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj         vpanic("mkOnesOfPrimopResultType: bad primop");
12980033ddccac6f90789fe2e78e86b8a649931d77b4sewardj   }
12990033ddccac6f90789fe2e78e86b8a649931d77b4sewardj}
13000033ddccac6f90789fe2e78e86b8a649931d77b4sewardj
13014cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj/* Helpers for folding Clz32/64. */
13024cba9f4d2f3b9999586c56fc8507d50df8607a74sewardjstatic UInt fold_Clz64 ( ULong value )
13034cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj{
13044cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   UInt i;
13054cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   vassert(value != 0ULL); /* no defined semantics for arg==0 */
13064cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   for (i = 0; i < 64; ++i) {
13077f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj      if (0ULL != (value & (((ULong)1) << (63 - i)))) return i;
13084cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   }
13094cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   vassert(0);
13104cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   /*NOTREACHED*/
13114cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   return 0;
13124cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj}
13134cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj
13144cba9f4d2f3b9999586c56fc8507d50df8607a74sewardjstatic UInt fold_Clz32 ( UInt value )
13154cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj{
13164cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   UInt i;
13174cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   vassert(value != 0); /* no defined semantics for arg==0 */
13184cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   for (i = 0; i < 32; ++i) {
13197f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj      if (0 != (value & (((UInt)1) << (31 - i)))) return i;
13204cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   }
13214cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   vassert(0);
13224cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   /*NOTREACHED*/
13234cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj   return 0;
13244cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj}
13254cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj
13264a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj/* V64 holds 8 summary-constant bits in V128/V256 style.  Convert to
13274a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj   the corresponding real constant. */
13284a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//XXX re-check this before use
13294a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//static ULong de_summarise_V64 ( UChar v64 )
13304a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//{
13314a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   ULong r = 0;
13324a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<0)) r |= 0x00000000000000FFULL;
13334a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<1)) r |= 0x000000000000FF00ULL;
13344a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<2)) r |= 0x0000000000FF0000ULL;
13354a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<3)) r |= 0x00000000FF000000ULL;
13364a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<4)) r |= 0x000000FF00000000ULL;
13374a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<5)) r |= 0x0000FF0000000000ULL;
13384a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<6)) r |= 0x00FF000000000000ULL;
13394a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   if (v64 & (1<<7)) r |= 0xFF00000000000000ULL;
13404a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//   return r;
13414a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj//}
13420033ddccac6f90789fe2e78e86b8a649931d77b4sewardj
1343009230b9758291b594e60d7c0243a73d53e81854sewardj/* Helper for arbitrary expression pattern matching in flat IR.  If
1344009230b9758291b594e60d7c0243a73d53e81854sewardj   'e' is a reference to a tmp, look it up in env -- repeatedly, if
1345009230b9758291b594e60d7c0243a73d53e81854sewardj   necessary -- until it resolves to a non-tmp.  Note that this can
1346009230b9758291b594e60d7c0243a73d53e81854sewardj   return NULL if it can't resolve 'e' to a new expression, which will
1347009230b9758291b594e60d7c0243a73d53e81854sewardj   be the case if 'e' is instead defined by an IRStmt (IRDirty or
1348009230b9758291b594e60d7c0243a73d53e81854sewardj   LLSC). */
1349009230b9758291b594e60d7c0243a73d53e81854sewardjstatic IRExpr* chase ( IRExpr** env, IRExpr* e )
1350009230b9758291b594e60d7c0243a73d53e81854sewardj{
1351009230b9758291b594e60d7c0243a73d53e81854sewardj   /* Why is this loop guaranteed to terminate?  Because all tmps must
1352009230b9758291b594e60d7c0243a73d53e81854sewardj      have definitions before use, hence a tmp cannot be bound
1353009230b9758291b594e60d7c0243a73d53e81854sewardj      (directly or indirectly) to itself. */
1354009230b9758291b594e60d7c0243a73d53e81854sewardj   while (e->tag == Iex_RdTmp) {
1355009230b9758291b594e60d7c0243a73d53e81854sewardj      if (0) { vex_printf("chase "); ppIRExpr(e); vex_printf("\n"); }
1356009230b9758291b594e60d7c0243a73d53e81854sewardj      e = env[(Int)e->Iex.RdTmp.tmp];
1357009230b9758291b594e60d7c0243a73d53e81854sewardj      if (e == NULL) break;
1358009230b9758291b594e60d7c0243a73d53e81854sewardj   }
1359009230b9758291b594e60d7c0243a73d53e81854sewardj   return e;
1360009230b9758291b594e60d7c0243a73d53e81854sewardj}
1361009230b9758291b594e60d7c0243a73d53e81854sewardj
136216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/* Similar to |chase|, but follows at most one level of tmp reference. */
136316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardjstatic IRExpr* chase1 ( IRExpr** env, IRExpr* e )
136416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj{
136516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (e == NULL || e->tag != Iex_RdTmp)
136616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return e;
136716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   else
136816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return env[(Int)e->Iex.RdTmp.tmp];
136916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj}
137016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
1371cdb5feebd7e817c8207471ef734b43c51c14dee3florianstatic IRExpr* fold_Expr ( IRExpr** env, IRExpr* e )
13720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
13730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     shift;
13740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr* e2 = e; /* e2 is the result of folding e, if possible */
137584be73746586afb2ea1f197907fd7271c8d1e2ffsewardj
1376708417d56d1798ffd62a05b7932da47cdc3d3337florian   switch (e->tag) {
1377708417d56d1798ffd62a05b7932da47cdc3d3337florian   case Iex_Unop:
1378708417d56d1798ffd62a05b7932da47cdc3d3337florian      /* UNARY ops */
1379708417d56d1798ffd62a05b7932da47cdc3d3337florian      if (e->Iex.Unop.arg->tag == Iex_Const) {
1380708417d56d1798ffd62a05b7932da47cdc3d3337florian         switch (e->Iex.Unop.op) {
13810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_1Uto8:
13829d2e769a9368d2b22c32a4764a70e9da38769628sewardj            e2 = IRExpr_Const(IRConst_U8(toUChar(
13830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
13849d2e769a9368d2b22c32a4764a70e9da38769628sewardj                    ? 1 : 0)));
13850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
13860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_1Uto32:
13870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32(
13880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
13890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    ? 1 : 0));
13900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
13912716ff157eb1a0351fcfa3aba8671aee198a9448sewardj         case Iop_1Uto64:
13922716ff157eb1a0351fcfa3aba8671aee198a9448sewardj            e2 = IRExpr_Const(IRConst_U64(
13932716ff157eb1a0351fcfa3aba8671aee198a9448sewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
13942716ff157eb1a0351fcfa3aba8671aee198a9448sewardj                    ? 1 : 0));
13952716ff157eb1a0351fcfa3aba8671aee198a9448sewardj            break;
139662617eff4fd50854f2b36afeafee10ca28b606f1sewardj
13971bee561912427ca8f8998c89b62d86ba2ee49732sewardj         case Iop_1Sto8:
13981bee561912427ca8f8998c89b62d86ba2ee49732sewardj            e2 = IRExpr_Const(IRConst_U8(toUChar(
13991bee561912427ca8f8998c89b62d86ba2ee49732sewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
14001bee561912427ca8f8998c89b62d86ba2ee49732sewardj                    ? 0xFF : 0)));
14011bee561912427ca8f8998c89b62d86ba2ee49732sewardj            break;
140268884efaa49d8454fa4b036af98af5339343f148sewardj         case Iop_1Sto16:
1403743d8f0a1b1dfee13633307d11725e2124707db0sewardj            e2 = IRExpr_Const(IRConst_U16(toUShort(
140468884efaa49d8454fa4b036af98af5339343f148sewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
1405743d8f0a1b1dfee13633307d11725e2124707db0sewardj                    ? 0xFFFF : 0)));
140668884efaa49d8454fa4b036af98af5339343f148sewardj            break;
14070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_1Sto32:
14080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32(
14090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
14100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    ? 0xFFFFFFFF : 0));
14110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_1Sto64:
14130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U64(
14140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1
14150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    ? 0xFFFFFFFFFFFFFFFFULL : 0));
14160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
141717442fe8094d0f82266e5a05509f62cac8f7539esewardj
14180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_8Sto32: {
1419108e03fcb0a4ef42164235b1988aa540aa1e5298florian            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1420108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u32 <<= 24;
1421108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u32 = (Int)u32 >> 24;   /* signed shift */
1422108e03fcb0a4ef42164235b1988aa540aa1e5298florian            e2 = IRExpr_Const(IRConst_U32(u32));
14230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
1424b8e7586be6001ff697d561160e089b0232784896sewardj         }
14257f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         case Iop_16Sto32: {
1426108e03fcb0a4ef42164235b1988aa540aa1e5298florian            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1427108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u32 <<= 16;
1428108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u32 = (Int)u32 >> 16;   /* signed shift */
1429108e03fcb0a4ef42164235b1988aa540aa1e5298florian            e2 = IRExpr_Const(IRConst_U32(u32));
14307f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            break;
14317f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         }
1432291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         case Iop_8Uto64:
1433291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            e2 = IRExpr_Const(IRConst_U64(
1434291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj                    0xFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
1435291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            break;
1436291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         case Iop_16Uto64:
1437291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            e2 = IRExpr_Const(IRConst_U64(
1438291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj                    0xFFFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
1439291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            break;
14400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_8Uto32:
14410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32(
14420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
14430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14447f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         case Iop_8Sto16: {
1445108e03fcb0a4ef42164235b1988aa540aa1e5298florian            UShort u16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;
1446108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u16 <<= 8;
1447108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u16 = (Short)u16 >> 8;  /* signed shift */
1448108e03fcb0a4ef42164235b1988aa540aa1e5298florian            e2 = IRExpr_Const(IRConst_U16(u16));
14497f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            break;
14507f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         }
14517f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         case Iop_8Uto16:
14527f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            e2 = IRExpr_Const(IRConst_U16(
14537f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));
14547f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            break;
14550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_16Uto32:
14560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32(
14570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));
14580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_32to16:
14609d2e769a9368d2b22c32a4764a70e9da38769628sewardj            e2 = IRExpr_Const(IRConst_U16(toUShort(
14619d2e769a9368d2b22c32a4764a70e9da38769628sewardj                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
14620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_32to8:
14649d2e769a9368d2b22c32a4764a70e9da38769628sewardj            e2 = IRExpr_Const(IRConst_U8(toUChar(
14659d2e769a9368d2b22c32a4764a70e9da38769628sewardj                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
14660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_32to1:
14689d2e769a9368d2b22c32a4764a70e9da38769628sewardj            e2 = IRExpr_Const(IRConst_U1(toBool(
14699d2e769a9368d2b22c32a4764a70e9da38769628sewardj                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
14709d2e769a9368d2b22c32a4764a70e9da38769628sewardj                 )));
14710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
1472291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         case Iop_64to1:
1473291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            e2 = IRExpr_Const(IRConst_U1(toBool(
1474291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U64)
1475291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj                 )));
1476291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            break;
147739e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj
14784a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         case Iop_NotV128:
14794a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            e2 = IRExpr_Const(IRConst_V128(
14804a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.V128)));
14814a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            break;
1482f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj         case Iop_Not64:
1483f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj            e2 = IRExpr_Const(IRConst_U64(
1484f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U64)));
1485f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj            break;
14860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_Not32:
14870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32(
14880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
14890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_Not16:
14919d2e769a9368d2b22c32a4764a70e9da38769628sewardj            e2 = IRExpr_Const(IRConst_U16(toUShort(
14929d2e769a9368d2b22c32a4764a70e9da38769628sewardj                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U16))));
14930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
14940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_Not8:
14959d2e769a9368d2b22c32a4764a70e9da38769628sewardj            e2 = IRExpr_Const(IRConst_U8(toUChar(
14969d2e769a9368d2b22c32a4764a70e9da38769628sewardj                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U8))));
14970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
149839e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj
14990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_Not1:
15000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U1(
15010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));
15020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
1503d503a3284fea71d0be035536c995bdd9a96f91bdsewardj
1504291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         case Iop_64to8: {
1505291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1506291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            w64 &= 0xFFULL;
1507291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            e2 = IRExpr_Const(IRConst_U8( (UChar)w64 ));
1508291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            break;
1509291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         }
1510291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         case Iop_64to16: {
1511291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1512291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            w64 &= 0xFFFFULL;
1513e85bc40fb3dcbe32202239f042b180686765fdc3sewardj            e2 = IRExpr_Const(IRConst_U16( (UShort)w64 ));
1514291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj            break;
1515291a7e8fa181da2b707a2a7d51fbdccb17908f87sewardj         }
15160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_64to32: {
15170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
15180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            w64 &= 0x00000000FFFFFFFFULL;
15190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
15200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
15210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
15220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         case Iop_64HIto32: {
15230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
15240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            w64 >>= 32;
15250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));
15260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
152739e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj         }
1528b5710b8d435892c36da69c815db96f1db2feefc2sewardj         case Iop_32Uto64:
1529b5710b8d435892c36da69c815db96f1db2feefc2sewardj            e2 = IRExpr_Const(IRConst_U64(
1530b5710b8d435892c36da69c815db96f1db2feefc2sewardj                    0xFFFFFFFFULL
1531b5710b8d435892c36da69c815db96f1db2feefc2sewardj                    & e->Iex.Unop.arg->Iex.Const.con->Ico.U32));
1532b5710b8d435892c36da69c815db96f1db2feefc2sewardj            break;
15337f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         case Iop_16Sto64: {
1534108e03fcb0a4ef42164235b1988aa540aa1e5298florian            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
1535108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u64 <<= 48;
1536108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u64 = (Long)u64 >> 48;   /* signed shift */
1537108e03fcb0a4ef42164235b1988aa540aa1e5298florian            e2 = IRExpr_Const(IRConst_U64(u64));
15387f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            break;
15397f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         }
1540287e9bb7ae95950d91c96eb7899c028a46edbed4sewardj         case Iop_32Sto64: {
1541108e03fcb0a4ef42164235b1988aa540aa1e5298florian            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1542108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u64 <<= 32;
1543108e03fcb0a4ef42164235b1988aa540aa1e5298florian            u64 = (Long)u64 >> 32;   /* signed shift */
1544108e03fcb0a4ef42164235b1988aa540aa1e5298florian            e2 = IRExpr_Const(IRConst_U64(u64));
1545287e9bb7ae95950d91c96eb7899c028a46edbed4sewardj            break;
1546287e9bb7ae95950d91c96eb7899c028a46edbed4sewardj         }
15477f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj
15487f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         case Iop_16to8: {
15497f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
15507f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            w16 &= 0xFF;
15517f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
15527f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            break;
15537f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         }
15547f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         case Iop_16HIto8: {
15557f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            UShort w16 = e->Iex.Unop.arg->Iex.Const.con->Ico.U16;
15567f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            w16 >>= 8;
15577f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            w16 &= 0xFF;
15587f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            e2 = IRExpr_Const(IRConst_U8( (UChar)w16 ));
15597f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            break;
15607f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj         }
15617f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj
15620033ddccac6f90789fe2e78e86b8a649931d77b4sewardj         case Iop_CmpNEZ8:
15630033ddccac6f90789fe2e78e86b8a649931d77b4sewardj            e2 = IRExpr_Const(IRConst_U1(toBool(
15640033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                    0 !=
15650033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                    (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)
15660033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                 )));
15670033ddccac6f90789fe2e78e86b8a649931d77b4sewardj            break;
15680033ddccac6f90789fe2e78e86b8a649931d77b4sewardj         case Iop_CmpNEZ32:
15690033ddccac6f90789fe2e78e86b8a649931d77b4sewardj            e2 = IRExpr_Const(IRConst_U1(toBool(
15700033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                    0 !=
15710033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                    (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
15720033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                 )));
15730033ddccac6f90789fe2e78e86b8a649931d77b4sewardj            break;
15740033ddccac6f90789fe2e78e86b8a649931d77b4sewardj         case Iop_CmpNEZ64:
15750033ddccac6f90789fe2e78e86b8a649931d77b4sewardj            e2 = IRExpr_Const(IRConst_U1(toBool(
15760033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                    0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64
15770033ddccac6f90789fe2e78e86b8a649931d77b4sewardj                 )));
15780033ddccac6f90789fe2e78e86b8a649931d77b4sewardj            break;
15790033ddccac6f90789fe2e78e86b8a649931d77b4sewardj
1580eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         case Iop_CmpwNEZ32: {
1581eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            UInt w32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1582eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            if (w32 == 0)
1583eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj               e2 = IRExpr_Const(IRConst_U32( 0 ));
1584eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            else
1585eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj               e2 = IRExpr_Const(IRConst_U32( 0xFFFFFFFF ));
1586eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            break;
1587eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         }
1588eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         case Iop_CmpwNEZ64: {
1589eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1590eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            if (w64 == 0)
1591eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj               e2 = IRExpr_Const(IRConst_U64( 0 ));
1592eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            else
1593eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj               e2 = IRExpr_Const(IRConst_U64( 0xFFFFFFFFFFFFFFFFULL ));
1594eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            break;
1595eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         }
1596eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj
1597eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         case Iop_Left32: {
1598eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
1599eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            Int  s32 = (Int)(u32 & 0xFFFFFFFF);
1600eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            s32 = (s32 | (-s32));
1601eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            e2 = IRExpr_Const( IRConst_U32( (UInt)s32 ));
1602eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            break;
1603eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         }
1604eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj
1605eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         case Iop_Left64: {
1606eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
1607eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            Long  s64 = (Long)u64;
1608eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            s64 = (s64 | (-s64));
1609eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            e2 = IRExpr_Const( IRConst_U64( (ULong)s64 ));
1610eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            break;
1611eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         }
1612eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj
16134cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj         case Iop_Clz32: {
16144cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
16154cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj            if (u32 != 0)
16164cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj               e2 = IRExpr_Const(IRConst_U32(fold_Clz32(u32)));
16174cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj            break;
16184cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj         }
16194cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj         case Iop_Clz64: {
16204cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
16214cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj            if (u64 != 0ULL)
16224cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj               e2 = IRExpr_Const(IRConst_U64(fold_Clz64(u64)));
16234cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj            break;
16244cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj         }
16254cba9f4d2f3b9999586c56fc8507d50df8607a74sewardj
16264a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         /* For these vector ones, can't fold all cases, but at least
16274a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            do the most obvious one.  Could do better here using
16284a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            summarise/desummarise of vector constants, but too
16294a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            difficult to verify; hence just handle the zero cases. */
16304a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         case Iop_32UtoV128: {
16314a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
16324a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            if (0 == u32) {
16334a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_V128(0x0000));
16344a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            } else {
16354a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               goto unhandled;
16364a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            }
16374a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            break;
16384a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         }
16394a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         case Iop_V128to64: {
16404a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
16414a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            if (0 == ((v128 >> 0) & 0xFF)) {
16424a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_U64(0));
16434a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            } else {
16444a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               goto unhandled;
16454a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            }
16464a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            break;
16474a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         }
16484a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         case Iop_V128HIto64: {
16494a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
16504a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            if (0 == ((v128 >> 8) & 0xFF)) {
16514a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_U64(0));
16524a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            } else {
16534a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               goto unhandled;
16544a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            }
16554a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            break;
16564a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         }
16574a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         case Iop_64UtoV128: {
16584a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
16594a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            if (0 == u64) {
16604a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_V128(0x0000));
16614a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            } else {
16624a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               goto unhandled;
16634a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            }
16644a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            break;
16654a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj         }
16664a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj
1667ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj         /* Even stupider (although still correct ..) */
1668ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj         case Iop_V256to64_0: case Iop_V256to64_1:
1669ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj         case Iop_V256to64_2: case Iop_V256to64_3: {
1670ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj            UInt v256 = e->Iex.Unop.arg->Iex.Const.con->Ico.V256;
1671ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj            if (v256 == 0x00000000) {
1672ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj               e2 = IRExpr_Const(IRConst_U64(0));
1673ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj            } else {
1674ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj               goto unhandled;
1675ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj            }
1676ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj            break;
1677ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj         }
1678ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj
1679fbe569d562acd250611c7d0491485bea1a8159cfsewardj         case Iop_ZeroHI64ofV128: {
1680fbe569d562acd250611c7d0491485bea1a8159cfsewardj            /* Could do better here -- only need to look at the bottom 64 bits
1681fbe569d562acd250611c7d0491485bea1a8159cfsewardj               of the argument, really. */
1682fbe569d562acd250611c7d0491485bea1a8159cfsewardj            UShort v128 = e->Iex.Unop.arg->Iex.Const.con->Ico.V128;
1683fbe569d562acd250611c7d0491485bea1a8159cfsewardj            if (v128 == 0x0000) {
1684fbe569d562acd250611c7d0491485bea1a8159cfsewardj               e2 = IRExpr_Const(IRConst_V128(0x0000));
1685fbe569d562acd250611c7d0491485bea1a8159cfsewardj            } else {
1686fbe569d562acd250611c7d0491485bea1a8159cfsewardj               goto unhandled;
1687fbe569d562acd250611c7d0491485bea1a8159cfsewardj            }
1688fbe569d562acd250611c7d0491485bea1a8159cfsewardj            break;
1689fbe569d562acd250611c7d0491485bea1a8159cfsewardj         }
1690fbe569d562acd250611c7d0491485bea1a8159cfsewardj
16910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         default:
16920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            goto unhandled;
169339e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj      }
1694708417d56d1798ffd62a05b7932da47cdc3d3337florian      }
1695708417d56d1798ffd62a05b7932da47cdc3d3337florian      break;
1696d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
1697708417d56d1798ffd62a05b7932da47cdc3d3337florian   case Iex_Binop:
1698708417d56d1798ffd62a05b7932da47cdc3d3337florian      /* BINARY ops */
16990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (e->Iex.Binop.arg1->tag == Iex_Const
17000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          && e->Iex.Binop.arg2->tag == Iex_Const) {
17010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* cases where both args are consts */
17020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         switch (e->Iex.Binop.op) {
1703d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
1704855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Or -- */
17050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Or8:
17069d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U8(toUChar(
17070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
17089d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
17090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
17100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Or16:
17119d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U16(toUShort(
17120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
17139d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
17140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
17150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Or32:
17160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               e2 = IRExpr_Const(IRConst_U32(
17170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
17180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
17190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1720f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj            case Iop_Or64:
1721f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj               e2 = IRExpr_Const(IRConst_U64(
1722f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1723f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1724f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj               break;
17254a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_OrV128:
17264a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_V128(
17274a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
17284a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
17294a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               break;
1730d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
1731855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Xor -- */
17320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Xor8:
17339d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U8(toUChar(
17340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
17359d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
17360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
173782c9f2fc94b8b7d741ac781656fb918507f02bf4sewardj            case Iop_Xor16:
1738c7c098ffb5170559fa21b341ced757e6e347f16esewardj               e2 = IRExpr_Const(IRConst_U16(toUShort(
173982c9f2fc94b8b7d741ac781656fb918507f02bf4sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
1740c7c098ffb5170559fa21b341ced757e6e347f16esewardj                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
174182c9f2fc94b8b7d741ac781656fb918507f02bf4sewardj               break;
1742855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_Xor32:
1743855dc72bbd008ca475ba5853c67b0b173096de1asewardj               e2 = IRExpr_Const(IRConst_U32(
1744855dc72bbd008ca475ba5853c67b0b173096de1asewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1745855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1746855dc72bbd008ca475ba5853c67b0b173096de1asewardj               break;
1747f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj            case Iop_Xor64:
1748f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj               e2 = IRExpr_Const(IRConst_U64(
1749f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1750f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1751f057afbef0dd5dd94a9702422ab8192565bd0f96sewardj               break;
17524a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_XorV128:
17534a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_V128(
17544a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
17554a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
17564a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               break;
1757855dc72bbd008ca475ba5853c67b0b173096de1asewardj
1758855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- And -- */
17590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_And8:
17609d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U8(toUChar(
17610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
17629d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
17630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
17647f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            case Iop_And16:
17657f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               e2 = IRExpr_Const(IRConst_U16(toUShort(
17667f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16
17677f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));
17687f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               break;
1769855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_And32:
17700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               e2 = IRExpr_Const(IRConst_U32(
17710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1772855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
17730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1774855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_And64:
177570a8ddfd89fbf0b0dc7b97e8bce9897cf31ba003sewardj               e2 = IRExpr_Const(IRConst_U64(
177670a8ddfd89fbf0b0dc7b97e8bce9897cf31ba003sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1777855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
177870a8ddfd89fbf0b0dc7b97e8bce9897cf31ba003sewardj               break;
17794a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_AndV128:
17804a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               e2 = IRExpr_Const(IRConst_V128(
17814a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.V128
17824a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                        & e->Iex.Binop.arg2->Iex.Const.con->Ico.V128)));
17834a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               break;
1784c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj
1785855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Add -- */
1786855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_Add8:
1787855dc72bbd008ca475ba5853c67b0b173096de1asewardj               e2 = IRExpr_Const(IRConst_U8(toUChar(
1788855dc72bbd008ca475ba5853c67b0b173096de1asewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1789855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
1790855dc72bbd008ca475ba5853c67b0b173096de1asewardj               break;
17910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Add32:
17920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               e2 = IRExpr_Const(IRConst_U32(
17930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
17940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
17950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1796c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj            case Iop_Add64:
1797c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj               e2 = IRExpr_Const(IRConst_U64(
1798c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1799c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj                        + e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1800c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj               break;
1801c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj
1802855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Sub -- */
1803855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_Sub8:
1804855dc72bbd008ca475ba5853c67b0b173096de1asewardj               e2 = IRExpr_Const(IRConst_U8(toUChar(
1805855dc72bbd008ca475ba5853c67b0b173096de1asewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
1806855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));
18070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1808855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_Sub32:
18090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               e2 = IRExpr_Const(IRConst_U32(
18100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
1811855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
1812855dc72bbd008ca475ba5853c67b0b173096de1asewardj               break;
1813855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_Sub64:
1814855dc72bbd008ca475ba5853c67b0b173096de1asewardj               e2 = IRExpr_Const(IRConst_U64(
1815855dc72bbd008ca475ba5853c67b0b173096de1asewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1816855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        - e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
18170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1818575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
1819478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            /* -- Max32U -- */
1820478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            case Iop_Max32U: {
1821478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj               UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1822478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj               UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1823478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj               UInt res  = u32a > u32b ? u32a : u32b;
1824478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj               e2 = IRExpr_Const(IRConst_U32(res));
1825478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj               break;
1826478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            }
1827478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj
1828855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Mul -- */
18290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Mul32:
18300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               e2 = IRExpr_Const(IRConst_U32(
18310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
18320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
18330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1834a34c071b549860710128356b8428ae4e368ef089sewardj            case Iop_Mul64:
1835a34c071b549860710128356b8428ae4e368ef089sewardj               e2 = IRExpr_Const(IRConst_U64(
1836a34c071b549860710128356b8428ae4e368ef089sewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1837a34c071b549860710128356b8428ae4e368ef089sewardj                        * e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));
1838a34c071b549860710128356b8428ae4e368ef089sewardj               break;
1839a34c071b549860710128356b8428ae4e368ef089sewardj
1840ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj            case Iop_MullS32: {
1841ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               /* very paranoid */
1842ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
1843ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1844ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               Int   s32a = (Int)u32a;
1845ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               Int   s32b = (Int)u32b;
1846ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               Long  s64a = (Long)s32a;
1847ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               Long  s64b = (Long)s32b;
1848ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               Long  sres = s64a * s64b;
1849ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               ULong ures = (ULong)sres;
1850ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               e2 = IRExpr_Const(IRConst_U64(ures));
1851ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj               break;
1852ea6bccb0dbc7a94b3475b951f5ebda3155a06f38sewardj            }
1853b095fba59bf2a23d574342f510d920127bda2c73sewardj
1854855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Shl -- */
18550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Shl32:
18560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
18570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
18580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               if (shift >= 0 && shift <= 31)
18590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  e2 = IRExpr_Const(IRConst_U32(
18600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
18610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                           << shift)));
18620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1863b095fba59bf2a23d574342f510d920127bda2c73sewardj            case Iop_Shl64:
1864b095fba59bf2a23d574342f510d920127bda2c73sewardj               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1865b095fba59bf2a23d574342f510d920127bda2c73sewardj               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1866b095fba59bf2a23d574342f510d920127bda2c73sewardj               if (shift >= 0 && shift <= 63)
1867b095fba59bf2a23d574342f510d920127bda2c73sewardj                  e2 = IRExpr_Const(IRConst_U64(
1868b095fba59bf2a23d574342f510d920127bda2c73sewardj                          (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1869b095fba59bf2a23d574342f510d920127bda2c73sewardj                           << shift)));
1870b095fba59bf2a23d574342f510d920127bda2c73sewardj               break;
1871b095fba59bf2a23d574342f510d920127bda2c73sewardj
1872855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Sar -- */
18730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Sar32: {
18740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               /* paranoid ... */
18750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               /*signed*/ Int s32;
18760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
18770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               s32   = (Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
18780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
18790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               if (shift >= 0 && shift <= 31) {
18800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  s32 >>=/*signed*/ shift;
18810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  e2 = IRExpr_Const(IRConst_U32((UInt)s32));
18820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               }
18830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
18840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            }
1885855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_Sar64: {
1886855dc72bbd008ca475ba5853c67b0b173096de1asewardj               /* paranoid ... */
1887855dc72bbd008ca475ba5853c67b0b173096de1asewardj               /*signed*/ Long s64;
1888855dc72bbd008ca475ba5853c67b0b173096de1asewardj               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
1889855dc72bbd008ca475ba5853c67b0b173096de1asewardj               s64   = (Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
1890855dc72bbd008ca475ba5853c67b0b173096de1asewardj               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
1891855dc72bbd008ca475ba5853c67b0b173096de1asewardj               if (shift >= 0 && shift <= 63) {
1892855dc72bbd008ca475ba5853c67b0b173096de1asewardj                  s64 >>=/*signed*/ shift;
1893855dc72bbd008ca475ba5853c67b0b173096de1asewardj                  e2 = IRExpr_Const(IRConst_U64((ULong)s64));
1894855dc72bbd008ca475ba5853c67b0b173096de1asewardj               }
1895855dc72bbd008ca475ba5853c67b0b173096de1asewardj               break;
1896855dc72bbd008ca475ba5853c67b0b173096de1asewardj            }
1897855dc72bbd008ca475ba5853c67b0b173096de1asewardj
1898855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- Shr -- */
18990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_Shr32: {
19000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               /* paranoid ... */
19014add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               /*unsigned*/ UInt u32;
19020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
19034add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               u32   = (UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32);
19040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
19050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               if (shift >= 0 && shift <= 31) {
19064add714eb0f3a8edb50c826a12d29912df75a7a8sewardj                  u32 >>=/*unsigned*/ shift;
19074add714eb0f3a8edb50c826a12d29912df75a7a8sewardj                  e2 = IRExpr_Const(IRConst_U32(u32));
19084add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               }
19094add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               break;
19104add714eb0f3a8edb50c826a12d29912df75a7a8sewardj            }
19114add714eb0f3a8edb50c826a12d29912df75a7a8sewardj            case Iop_Shr64: {
19124add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               /* paranoid ... */
19134add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               /*unsigned*/ ULong u64;
19144add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
19154add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               u64   = (ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64);
19164add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
19174add714eb0f3a8edb50c826a12d29912df75a7a8sewardj               if (shift >= 0 && shift <= 63) {
19184add714eb0f3a8edb50c826a12d29912df75a7a8sewardj                  u64 >>=/*unsigned*/ shift;
19194add714eb0f3a8edb50c826a12d29912df75a7a8sewardj                  e2 = IRExpr_Const(IRConst_U64(u64));
19200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               }
19210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
19220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            }
1923855dc72bbd008ca475ba5853c67b0b173096de1asewardj
1924855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- CmpEQ -- */
19250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpEQ32:
19269d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
19289d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
19290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1930855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_CmpEQ64:
1931855dc72bbd008ca475ba5853c67b0b173096de1asewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
1932855dc72bbd008ca475ba5853c67b0b173096de1asewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
1933855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        == e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
1934855dc72bbd008ca475ba5853c67b0b173096de1asewardj               break;
1935855dc72bbd008ca475ba5853c67b0b173096de1asewardj
1936855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- CmpNE -- */
1937855dc72bbd008ca475ba5853c67b0b173096de1asewardj            case Iop_CmpNE8:
1938e13074c2c1321d069fb95806bdce64f9a3512341sewardj            case Iop_CasCmpNE8:
1939e13074c2c1321d069fb95806bdce64f9a3512341sewardj            case Iop_ExpCmpNE8:
1940855dc72bbd008ca475ba5853c67b0b173096de1asewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
1941855dc72bbd008ca475ba5853c67b0b173096de1asewardj                       ((0xFF & e->Iex.Binop.arg1->Iex.Const.con->Ico.U8)
1942855dc72bbd008ca475ba5853c67b0b173096de1asewardj                        != (0xFF & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8)))));
1943855dc72bbd008ca475ba5853c67b0b173096de1asewardj               break;
19440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpNE32:
1945e13074c2c1321d069fb95806bdce64f9a3512341sewardj            case Iop_CasCmpNE32:
1946e13074c2c1321d069fb95806bdce64f9a3512341sewardj            case Iop_ExpCmpNE32:
19479d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
19499d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))));
19500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
19510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpNE64:
1952e13074c2c1321d069fb95806bdce64f9a3512341sewardj            case Iop_CasCmpNE64:
1953e13074c2c1321d069fb95806bdce64f9a3512341sewardj            case Iop_ExpCmpNE64:
19549d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64
19569d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        != e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))));
19570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
1958d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
1959855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- CmpLEU -- */
19600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpLE32U:
19619d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
19639d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        <= (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
19640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
19657f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            case Iop_CmpLE64U:
19667f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19677f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
19687f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                        <= (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
19697f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               break;
1970855dc72bbd008ca475ba5853c67b0b173096de1asewardj
1971855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- CmpLES -- */
19720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpLE32S:
19739d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
19759d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        <= (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
19760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
19777f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            case Iop_CmpLE64S:
19787f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19797f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
19807f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                        <= (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
19817f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               break;
1982d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
1983855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- CmpLTS -- */
19840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpLT32S:
19859d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
19879d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        < (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
19880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
19897f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            case Iop_CmpLT64S:
19907f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19917f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                       ((Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
19927f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                        < (Long)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
19937f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               break;
1994855dc72bbd008ca475ba5853c67b0b173096de1asewardj
1995855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- CmpLTU -- */
19960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_CmpLT32U:
19979d2e769a9368d2b22c32a4764a70e9da38769628sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
19980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)
19999d2e769a9368d2b22c32a4764a70e9da38769628sewardj                        < (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))));
20000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
20017f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj            case Iop_CmpLT64U:
20027f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               e2 = IRExpr_Const(IRConst_U1(toBool(
20037f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                       ((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64)
20047f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj                        < (ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))));
20057f6330dbf0608dcc395ec49e66c25f7ad03a8c60sewardj               break;
20062963239357452b96dbe6de1b3f8b626ea3305780sewardj
2007b51f0f4f33256638ed953156a2635aa739b232f1sewardj            /* -- CmpORD -- */
2008b51f0f4f33256638ed953156a2635aa739b232f1sewardj            case Iop_CmpORD32S: {
2009b51f0f4f33256638ed953156a2635aa739b232f1sewardj               /* very paranoid */
2010b51f0f4f33256638ed953156a2635aa739b232f1sewardj               UInt  u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32;
2011b51f0f4f33256638ed953156a2635aa739b232f1sewardj               UInt  u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
2012b51f0f4f33256638ed953156a2635aa739b232f1sewardj               Int   s32a = (Int)u32a;
2013b51f0f4f33256638ed953156a2635aa739b232f1sewardj               Int   s32b = (Int)u32b;
2014b51f0f4f33256638ed953156a2635aa739b232f1sewardj               Int   r = 0x2; /* EQ */
2015b51f0f4f33256638ed953156a2635aa739b232f1sewardj               if (s32a < s32b) {
2016b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  r = 0x8; /* LT */
2017b51f0f4f33256638ed953156a2635aa739b232f1sewardj               }
2018b51f0f4f33256638ed953156a2635aa739b232f1sewardj               else if (s32a > s32b) {
2019b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  r = 0x4; /* GT */
2020b51f0f4f33256638ed953156a2635aa739b232f1sewardj               }
2021b51f0f4f33256638ed953156a2635aa739b232f1sewardj               e2 = IRExpr_Const(IRConst_U32(r));
2022b51f0f4f33256638ed953156a2635aa739b232f1sewardj               break;
2023b51f0f4f33256638ed953156a2635aa739b232f1sewardj            }
2024b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2025855dc72bbd008ca475ba5853c67b0b173096de1asewardj            /* -- nHLto2n -- */
20260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            case Iop_32HLto64:
20270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               e2 = IRExpr_Const(IRConst_U64(
20284a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                       (((ULong)(e->Iex.Binop.arg1
20294a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                                  ->Iex.Const.con->Ico.U32)) << 32)
20300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       | ((ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))
20310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    ));
20320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               break;
20333bc8a59c12554ebd3abdb04c2417e0077054f936sewardj            case Iop_64HLto128:
20343bc8a59c12554ebd3abdb04c2417e0077054f936sewardj               /* We can't fold this, because there is no way to
20353bc8a59c12554ebd3abdb04c2417e0077054f936sewardj                  express he result in IR, but at least pretend to
20363bc8a59c12554ebd3abdb04c2417e0077054f936sewardj                  handle it, so as to stop getting blasted with
20373bc8a59c12554ebd3abdb04c2417e0077054f936sewardj                  no-rule-for-this-primop messages. */
20383bc8a59c12554ebd3abdb04c2417e0077054f936sewardj               break;
20394a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            /* For this vector one, can't fold all cases, but at
20404a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               least do the most obvious one.  Could do better here
20414a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               using summarise/desummarise of vector constants, but
20424a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               too difficult to verify; hence just handle the zero
20434a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               cases. */
20444a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_64HLtoV128: {
20454a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               ULong argHi = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64;
20464a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               ULong argLo = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64;
20474a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               if (0 == argHi && 0 == argLo) {
20484a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                  e2 = IRExpr_Const(IRConst_V128(0));
20494a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               } else {
20504a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                  goto unhandled;
20514a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               }
20524a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               break;
20534a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            }
20549571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj            /* Same reasoning for the 256-bit version. */
20559571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj            case Iop_V128HLtoV256: {
20569571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               IRExpr* argHi = e->Iex.Binop.arg1;
20579571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               IRExpr* argLo = e->Iex.Binop.arg2;
20589571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               if (isZeroV128(argHi) && isZeroV128(argLo)) {
20599571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  e2 = IRExpr_Const(IRConst_V256(0));
20609571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               } else {
20619571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  goto unhandled;
20629571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               }
20639571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               break;
20649571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj            }
20654a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj
20664a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            /* -- V128 stuff -- */
20674a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_InterleaveLO8x16: {
20684a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               /* This turns up a lot in Memcheck instrumentation of
20694a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                  Icc generated code.  I don't know why. */
20704a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               UShort arg1 =  e->Iex.Binop.arg1->Iex.Const.con->Ico.V128;
20714a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               UShort arg2 =  e->Iex.Binop.arg2->Iex.Const.con->Ico.V128;
20724a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               if (0 == arg1 && 0 == arg2) {
20734a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                  e2 = IRExpr_Const(IRConst_V128(0));
20744a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               } else {
20754a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                  goto unhandled;
20764a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               }
20774a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               break;
20784a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            }
2079855dc72bbd008ca475ba5853c67b0b173096de1asewardj
20800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            default:
20810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               goto unhandled;
20820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
2083f0e431671cb877601c2f2e551f42246469b4ee62sewardj
20840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      } else {
2085d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
20860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* other cases (identities, etc) */
208764d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj         switch (e->Iex.Binop.op) {
2088f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2089f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Shl32:
2090f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Shl64:
2091f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Shr64:
2092b979d7a9fd0fd7cb3b71de211584ea662f4fa140sewardj            case Iop_Sar64:
2093b979d7a9fd0fd7cb3b71de211584ea662f4fa140sewardj               /* Shl32/Shl64/Shr64/Sar64(x,0) ==> x */
2094f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg2)) {
2095f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2096f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2097f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2098f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* Shl32/Shl64/Shr64(0,x) ==> 0 */
2099f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg1)) {
2100f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2101f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2102f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2103f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
2104f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2105b979d7a9fd0fd7cb3b71de211584ea662f4fa140sewardj            case Iop_Sar32:
2106f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Shr32:
2107b979d7a9fd0fd7cb3b71de211584ea662f4fa140sewardj               /* Shr32/Sar32(x,0) ==> x */
2108f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg2)) {
2109f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2110f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2111f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2112f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
2113f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2114f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Or8:
2115f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Or16:
2116f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Or32:
2117f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Or64:
211864d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj            case Iop_Max32U:
2119cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               /* Or8/Or16/Or32/Or64/Max32U(x,0) ==> x */
2120f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg2)) {
2121f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2122f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2123f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2124cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               /* Or8/Or16/Or32/Or64/Max32U(0,x) ==> x */
2125f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg1)) {
2126f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg2;
2127f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2128f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2129cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               /* Or8/Or16/Or32/Or64/Max32U(x,1---1b) ==> 1---1b */
2130cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               /* Or8/Or16/Or32/Or64/Max32U(1---1b,x) ==> 1---1b */
2131cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               if (isOnesU(e->Iex.Binop.arg1) || isOnesU(e->Iex.Binop.arg2)) {
2132cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
2133cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj                  break;
2134cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               }
2135cf4be4a70cb7393839b68fad19e3660e2c053b57sewardj               /* Or8/Or16/Or32/Or64/Max32U(t,t) ==> t, for some IRTemp t */
2136cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
213764d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj                  e2 = e->Iex.Binop.arg1;
2138f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2139f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
214064d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj               break;
2141f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2142f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Add8:
2143f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* Add8(t,t) ==> t << 1.
2144f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  Memcheck doesn't understand that
2145f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  x+x produces a defined least significant bit, and it seems
2146f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  simplest just to get rid of the problem by rewriting it
2147f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  out, since the opportunity to do so exists. */
2148cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2149f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = IRExpr_Binop(Iop_Shl8, e->Iex.Binop.arg1,
2150f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                                    IRExpr_Const(IRConst_U8(1)));
2151f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2152f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
215364d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj               break;
2154d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
2155f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* NB no Add16(t,t) case yet as no known test case exists */
2156f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2157f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Add32:
2158f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Add64:
2159f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* Add32/Add64(x,0) ==> x */
2160f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg2)) {
2161f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2162f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2163f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2164f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* Add32/Add64(0,x) ==> x */
2165f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               if (isZeroU(e->Iex.Binop.arg1)) {
2166f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg2;
2167f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2168f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2169f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* Add32/Add64(t,t) ==> t << 1. Same rationale as for Add8. */
2170cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
21716399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                  e2 = IRExpr_Binop(
21726399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                          e->Iex.Binop.op == Iop_Add32 ? Iop_Shl32 : Iop_Shl64,
21736399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                          e->Iex.Binop.arg1, IRExpr_Const(IRConst_U8(1)));
2174f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2175f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2176f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
2177f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
21781beb4330bdbd49e1a162734d5eb1b2ec6f6cbf04sewardj            case Iop_Sub32:
2179f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Sub64:
21801beb4330bdbd49e1a162734d5eb1b2ec6f6cbf04sewardj               /* Sub32/Sub64(x,0) ==> x */
21811beb4330bdbd49e1a162734d5eb1b2ec6f6cbf04sewardj               if (isZeroU(e->Iex.Binop.arg2)) {
2182f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2183f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2184f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
21851beb4330bdbd49e1a162734d5eb1b2ec6f6cbf04sewardj               /* Sub32/Sub64(t,t) ==> 0, for some IRTemp t */
2186cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2187f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2188f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2189f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2190f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
219136a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj            case Iop_Sub8x16:
219236a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj               /* Sub8x16(x,0) ==> x */
219336a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj               if (isZeroV128(e->Iex.Binop.arg2)) {
219436a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                  e2 = e->Iex.Binop.arg1;
219536a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                  break;
219636a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj               }
219736a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj               break;
2198f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
21992782d2143d385935418ce42aa5754fd6a97e9692florian            case Iop_And8:
22002782d2143d385935418ce42aa5754fd6a97e9692florian            case Iop_And16:
2201f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_And32:
22022782d2143d385935418ce42aa5754fd6a97e9692florian            case Iop_And64:
22032782d2143d385935418ce42aa5754fd6a97e9692florian               /* And8/And16/And32/And64(x,1---1b) ==> x */
220455ce7b748cd0c8534865844f219685fdb8e96e59florian               if (isOnesU(e->Iex.Binop.arg2)) {
2205f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2206f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2207f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
22082782d2143d385935418ce42aa5754fd6a97e9692florian               /* And8/And16/And32/And64(1---1b,x) ==> x */
22092782d2143d385935418ce42aa5754fd6a97e9692florian               if (isOnesU(e->Iex.Binop.arg1)) {
22102782d2143d385935418ce42aa5754fd6a97e9692florian                  e2 = e->Iex.Binop.arg2;
22112782d2143d385935418ce42aa5754fd6a97e9692florian                  break;
22122782d2143d385935418ce42aa5754fd6a97e9692florian               }
22132782d2143d385935418ce42aa5754fd6a97e9692florian               /* And8/And16/And32/And64(x,0) ==> 0 */
221455ce7b748cd0c8534865844f219685fdb8e96e59florian               if (isZeroU(e->Iex.Binop.arg2)) {
2215f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg2;
2216f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2217f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
22182782d2143d385935418ce42aa5754fd6a97e9692florian               /* And8/And16/And32/And64(0,x) ==> 0 */
221955ce7b748cd0c8534865844f219685fdb8e96e59florian               if (isZeroU(e->Iex.Binop.arg1)) {
2220f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2221f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2222f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
22232782d2143d385935418ce42aa5754fd6a97e9692florian               /* And8/And16/And32/And64(t,t) ==> t, for some IRTemp t */
2224cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2225f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2226f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2227f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2228f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
2229f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
22304a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_AndV128:
22314a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_AndV256:
223255ce7b748cd0c8534865844f219685fdb8e96e59florian               /* And8/And16/AndV128/AndV256(t,t)
22334a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj                  ==> t, for some IRTemp t */
2234cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2235f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2236f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2237f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
223836a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj               /* Deal with either arg zero.  Could handle other And
223936a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                  cases here too. */
22401b7c4719bc445c8e71230e58e62050d67aaf0109florian               if (e->Iex.Binop.op == Iop_AndV256
22411b7c4719bc445c8e71230e58e62050d67aaf0109florian                   && (isZeroV256(e->Iex.Binop.arg1)
22421b7c4719bc445c8e71230e58e62050d67aaf0109florian                       || isZeroV256(e->Iex.Binop.arg2))) {
2243bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj                  e2 =  mkZeroOfPrimopResultType(e->Iex.Binop.op);
2244bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj                  break;
224536a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj               } else if (e->Iex.Binop.op == Iop_AndV128
224636a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                          && (isZeroV128(e->Iex.Binop.arg1)
224736a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                              || isZeroV128(e->Iex.Binop.arg2))) {
224836a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                  e2 =  mkZeroOfPrimopResultType(e->Iex.Binop.op);
224936a911a8167a49ed3b3c5da4cd8344dfe18acf1dsewardj                  break;
2250bbcf188f6ae64a44fb31414eb9e1a738b4befcc0sewardj               }
2251f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
2252f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2253f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_OrV128:
22544a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj            case Iop_OrV256:
22554a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj               /* V128/V256(t,t) ==> t, for some IRTemp t */
2256cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2257f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = e->Iex.Binop.arg1;
2258f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2259f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
22609571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               /* OrV128(t,0) ==> t */
22619571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               if (e->Iex.Binop.op == Iop_OrV128) {
22629571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  if (isZeroV128(e->Iex.Binop.arg2)) {
22639571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                     e2 = e->Iex.Binop.arg1;
22649571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                     break;
22659571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  }
22669571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  if (isZeroV128(e->Iex.Binop.arg1)) {
22679571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                     e2 = e->Iex.Binop.arg2;
22689571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                     break;
22699571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  }
22709571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               }
22719571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               /* OrV256(t,0) ==> t */
22729571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               if (e->Iex.Binop.op == Iop_OrV256) {
22739571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  if (isZeroV256(e->Iex.Binop.arg2)) {
22749571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                     e2 = e->Iex.Binop.arg1;
22759571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                     break;
22769571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  }
22779571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  //Disabled because there's no known test case right now.
22789571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  //if (isZeroV256(e->Iex.Binop.arg1)) {
22799571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  //   e2 = e->Iex.Binop.arg2;
22809571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  //   break;
22819571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj                  //}
22829571dc05739e7980539cfd9dbc4e9ca19324e6d6sewardj               }
2283f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               break;
2284f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2285f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Xor8:
2286f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Xor16:
2287f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Xor32:
2288f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian            case Iop_Xor64:
228964d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj            case Iop_XorV128:
229070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case Iop_XorV256:
2291f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               /* Xor8/16/32/64/V128(t,t) ==> 0, for some IRTemp t */
2292cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
229364d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2294f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2295f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2296b01ff4034e82ba4e57ab417af9a79742dc522934sewardj               /* XorV128(t,0) ==> t */
2297b01ff4034e82ba4e57ab417af9a79742dc522934sewardj               if (e->Iex.Binop.op == Iop_XorV128) {
2298b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  if (isZeroV128(e->Iex.Binop.arg2)) {
2299b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                     e2 = e->Iex.Binop.arg1;
2300b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                     break;
2301b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  }
2302b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  //Disabled because there's no known test case right now.
2303b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  //if (isZeroV128(e->Iex.Binop.arg1)) {
2304b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  //   e2 = e->Iex.Binop.arg2;
2305b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  //   break;
2306b01ff4034e82ba4e57ab417af9a79742dc522934sewardj                  //}
23079e2a0080120557075fcf84237bd4cf7f257911e9sewardj               } else {
23089e2a0080120557075fcf84237bd4cf7f257911e9sewardj                  /* Xor8/16/32/64(0,t) ==> t */
23099e2a0080120557075fcf84237bd4cf7f257911e9sewardj                  if (isZeroU(e->Iex.Binop.arg1)) {
23109e2a0080120557075fcf84237bd4cf7f257911e9sewardj                     e2 = e->Iex.Binop.arg2;
23119e2a0080120557075fcf84237bd4cf7f257911e9sewardj                     break;
23129e2a0080120557075fcf84237bd4cf7f257911e9sewardj                  }
23139e2a0080120557075fcf84237bd4cf7f257911e9sewardj                  /* Xor8/16/32/64(t,0) ==> t */
23149e2a0080120557075fcf84237bd4cf7f257911e9sewardj                  if (isZeroU(e->Iex.Binop.arg2)) {
23159e2a0080120557075fcf84237bd4cf7f257911e9sewardj                     e2 = e->Iex.Binop.arg1;
23169e2a0080120557075fcf84237bd4cf7f257911e9sewardj                     break;
23179e2a0080120557075fcf84237bd4cf7f257911e9sewardj                  }
2318b01ff4034e82ba4e57ab417af9a79742dc522934sewardj               }
231964d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj               break;
2320f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
2321a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj            case Iop_CmpNE32:
23221beb4330bdbd49e1a162734d5eb1b2ec6f6cbf04sewardj               /* CmpNE32(t,t) ==> 0, for some IRTemp t */
2323cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
2324f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  e2 = mkZeroOfPrimopResultType(e->Iex.Binop.op);
2325f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2326f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
2327009230b9758291b594e60d7c0243a73d53e81854sewardj               /* CmpNE32(1Uto32(b), 0) ==> b */
2328009230b9758291b594e60d7c0243a73d53e81854sewardj               if (isZeroU32(e->Iex.Binop.arg2)) {
2329009230b9758291b594e60d7c0243a73d53e81854sewardj                  IRExpr* a1 = chase(env, e->Iex.Binop.arg1);
2330009230b9758291b594e60d7c0243a73d53e81854sewardj                  if (a1 && a1->tag == Iex_Unop
2331009230b9758291b594e60d7c0243a73d53e81854sewardj                         && a1->Iex.Unop.op == Iop_1Uto32) {
2332009230b9758291b594e60d7c0243a73d53e81854sewardj                     e2 = a1->Iex.Unop.arg;
2333009230b9758291b594e60d7c0243a73d53e81854sewardj                     break;
2334009230b9758291b594e60d7c0243a73d53e81854sewardj                  }
2335009230b9758291b594e60d7c0243a73d53e81854sewardj               }
233664d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj               break;
233764d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj
2338a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj            case Iop_CmpEQ32:
233964d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj            case Iop_CmpEQ64:
234064d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj            case Iop_CmpEQ8x8:
234164d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj            case Iop_CmpEQ8x16:
2342899d1838d6fd60b141a3d808b02dc04be5901681sewardj            case Iop_CmpEQ16x8:
2343ffccf2be3406c1344706d0fe7ae57e1c3998e6cdsewardj            case Iop_CmpEQ32x4:
2344cdb5feebd7e817c8207471ef734b43c51c14dee3florian               if (sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
234564d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj                  e2 = mkOnesOfPrimopResultType(e->Iex.Binop.op);
2346f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian                  break;
2347f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian               }
234864d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj               break;
2349f6402ab3a43ec0eb821b4612a9bc8bae34f04dfaflorian
235064d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj            default:
235164d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj               break;
23520033ddccac6f90789fe2e78e86b8a649931d77b4sewardj         }
2353d721703a7a904a66c49d0e6318c184d0076b40b0sewardj      }
2354708417d56d1798ffd62a05b7932da47cdc3d3337florian      break;
2355708417d56d1798ffd62a05b7932da47cdc3d3337florian
235699dd03e04a6914d90d5fee727d61d76905334becflorian   case Iex_ITE:
235799dd03e04a6914d90d5fee727d61d76905334becflorian      /* ITE */
23586c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /* is the discriminant is a constant? */
235999dd03e04a6914d90d5fee727d61d76905334becflorian      if (e->Iex.ITE.cond->tag == Iex_Const) {
23606c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* assured us by the IR type rules */
236199dd03e04a6914d90d5fee727d61d76905334becflorian         vassert(e->Iex.ITE.cond->Iex.Const.con->tag == Ico_U1);
236299dd03e04a6914d90d5fee727d61d76905334becflorian         e2 = e->Iex.ITE.cond->Iex.Const.con->Ico.U1
236399dd03e04a6914d90d5fee727d61d76905334becflorian                 ? e->Iex.ITE.iftrue : e->Iex.ITE.iffalse;
23646c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
23656c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      else
23666c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /* are the arms identical? (pretty weedy test) */
236799dd03e04a6914d90d5fee727d61d76905334becflorian      if (sameIRExprs(env, e->Iex.ITE.iftrue,
236899dd03e04a6914d90d5fee727d61d76905334becflorian                           e->Iex.ITE.iffalse)) {
236999dd03e04a6914d90d5fee727d61d76905334becflorian         e2 = e->Iex.ITE.iffalse;
23706c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2371708417d56d1798ffd62a05b7932da47cdc3d3337florian      break;
2372708417d56d1798ffd62a05b7932da47cdc3d3337florian
2373708417d56d1798ffd62a05b7932da47cdc3d3337florian   default:
2374708417d56d1798ffd62a05b7932da47cdc3d3337florian      /* not considered */
2375708417d56d1798ffd62a05b7932da47cdc3d3337florian      break;
23760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
2377d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
2378a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   /* Show cases where we've found but not folded 'op(t,t)'.  Be
2379a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      careful not to call sameIRExprs with values of different types,
2380a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      though, else it will assert (and so it should!).  We can't
2381a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      conveniently call typeOfIRExpr on the two args without a whole
2382a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      bunch of extra plumbing to pass in a type env, so just use a
2383a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      hacky test to check the arguments are not anything that might
2384a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      sameIRExprs to assert.  This is only OK because this kludge is
2385a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      only used for debug printing, not for "real" operation.  For
2386a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      "real" operation (ie, all other calls to sameIRExprs), it is
2387a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      essential that the to args have the same type.
2388a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj
2389a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      The "right" solution is to plumb the containing block's
2390a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      IRTypeEnv through to here and use typeOfIRExpr to be sure.  But
2391a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      that's a bunch of extra parameter passing which will just slow
2392a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj      down the normal case, for no purpose. */
2393a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj   if (vex_control.iropt_verbosity > 0
2394a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj       && e == e2
2395a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj       && e->tag == Iex_Binop
2396a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj       && !debug_only_hack_sameIRExprs_might_assert(e->Iex.Binop.arg1,
2397a7e963847c4ceaf45d246a4a2e5982ea1f273ff4sewardj                                                    e->Iex.Binop.arg2)
2398cdb5feebd7e817c8207471ef734b43c51c14dee3florian       && sameIRExprs(env, e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
23994a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj      vex_printf("vex iropt: fold_Expr: no ident rule for: ");
24004a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj      ppIRExpr(e);
24014a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj      vex_printf("\n");
240264d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj   }
240364d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj
240464d776c37f5dcb3475b0ca99aaafa448ba98b717sewardj   /* Show the overall results of folding. */
24050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (DEBUG_IROPT && e2 != e) {
24060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf("FOLD: ");
24070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      ppIRExpr(e); vex_printf("  ->  ");
24080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      ppIRExpr(e2); vex_printf("\n");
24090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
2410d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
24110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return e2;
2412f0e431671cb877601c2f2e551f42246469b4ee62sewardj
24130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj unhandled:
24140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  if 0
24150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vex_printf("\n\n");
24160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   ppIRExpr(e);
24170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vpanic("fold_Expr: no rule for the above");
24180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  else
2419328b54be1d7eeb46108a2116b6d5643b5aa72627sewardj   if (vex_control.iropt_verbosity > 0) {
24204a0bee01373f2ff1d0a915d30dd4f93bbd9729f9sewardj      vex_printf("vex iropt: fold_Expr: no const rule for: ");
2421328b54be1d7eeb46108a2116b6d5643b5aa72627sewardj      ppIRExpr(e);
2422328b54be1d7eeb46108a2116b6d5643b5aa72627sewardj      vex_printf("\n");
2423328b54be1d7eeb46108a2116b6d5643b5aa72627sewardj   }
24240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return e2;
24250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  endif
24260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
2427f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2428044a215317abdd84dd7224a416595c43eedc96d3sewardj
24290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Apply the subst to a simple 1-level expression -- guaranteed to be
24300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   1-level due to previous flattening pass. */
2431f0e431671cb877601c2f2e551f42246469b4ee62sewardj
24320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex )
24330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
24340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (ex->tag) {
2435dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp:
2436dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (env[(Int)ex->Iex.RdTmp.tmp] != NULL) {
2437cdb5feebd7e817c8207471ef734b43c51c14dee3florian            IRExpr *rhs = env[(Int)ex->Iex.RdTmp.tmp];
2438cdb5feebd7e817c8207471ef734b43c51c14dee3florian            if (rhs->tag == Iex_RdTmp)
2439cdb5feebd7e817c8207471ef734b43c51c14dee3florian               return rhs;
2440cdb5feebd7e817c8207471ef734b43c51c14dee3florian            if (rhs->tag == Iex_Const
2441cdb5feebd7e817c8207471ef734b43c51c14dee3florian                && rhs->Iex.Const.con->tag != Ico_F64i)
2442cdb5feebd7e817c8207471ef734b43c51c14dee3florian               return rhs;
2443f0e431671cb877601c2f2e551f42246469b4ee62sewardj         }
2444cdb5feebd7e817c8207471ef734b43c51c14dee3florian         /* not bound in env */
2445cdb5feebd7e817c8207471ef734b43c51c14dee3florian         return ex;
244617442fe8094d0f82266e5a05509f62cac8f7539esewardj
24470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Const:
24480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Get:
24490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return ex;
2450f0e431671cb877601c2f2e551f42246469b4ee62sewardj
24510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_GetI:
2452496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(ex->Iex.GetI.ix));
24530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_GetI(
24540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ex->Iex.GetI.descr,
24550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            subst_Expr(env, ex->Iex.GetI.ix),
24560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ex->Iex.GetI.bias
24570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         );
2458cf1ea9c5ba5ae88b1f64345631b738959ab1c7f6sewardj
245996d7cc3e7d54ad5af2af2821223b21f9a8516a59florian      case Iex_Qop: {
246096d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         IRQop* qop = ex->Iex.Qop.details;
246196d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         vassert(isIRAtom(qop->arg1));
246296d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         vassert(isIRAtom(qop->arg2));
246396d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         vassert(isIRAtom(qop->arg3));
246496d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         vassert(isIRAtom(qop->arg4));
246540c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         return IRExpr_Qop(
246696d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   qop->op,
246796d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   subst_Expr(env, qop->arg1),
246896d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   subst_Expr(env, qop->arg2),
246996d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   subst_Expr(env, qop->arg3),
247096d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   subst_Expr(env, qop->arg4)
247140c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                );
247296d7cc3e7d54ad5af2af2821223b21f9a8516a59florian      }
247340c802659108a96bb87cbc1a30b7b77e2abd0829sewardj
2474420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian      case Iex_Triop: {
2475420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         IRTriop* triop = ex->Iex.Triop.details;
2476420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         vassert(isIRAtom(triop->arg1));
2477420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         vassert(isIRAtom(triop->arg2));
2478420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         vassert(isIRAtom(triop->arg3));
2479b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         return IRExpr_Triop(
2480420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   triop->op,
2481420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   subst_Expr(env, triop->arg1),
2482420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   subst_Expr(env, triop->arg2),
2483420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   subst_Expr(env, triop->arg3)
2484b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                );
2485420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian      }
2486b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
24870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Binop:
2488496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(ex->Iex.Binop.arg1));
2489496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(ex->Iex.Binop.arg2));
24900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_Binop(
24910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   ex->Iex.Binop.op,
24920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   subst_Expr(env, ex->Iex.Binop.arg1),
24930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   subst_Expr(env, ex->Iex.Binop.arg2)
24940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
2495044a215317abdd84dd7224a416595c43eedc96d3sewardj
24960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Unop:
2497496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(ex->Iex.Unop.arg));
24980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_Unop(
24990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   ex->Iex.Unop.op,
25000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   subst_Expr(env, ex->Iex.Unop.arg)
25010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
25020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
2503af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Iex_Load:
2504af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(ex->Iex.Load.addr));
2505af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         return IRExpr_Load(
2506af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   ex->Iex.Load.end,
2507af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   ex->Iex.Load.ty,
2508af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   subst_Expr(env, ex->Iex.Load.addr)
25090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
25100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
25110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_CCall: {
25120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         Int      i;
2513dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         IRExpr** args2 = shallowCopyIRExprVec(ex->Iex.CCall.args);
25140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (i = 0; args2[i]; i++) {
2515496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj            vassert(isIRAtom(args2[i]));
25160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            args2[i] = subst_Expr(env, args2[i]);
25178d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj         }
25180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_CCall(
25190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   ex->Iex.CCall.cee,
25200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   ex->Iex.CCall.retty,
25210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   args2
25220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
2523044a215317abdd84dd7224a416595c43eedc96d3sewardj      }
25248d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj
252599dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
252699dd03e04a6914d90d5fee727d61d76905334becflorian         vassert(isIRAtom(ex->Iex.ITE.cond));
252799dd03e04a6914d90d5fee727d61d76905334becflorian         vassert(isIRAtom(ex->Iex.ITE.iftrue));
252899dd03e04a6914d90d5fee727d61d76905334becflorian         vassert(isIRAtom(ex->Iex.ITE.iffalse));
252999dd03e04a6914d90d5fee727d61d76905334becflorian         return IRExpr_ITE(
253099dd03e04a6914d90d5fee727d61d76905334becflorian                   subst_Expr(env, ex->Iex.ITE.cond),
253199dd03e04a6914d90d5fee727d61d76905334becflorian                   subst_Expr(env, ex->Iex.ITE.iftrue),
253299dd03e04a6914d90d5fee727d61d76905334becflorian                   subst_Expr(env, ex->Iex.ITE.iffalse)
25330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
25340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
25350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
25360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n\n"); ppIRExpr(ex);
25370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("subst_Expr");
25380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
25390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
2540f0e431671cb877601c2f2e551f42246469b4ee62sewardj}
2541f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2542f0e431671cb877601c2f2e551f42246469b4ee62sewardj
25430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Apply the subst to stmt, then fold the result as much as possible.
2544d2445f60726580b450eca68ab40c568f9df338e2sewardj   Much simplified due to stmt being previously flattened.  As a
2545d2445f60726580b450eca68ab40c568f9df338e2sewardj   result of this, the stmt may wind up being turned into a no-op.
2546d2445f60726580b450eca68ab40c568f9df338e2sewardj*/
25470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
25480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
25490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  if 0
25500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vex_printf("\nsubst and fold stmt\n");
25510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   ppIRStmt(st);
25520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vex_printf("\n");
25530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  endif
2554f0e431671cb877601c2f2e551f42246469b4ee62sewardj
25550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (st->tag) {
25565a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
25575a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         vassert(isIRAtom(st->Ist.AbiHint.base));
2558478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         vassert(isIRAtom(st->Ist.AbiHint.nia));
25595a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         return IRStmt_AbiHint(
2560cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.base)),
2561478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                   st->Ist.AbiHint.len,
2562cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.AbiHint.nia))
25635a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj                );
25640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Put:
2565496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(st->Ist.Put.data));
25660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRStmt_Put(
25670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   st->Ist.Put.offset,
2568cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.Put.data))
25690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
2570f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2571d6f38b3f822f7d57adfc0da3410995d85d6a4597florian      case Ist_PutI: {
2572d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         IRPutI *puti, *puti2;
2573d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         puti = st->Ist.PutI.details;
2574d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         vassert(isIRAtom(puti->ix));
2575d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         vassert(isIRAtom(puti->data));
2576d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         puti2 = mkIRPutI(puti->descr,
2577d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                          fold_Expr(env, subst_Expr(env, puti->ix)),
2578d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                          puti->bias,
2579d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                          fold_Expr(env, subst_Expr(env, puti->data)));
2580d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         return IRStmt_PutI(puti2);
2581d6f38b3f822f7d57adfc0da3410995d85d6a4597florian      }
2582f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2583dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
2584dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         /* This is the one place where an expr (st->Ist.WrTmp.data) is
25850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            allowed to be more than just a constant or a tmp. */
2586dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRStmt_WrTmp(
2587dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                   st->Ist.WrTmp.tmp,
2588cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.WrTmp.data))
25890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
2590f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2591af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
2592af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(st->Ist.Store.addr));
2593af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(st->Ist.Store.data));
2594af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         return IRStmt_Store(
2595af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   st->Ist.Store.end,
2596cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.Store.addr)),
2597cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.Store.data))
25980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
2599f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2600cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG: {
2601cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRStoreG* sg = st->Ist.StoreG.details;
2602cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(sg->addr));
2603cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(sg->data));
2604cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(sg->guard));
2605cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRExpr* faddr  = fold_Expr(env, subst_Expr(env, sg->addr));
2606cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRExpr* fdata  = fold_Expr(env, subst_Expr(env, sg->data));
2607cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRExpr* fguard = fold_Expr(env, subst_Expr(env, sg->guard));
2608cfe046e178666280b87da998b1b52ecda03ecd89sewardj         if (fguard->tag == Iex_Const) {
2609cfe046e178666280b87da998b1b52ecda03ecd89sewardj            /* The condition on this store has folded down to a constant. */
2610cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(fguard->Iex.Const.con->tag == Ico_U1);
2611cfe046e178666280b87da998b1b52ecda03ecd89sewardj            if (fguard->Iex.Const.con->Ico.U1 == False) {
2612cfe046e178666280b87da998b1b52ecda03ecd89sewardj               return IRStmt_NoOp();
2613cfe046e178666280b87da998b1b52ecda03ecd89sewardj            } else {
2614cfe046e178666280b87da998b1b52ecda03ecd89sewardj               vassert(fguard->Iex.Const.con->Ico.U1 == True);
2615cfe046e178666280b87da998b1b52ecda03ecd89sewardj               return IRStmt_Store(sg->end, faddr, fdata);
2616cfe046e178666280b87da998b1b52ecda03ecd89sewardj            }
2617cfe046e178666280b87da998b1b52ecda03ecd89sewardj         }
2618cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return IRStmt_StoreG(sg->end, faddr, fdata, fguard);
2619cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
2620cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2621cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG: {
2622cfe046e178666280b87da998b1b52ecda03ecd89sewardj         /* This is complicated.  If the guard folds down to 'false',
2623cfe046e178666280b87da998b1b52ecda03ecd89sewardj            we can replace it with an assignment 'dst := alt', but if
2624cfe046e178666280b87da998b1b52ecda03ecd89sewardj            the guard folds down to 'true', we can't conveniently
2625cfe046e178666280b87da998b1b52ecda03ecd89sewardj            replace it with an unconditional load, because doing so
2626cfe046e178666280b87da998b1b52ecda03ecd89sewardj            requires generating a new temporary, and that is not easy
2627cfe046e178666280b87da998b1b52ecda03ecd89sewardj            to do at this point. */
2628cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRLoadG* lg = st->Ist.LoadG.details;
2629cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(lg->addr));
2630cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(lg->alt));
2631cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vassert(isIRAtom(lg->guard));
2632cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRExpr* faddr  = fold_Expr(env, subst_Expr(env, lg->addr));
2633cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRExpr* falt   = fold_Expr(env, subst_Expr(env, lg->alt));
2634cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRExpr* fguard = fold_Expr(env, subst_Expr(env, lg->guard));
2635cfe046e178666280b87da998b1b52ecda03ecd89sewardj         if (fguard->tag == Iex_Const) {
2636cfe046e178666280b87da998b1b52ecda03ecd89sewardj            /* The condition on this load has folded down to a constant. */
2637cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(fguard->Iex.Const.con->tag == Ico_U1);
2638cfe046e178666280b87da998b1b52ecda03ecd89sewardj            if (fguard->Iex.Const.con->Ico.U1 == False) {
2639cfe046e178666280b87da998b1b52ecda03ecd89sewardj               /* The load is not going to happen -- instead 'alt' is
2640cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  assigned to 'dst'.  */
2641cfe046e178666280b87da998b1b52ecda03ecd89sewardj               return IRStmt_WrTmp(lg->dst, falt);
2642cfe046e178666280b87da998b1b52ecda03ecd89sewardj            } else {
2643cfe046e178666280b87da998b1b52ecda03ecd89sewardj               vassert(fguard->Iex.Const.con->Ico.U1 == True);
2644cfe046e178666280b87da998b1b52ecda03ecd89sewardj               /* The load is always going to happen.  We want to
2645cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  convert to an unconditional load and assign to 'dst'
2646cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  (IRStmt_WrTmp).  Problem is we need an extra temp to
2647cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  hold the loaded value, but none is available.
2648cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  Instead, reconstitute the conditional load (with
2649cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  folded args, of course) and let the caller of this
2650cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  routine deal with the problem. */
2651cfe046e178666280b87da998b1b52ecda03ecd89sewardj            }
2652cfe046e178666280b87da998b1b52ecda03ecd89sewardj         }
2653cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return IRStmt_LoadG(lg->end, lg->cvt, lg->dst, faddr, falt, fguard);
2654cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
2655cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2656e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS: {
2657e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRCAS *cas, *cas2;
2658e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas = st->Ist.CAS.details;
2659e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vassert(isIRAtom(cas->addr));
2660e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
2661e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vassert(isIRAtom(cas->expdLo));
2662e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
2663e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vassert(isIRAtom(cas->dataLo));
2664e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas2 = mkIRCAS(
2665e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   cas->oldHi, cas->oldLo, cas->end,
2666cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, cas->addr)),
26676399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                   cas->expdHi ? fold_Expr(env, subst_Expr(env, cas->expdHi))
26686399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                               : NULL,
2669cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, cas->expdLo)),
26706399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                   cas->dataHi ? fold_Expr(env, subst_Expr(env, cas->dataHi))
26716399f81e98cd8c7fbd55255c67f051a0a1873658sewardj                               : NULL,
2672cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, cas->dataLo))
2673e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                );
2674e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return IRStmt_CAS(cas2);
2675e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      }
2676e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
2677e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
2678e768e92e054cde495849a5c842a477d287677f78sewardj         vassert(isIRAtom(st->Ist.LLSC.addr));
2679e768e92e054cde495849a5c842a477d287677f78sewardj         if (st->Ist.LLSC.storedata)
2680e768e92e054cde495849a5c842a477d287677f78sewardj            vassert(isIRAtom(st->Ist.LLSC.storedata));
2681e768e92e054cde495849a5c842a477d287677f78sewardj         return IRStmt_LLSC(
2682e768e92e054cde495849a5c842a477d287677f78sewardj                   st->Ist.LLSC.end,
2683e768e92e054cde495849a5c842a477d287677f78sewardj                   st->Ist.LLSC.result,
2684cdb5feebd7e817c8207471ef734b43c51c14dee3florian                   fold_Expr(env, subst_Expr(env, st->Ist.LLSC.addr)),
2685e768e92e054cde495849a5c842a477d287677f78sewardj                   st->Ist.LLSC.storedata
2686cdb5feebd7e817c8207471ef734b43c51c14dee3florian                      ? fold_Expr(env, subst_Expr(env, st->Ist.LLSC.storedata))
2687e768e92e054cde495849a5c842a477d287677f78sewardj                      : NULL
2688e768e92e054cde495849a5c842a477d287677f78sewardj                );
2689e768e92e054cde495849a5c842a477d287677f78sewardj
26900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Dirty: {
26910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         Int     i;
26920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         IRDirty *d, *d2;
26930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         d = st->Ist.Dirty.details;
26940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         d2 = emptyIRDirty();
26950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         *d2 = *d;
2696dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         d2->args = shallowCopyIRExprVec(d2->args);
26970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (d2->mFx != Ifx_None) {
2698496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj            vassert(isIRAtom(d2->mAddr));
2699cdb5feebd7e817c8207471ef734b43c51c14dee3florian            d2->mAddr = fold_Expr(env, subst_Expr(env, d2->mAddr));
27000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
2701496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(d2->guard));
2702cdb5feebd7e817c8207471ef734b43c51c14dee3florian         d2->guard = fold_Expr(env, subst_Expr(env, d2->guard));
27030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (i = 0; d2->args[i]; i++) {
270474142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            IRExpr* arg = d2->args[i];
2705ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg))) {
270674142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               vassert(isIRAtom(arg));
270774142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               d2->args[i] = fold_Expr(env, subst_Expr(env, arg));
270874142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            }
27090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
27100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRStmt_Dirty(d2);
2711f0e431671cb877601c2f2e551f42246469b4ee62sewardj      }
2712f0e431671cb877601c2f2e551f42246469b4ee62sewardj
2713f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
27142f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj         return IRStmt_IMark(st->Ist.IMark.addr,
27152f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj                             st->Ist.IMark.len,
27162f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj                             st->Ist.IMark.delta);
2717f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj
2718d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
2719d2445f60726580b450eca68ab40c568f9df338e2sewardj         return IRStmt_NoOp();
2720d2445f60726580b450eca68ab40c568f9df338e2sewardj
2721c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
2722c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         return IRStmt_MBE(st->Ist.MBE.event);
27233e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj
27240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Exit: {
27250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         IRExpr* fcond;
2726496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(st->Ist.Exit.guard));
2727cdb5feebd7e817c8207471ef734b43c51c14dee3florian         fcond = fold_Expr(env, subst_Expr(env, st->Ist.Exit.guard));
27280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (fcond->tag == Iex_Const) {
27290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* Interesting.  The condition on this exit has folded down to
27300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               a constant. */
27310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vassert(fcond->Iex.Const.con->tag == Ico_U1);
27320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (fcond->Iex.Const.con->Ico.U1 == False) {
27330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               /* exit is never going to happen, so dump the statement. */
2734d2445f60726580b450eca68ab40c568f9df338e2sewardj               return IRStmt_NoOp();
27350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            } else {
27360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vassert(fcond->Iex.Const.con->Ico.U1 == True);
2737e810c1940eab1792cfd312635708c540b9a9bfdfsewardj               /* Hmmm.  The exit has become unconditional.  Leave it
2738e810c1940eab1792cfd312635708c540b9a9bfdfsewardj                  as it is for now, since we'd have to truncate the BB
2739e810c1940eab1792cfd312635708c540b9a9bfdfsewardj                  at this point, which is tricky.  Such truncation is
2740e810c1940eab1792cfd312635708c540b9a9bfdfsewardj                  done later by the dead-code elimination pass. */
27410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               /* fall out into the reconstruct-the-exit code. */
27420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               if (vex_control.iropt_verbosity > 0)
27430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  /* really a misuse of vex_control.iropt_verbosity */
27440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  vex_printf("vex iropt: IRStmt_Exit became unconditional\n");
27452963239357452b96dbe6de1b3f8b626ea3305780sewardj            }
2746f0e431671cb877601c2f2e551f42246469b4ee62sewardj         }
2747c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return IRStmt_Exit(fcond, st->Ist.Exit.jk,
2748c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                   st->Ist.Exit.dst, st->Ist.Exit.offsIP);
2749f0e431671cb877601c2f2e551f42246469b4ee62sewardj      }
2750f0e431671cb877601c2f2e551f42246469b4ee62sewardj
27510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   default:
27520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf("\n"); ppIRStmt(st);
27530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vpanic("subst_and_fold_Stmt");
27540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
27550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
27560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
27570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
2758dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjIRSB* cprop_BB ( IRSB* in )
27590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
27600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      i;
2761dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   IRSB*    out;
27620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt*  st2;
27630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      n_tmps = in->tyenv->types_used;
2764d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   IRExpr** env = LibVEX_Alloc_inline(n_tmps * sizeof(IRExpr*));
2765cfe046e178666280b87da998b1b52ecda03ecd89sewardj   /* Keep track of IRStmt_LoadGs that we need to revisit after
2766cfe046e178666280b87da998b1b52ecda03ecd89sewardj      processing all the other statements. */
2767cfe046e178666280b87da998b1b52ecda03ecd89sewardj   const Int N_FIXUPS = 16;
2768cfe046e178666280b87da998b1b52ecda03ecd89sewardj   Int fixups[N_FIXUPS]; /* indices in the stmt array of 'out' */
2769cfe046e178666280b87da998b1b52ecda03ecd89sewardj   Int n_fixups = 0;
27700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
2771dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   out = emptyIRSB();
2772dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   out->tyenv = deepCopyIRTypeEnv( in->tyenv );
27730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
27740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Set up the env with which travels forward.  This holds a
2775cdb5feebd7e817c8207471ef734b43c51c14dee3florian      substitution, mapping IRTemps to IRExprs. The environment
2776cdb5feebd7e817c8207471ef734b43c51c14dee3florian      is to be applied as we move along.  Keys are IRTemps.
2777cdb5feebd7e817c8207471ef734b43c51c14dee3florian      Values are IRExpr*s.
27780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   */
27790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < n_tmps; i++)
27800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      env[i] = NULL;
2781f0e431671cb877601c2f2e551f42246469b4ee62sewardj
27820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* For each original SSA-form stmt ... */
27830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < in->stmts_used; i++) {
2784f0e431671cb877601c2f2e551f42246469b4ee62sewardj
27850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* First apply the substitution to the current stmt.  This
27860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         propagates in any constants and tmp-tmp assignments
27870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         accumulated prior to this point.  As part of the subst_Stmt
27880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         call, also then fold any constant expressions resulting. */
278984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
27900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st2 = in->stmts[i];
279184ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
27920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* perhaps st2 is already a no-op? */
27938bee6d15808653a71717c256a3abe96993439d25sewardj      if (st2->tag == Ist_NoOp) continue;
279484ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
27950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st2 = subst_and_fold_Stmt( env, st2 );
279684ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
2797cfe046e178666280b87da998b1b52ecda03ecd89sewardj      /* Deal with some post-folding special cases. */
2798cfe046e178666280b87da998b1b52ecda03ecd89sewardj      switch (st2->tag) {
2799cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2800cfe046e178666280b87da998b1b52ecda03ecd89sewardj         /* If the statement has been folded into a no-op, forget
2801cfe046e178666280b87da998b1b52ecda03ecd89sewardj            it. */
2802cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_NoOp:
2803cfe046e178666280b87da998b1b52ecda03ecd89sewardj            continue;
2804cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2805cfe046e178666280b87da998b1b52ecda03ecd89sewardj         /* If the statement assigns to an IRTemp add it to the
2806cfe046e178666280b87da998b1b52ecda03ecd89sewardj            running environment. This is for the benefit of copy
2807cfe046e178666280b87da998b1b52ecda03ecd89sewardj            propagation and to allow sameIRExpr look through
2808cfe046e178666280b87da998b1b52ecda03ecd89sewardj            IRTemps. */
2809cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_WrTmp: {
2810cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(env[(Int)(st2->Ist.WrTmp.tmp)] == NULL);
2811cfe046e178666280b87da998b1b52ecda03ecd89sewardj            env[(Int)(st2->Ist.WrTmp.tmp)] = st2->Ist.WrTmp.data;
2812cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2813cfe046e178666280b87da998b1b52ecda03ecd89sewardj            /* 't1 = t2' -- don't add to BB; will be optimized out */
2814cfe046e178666280b87da998b1b52ecda03ecd89sewardj            if (st2->Ist.WrTmp.data->tag == Iex_RdTmp)
2815cfe046e178666280b87da998b1b52ecda03ecd89sewardj               continue;
2816cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2817cfe046e178666280b87da998b1b52ecda03ecd89sewardj            /* 't = const' && 'const != F64i' -- don't add to BB
2818cfe046e178666280b87da998b1b52ecda03ecd89sewardj               Note, we choose not to propagate const when const is an
2819cfe046e178666280b87da998b1b52ecda03ecd89sewardj               F64i, so that F64i literals can be CSE'd later.  This
2820cfe046e178666280b87da998b1b52ecda03ecd89sewardj               helps x86 floating point code generation. */
2821cfe046e178666280b87da998b1b52ecda03ecd89sewardj            if (st2->Ist.WrTmp.data->tag == Iex_Const
2822cfe046e178666280b87da998b1b52ecda03ecd89sewardj                && st2->Ist.WrTmp.data->Iex.Const.con->tag != Ico_F64i) {
2823cfe046e178666280b87da998b1b52ecda03ecd89sewardj               continue;
2824cfe046e178666280b87da998b1b52ecda03ecd89sewardj            }
2825cfe046e178666280b87da998b1b52ecda03ecd89sewardj            /* else add it to the output, as normal */
2826cfe046e178666280b87da998b1b52ecda03ecd89sewardj            break;
2827cfe046e178666280b87da998b1b52ecda03ecd89sewardj         }
282884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
2829cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_LoadG: {
2830cfe046e178666280b87da998b1b52ecda03ecd89sewardj            IRLoadG* lg    = st2->Ist.LoadG.details;
2831cfe046e178666280b87da998b1b52ecda03ecd89sewardj            IRExpr*  guard = lg->guard;
2832cfe046e178666280b87da998b1b52ecda03ecd89sewardj            if (guard->tag == Iex_Const) {
2833cfe046e178666280b87da998b1b52ecda03ecd89sewardj               /* The guard has folded to a constant, and that
2834cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  constant must be 1:I1, since subst_and_fold_Stmt
2835cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  folds out the case 0:I1 by itself. */
2836cfe046e178666280b87da998b1b52ecda03ecd89sewardj               vassert(guard->Iex.Const.con->tag == Ico_U1);
2837cfe046e178666280b87da998b1b52ecda03ecd89sewardj               vassert(guard->Iex.Const.con->Ico.U1 == True);
2838cfe046e178666280b87da998b1b52ecda03ecd89sewardj               /* Add a NoOp here as a placeholder, and make a note of
2839cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  where it is in the output block.  Afterwards we'll
2840cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  come back here and transform the NoOp and the LoadG
2841cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  into a load-convert pair.  The fixups[] entry
2842cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  refers to the inserted NoOp, and we expect to find
2843cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  the relevant LoadG immediately after it. */
2844cfe046e178666280b87da998b1b52ecda03ecd89sewardj               vassert(n_fixups >= 0 && n_fixups <= N_FIXUPS);
2845cfe046e178666280b87da998b1b52ecda03ecd89sewardj               if (n_fixups < N_FIXUPS) {
2846cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  fixups[n_fixups++] = out->stmts_used;
2847cfe046e178666280b87da998b1b52ecda03ecd89sewardj                  addStmtToIRSB( out, IRStmt_NoOp() );
2848cfe046e178666280b87da998b1b52ecda03ecd89sewardj               }
2849cfe046e178666280b87da998b1b52ecda03ecd89sewardj            }
2850cfe046e178666280b87da998b1b52ecda03ecd89sewardj            /* And always add the LoadG to the output, regardless. */
2851cfe046e178666280b87da998b1b52ecda03ecd89sewardj            break;
2852cfe046e178666280b87da998b1b52ecda03ecd89sewardj         }
2853cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2854cfe046e178666280b87da998b1b52ecda03ecd89sewardj      default:
2855cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
28560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
2857cdb5feebd7e817c8207471ef734b43c51c14dee3florian
2858cdb5feebd7e817c8207471ef734b43c51c14dee3florian      /* Not interesting, copy st2 into the output block. */
2859cdb5feebd7e817c8207471ef734b43c51c14dee3florian      addStmtToIRSB( out, st2 );
286084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
28610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
2862cfe046e178666280b87da998b1b52ecda03ecd89sewardj#  if STATS_IROPT
2863cdb5feebd7e817c8207471ef734b43c51c14dee3florian   vex_printf("sameIRExpr: invoked = %u/%u  equal = %u/%u max_nodes = %u\n",
2864cdb5feebd7e817c8207471ef734b43c51c14dee3florian              invocation_count, recursion_count, success_count,
2865cdb5feebd7e817c8207471ef734b43c51c14dee3florian              recursion_success_count, max_nodes_visited);
2866cfe046e178666280b87da998b1b52ecda03ecd89sewardj#  endif
2867cdb5feebd7e817c8207471ef734b43c51c14dee3florian
28680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   out->next     = subst_Expr( env, in->next );
28690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   out->jumpkind = in->jumpkind;
2870c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   out->offsIP   = in->offsIP;
2871cfe046e178666280b87da998b1b52ecda03ecd89sewardj
2872cfe046e178666280b87da998b1b52ecda03ecd89sewardj   /* Process any leftover unconditional LoadGs that we noticed
2873cfe046e178666280b87da998b1b52ecda03ecd89sewardj      in the main pass. */
2874cfe046e178666280b87da998b1b52ecda03ecd89sewardj   vassert(n_fixups >= 0 && n_fixups <= N_FIXUPS);
2875cfe046e178666280b87da998b1b52ecda03ecd89sewardj   for (i = 0; i < n_fixups; i++) {
2876cfe046e178666280b87da998b1b52ecda03ecd89sewardj      Int ix = fixups[i];
2877cfe046e178666280b87da998b1b52ecda03ecd89sewardj      /* Carefully verify that the LoadG has the expected form. */
2878cfe046e178666280b87da998b1b52ecda03ecd89sewardj      vassert(ix >= 0 && ix+1 < out->stmts_used);
2879cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IRStmt* nop = out->stmts[ix];
2880cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IRStmt* lgu = out->stmts[ix+1];
2881cfe046e178666280b87da998b1b52ecda03ecd89sewardj      vassert(nop->tag == Ist_NoOp);
2882cfe046e178666280b87da998b1b52ecda03ecd89sewardj      vassert(lgu->tag == Ist_LoadG);
2883cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IRLoadG* lg    = lgu->Ist.LoadG.details;
2884cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IRExpr*  guard = lg->guard;
2885cfe046e178666280b87da998b1b52ecda03ecd89sewardj      vassert(guard->Iex.Const.con->tag == Ico_U1);
2886cfe046e178666280b87da998b1b52ecda03ecd89sewardj      vassert(guard->Iex.Const.con->Ico.U1 == True);
2887cfe046e178666280b87da998b1b52ecda03ecd89sewardj      /* Figure out the load and result types, and the implied
2888cfe046e178666280b87da998b1b52ecda03ecd89sewardj         conversion operation. */
2889cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IRType cvtRes = Ity_INVALID, cvtArg = Ity_INVALID;
2890cfe046e178666280b87da998b1b52ecda03ecd89sewardj      typeOfIRLoadGOp(lg->cvt, &cvtRes, &cvtArg);
2891cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IROp cvtOp = Iop_INVALID;
2892cfe046e178666280b87da998b1b52ecda03ecd89sewardj      switch (lg->cvt) {
289370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         case ILGop_IdentV128:
289470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         case ILGop_Ident64:
2895cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case ILGop_Ident32: break;
2896cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case ILGop_8Uto32:  cvtOp = Iop_8Uto32;  break;
2897cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case ILGop_8Sto32:  cvtOp = Iop_8Sto32;  break;
2898cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case ILGop_16Uto32: cvtOp = Iop_16Uto32; break;
2899cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case ILGop_16Sto32: cvtOp = Iop_16Sto32; break;
2900cfe046e178666280b87da998b1b52ecda03ecd89sewardj         default: vpanic("cprop_BB: unhandled ILGOp");
2901cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
2902cfe046e178666280b87da998b1b52ecda03ecd89sewardj      /* Replace the placeholder NoOp by the required unconditional
2903cfe046e178666280b87da998b1b52ecda03ecd89sewardj         load. */
2904cfe046e178666280b87da998b1b52ecda03ecd89sewardj      IRTemp tLoaded = newIRTemp(out->tyenv, cvtArg);
2905cfe046e178666280b87da998b1b52ecda03ecd89sewardj      out->stmts[ix]
2906cfe046e178666280b87da998b1b52ecda03ecd89sewardj         = IRStmt_WrTmp(tLoaded,
2907cfe046e178666280b87da998b1b52ecda03ecd89sewardj                        IRExpr_Load(lg->end, cvtArg, lg->addr));
2908cfe046e178666280b87da998b1b52ecda03ecd89sewardj      /* Replace the LoadG by a conversion from the loaded value's
2909cfe046e178666280b87da998b1b52ecda03ecd89sewardj         type to the required result type. */
2910cfe046e178666280b87da998b1b52ecda03ecd89sewardj      out->stmts[ix+1]
2911cfe046e178666280b87da998b1b52ecda03ecd89sewardj         = IRStmt_WrTmp(
2912cfe046e178666280b87da998b1b52ecda03ecd89sewardj              lg->dst, cvtOp == Iop_INVALID
2913cfe046e178666280b87da998b1b52ecda03ecd89sewardj                          ? IRExpr_RdTmp(tLoaded)
2914cfe046e178666280b87da998b1b52ecda03ecd89sewardj                          : IRExpr_Unop(cvtOp, IRExpr_RdTmp(tLoaded)));
2915cfe046e178666280b87da998b1b52ecda03ecd89sewardj   }
2916cfe046e178666280b87da998b1b52ecda03ecd89sewardj
29170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return out;
291884ff0657940e62f38e618ea18bac6f27ce0e741fsewardj}
291984ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
29202963239357452b96dbe6de1b3f8b626ea3305780sewardj
29212963239357452b96dbe6de1b3f8b626ea3305780sewardj/*---------------------------------------------------------------*/
29220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Dead code (t = E) removal                               ---*/
29232963239357452b96dbe6de1b3f8b626ea3305780sewardj/*---------------------------------------------------------------*/
29242963239357452b96dbe6de1b3f8b626ea3305780sewardj
2925e810c1940eab1792cfd312635708c540b9a9bfdfsewardj/* As a side effect, also removes all code following an unconditional
2926e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   side exit. */
2927e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
29280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* The type of the HashHW map is: a map from IRTemp to nothing
29290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   -- really just operating a set or IRTemps.
29302963239357452b96dbe6de1b3f8b626ea3305780sewardj*/
29310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
29320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjinline
29330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void addUses_Temp ( Bool* set, IRTemp tmp )
29342963239357452b96dbe6de1b3f8b626ea3305780sewardj{
29350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   set[(Int)tmp] = True;
293617442fe8094d0f82266e5a05509f62cac8f7539esewardj}
293717442fe8094d0f82266e5a05509f62cac8f7539esewardj
29380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void addUses_Expr ( Bool* set, IRExpr* e )
293917442fe8094d0f82266e5a05509f62cac8f7539esewardj{
294017442fe8094d0f82266e5a05509f62cac8f7539esewardj   Int i;
29412963239357452b96dbe6de1b3f8b626ea3305780sewardj   switch (e->tag) {
29420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_GetI:
29430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, e->Iex.GetI.ix);
29442963239357452b96dbe6de1b3f8b626ea3305780sewardj         return;
294599dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
294699dd03e04a6914d90d5fee727d61d76905334becflorian         addUses_Expr(set, e->Iex.ITE.cond);
294799dd03e04a6914d90d5fee727d61d76905334becflorian         addUses_Expr(set, e->Iex.ITE.iftrue);
294899dd03e04a6914d90d5fee727d61d76905334becflorian         addUses_Expr(set, e->Iex.ITE.iffalse);
29490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
29500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_CCall:
29510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (i = 0; e->Iex.CCall.args[i]; i++)
29520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            addUses_Expr(set, e->Iex.CCall.args[i]);
29530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
2954af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Iex_Load:
2955af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         addUses_Expr(set, e->Iex.Load.addr);
29560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
295740c802659108a96bb87cbc1a30b7b77e2abd0829sewardj      case Iex_Qop:
295896d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         addUses_Expr(set, e->Iex.Qop.details->arg1);
295996d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         addUses_Expr(set, e->Iex.Qop.details->arg2);
296096d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         addUses_Expr(set, e->Iex.Qop.details->arg3);
296196d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         addUses_Expr(set, e->Iex.Qop.details->arg4);
296240c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         return;
2963b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      case Iex_Triop:
2964420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         addUses_Expr(set, e->Iex.Triop.details->arg1);
2965420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         addUses_Expr(set, e->Iex.Triop.details->arg2);
2966420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         addUses_Expr(set, e->Iex.Triop.details->arg3);
2967b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         return;
29680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Binop:
29690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, e->Iex.Binop.arg1);
29700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, e->Iex.Binop.arg2);
29710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
29720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Unop:
29730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, e->Iex.Unop.arg);
29740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
2975dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp:
2976dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addUses_Temp(set, e->Iex.RdTmp.tmp);
29770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
29780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Const:
29790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Get:
29800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
29810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
29820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n");
29830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ppIRExpr(e);
29840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("addUses_Expr");
29850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
29860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
29870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
29880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void addUses_Stmt ( Bool* set, IRStmt* st )
29890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
29900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      i;
29910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRDirty* d;
2992e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRCAS*   cas;
29930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (st->tag) {
29945a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
29955a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         addUses_Expr(set, st->Ist.AbiHint.base);
2996478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         addUses_Expr(set, st->Ist.AbiHint.nia);
29975a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         return;
29980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_PutI:
2999d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         addUses_Expr(set, st->Ist.PutI.details->ix);
3000d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         addUses_Expr(set, st->Ist.PutI.details->data);
30010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
3002dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
3003dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addUses_Expr(set, st->Ist.WrTmp.data);
30040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
30050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Put:
30060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, st->Ist.Put.data);
30070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
3008af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
3009af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         addUses_Expr(set, st->Ist.Store.addr);
3010af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         addUses_Expr(set, st->Ist.Store.data);
30110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
3012cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG: {
3013cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRStoreG* sg = st->Ist.StoreG.details;
3014cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addUses_Expr(set, sg->addr);
3015cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addUses_Expr(set, sg->data);
3016cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addUses_Expr(set, sg->guard);
3017cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return;
3018cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
3019cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG: {
3020cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRLoadG* lg = st->Ist.LoadG.details;
3021cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addUses_Expr(set, lg->addr);
3022cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addUses_Expr(set, lg->alt);
3023cfe046e178666280b87da998b1b52ecda03ecd89sewardj         addUses_Expr(set, lg->guard);
3024cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return;
3025cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
3026e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
3027e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas = st->Ist.CAS.details;
3028e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addUses_Expr(set, cas->addr);
3029e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (cas->expdHi)
3030e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            addUses_Expr(set, cas->expdHi);
3031e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addUses_Expr(set, cas->expdLo);
3032e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (cas->dataHi)
3033e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            addUses_Expr(set, cas->dataHi);
3034e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addUses_Expr(set, cas->dataLo);
3035e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
3036e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
3037e768e92e054cde495849a5c842a477d287677f78sewardj         addUses_Expr(set, st->Ist.LLSC.addr);
3038e768e92e054cde495849a5c842a477d287677f78sewardj         if (st->Ist.LLSC.storedata)
3039e768e92e054cde495849a5c842a477d287677f78sewardj            addUses_Expr(set, st->Ist.LLSC.storedata);
3040e768e92e054cde495849a5c842a477d287677f78sewardj         return;
30410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Dirty:
30420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         d = st->Ist.Dirty.details;
30430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (d->mFx != Ifx_None)
30440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            addUses_Expr(set, d->mAddr);
30450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, d->guard);
304674142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         for (i = 0; d->args[i] != NULL; i++) {
304774142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            IRExpr* arg = d->args[i];
3048ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
304974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               addUses_Expr(set, arg);
305074142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         }
30510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
3052d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
3053f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
3054c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
30553e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj         return;
30560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Exit:
30570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Expr(set, st->Ist.Exit.guard);
30582963239357452b96dbe6de1b3f8b626ea3305780sewardj         return;
30590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
30600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n");
30610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ppIRStmt(st);
30620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("addUses_Stmt");
30630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
30640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
30650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
30660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
30670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Is this literally IRExpr_Const(IRConst_U1(False)) ? */
30680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic Bool isZeroU1 ( IRExpr* e )
30690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
30709d2e769a9368d2b22c32a4764a70e9da38769628sewardj   return toBool( e->tag == Iex_Const
30719d2e769a9368d2b22c32a4764a70e9da38769628sewardj                  && e->Iex.Const.con->tag == Ico_U1
30729d2e769a9368d2b22c32a4764a70e9da38769628sewardj                  && e->Iex.Const.con->Ico.U1 == False );
30730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
30740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3075e810c1940eab1792cfd312635708c540b9a9bfdfsewardj/* Is this literally IRExpr_Const(IRConst_U1(True)) ? */
3076e810c1940eab1792cfd312635708c540b9a9bfdfsewardjstatic Bool isOneU1 ( IRExpr* e )
3077e810c1940eab1792cfd312635708c540b9a9bfdfsewardj{
3078e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   return toBool( e->tag == Iex_Const
3079e810c1940eab1792cfd312635708c540b9a9bfdfsewardj                  && e->Iex.Const.con->tag == Ico_U1
3080e810c1940eab1792cfd312635708c540b9a9bfdfsewardj                  && e->Iex.Const.con->Ico.U1 == True );
3081e810c1940eab1792cfd312635708c540b9a9bfdfsewardj}
3082e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
30830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3084dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj/* Note, this destructively modifies the given IRSB. */
30850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
30860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Scan backwards through statements, carrying a set of IRTemps which
30870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   are known to be used after the current point.  On encountering 't =
30880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   E', delete the binding if it is not used.  Otherwise, add any temp
3089e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   uses to the set and keep on moving backwards.
3090e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
3091e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   As an enhancement, the first (backwards) pass searches for IR exits
3092e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   with always-taken conditions and notes the location of the earliest
3093e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   one in the block.  If any such are found, a second pass copies the
3094e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   exit destination and jump kind to the bb-end.  Then, the exit and
3095e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   all statements following it are turned into no-ops.
3096e810c1940eab1792cfd312635708c540b9a9bfdfsewardj*/
30970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3098dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj/* notstatic */ void do_deadcode_BB ( IRSB* bb )
30990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
3100e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   Int     i, i_unconditional_exit;
31010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     n_tmps = bb->tyenv->types_used;
3102d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   Bool*   set = LibVEX_Alloc_inline(n_tmps * sizeof(Bool));
31030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt* st;
31040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
31050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < n_tmps; i++)
31060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      set[i] = False;
31070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
31080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* start off by recording IRTemp uses in the next field. */
31090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   addUses_Expr(set, bb->next);
31100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3111e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   /* First pass */
3112e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
31130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Work backwards through the stmts */
3114e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   i_unconditional_exit = -1;
31150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = bb->stmts_used-1; i >= 0; i--) {
31160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
31178bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
31180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
3119e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      /* take note of any unconditional exits */
3120e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      if (st->tag == Ist_Exit
3121e810c1940eab1792cfd312635708c540b9a9bfdfsewardj          && isOneU1(st->Ist.Exit.guard))
3122e810c1940eab1792cfd312635708c540b9a9bfdfsewardj         i_unconditional_exit = i;
3123dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag == Ist_WrTmp
3124dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && set[(Int)(st->Ist.WrTmp.tmp)] == False) {
31250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          /* it's an IRTemp which never got used.  Delete it. */
31260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (DEBUG_IROPT) {
31270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("DEAD: ");
31280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ppIRStmt(st);
31290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("\n");
31300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
3131d2445f60726580b450eca68ab40c568f9df338e2sewardj         bb->stmts[i] = IRStmt_NoOp();
31320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
31330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      else
31340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Dirty
31350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          && st->Ist.Dirty.details->guard
31360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          && isZeroU1(st->Ist.Dirty.details->guard)) {
3137d2445f60726580b450eca68ab40c568f9df338e2sewardj         /* This is a dirty helper which will never get called.
3138d2445f60726580b450eca68ab40c568f9df338e2sewardj            Delete it. */
3139d2445f60726580b450eca68ab40c568f9df338e2sewardj         bb->stmts[i] = IRStmt_NoOp();
31400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj       }
31410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj       else {
31420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* Note any IRTemp uses made by the current statement. */
31430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addUses_Stmt(set, st);
31440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
31450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
3146e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
3147e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   /* Optional second pass: if any unconditional exits were found,
3148e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      delete them and all following statements. */
3149e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
3150e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   if (i_unconditional_exit != -1) {
3151e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      if (0) vex_printf("ZAPPING ALL FORWARDS from %d\n",
3152e810c1940eab1792cfd312635708c540b9a9bfdfsewardj                        i_unconditional_exit);
3153e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      vassert(i_unconditional_exit >= 0
3154e810c1940eab1792cfd312635708c540b9a9bfdfsewardj              && i_unconditional_exit < bb->stmts_used);
3155e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      bb->next
3156e810c1940eab1792cfd312635708c540b9a9bfdfsewardj         = IRExpr_Const( bb->stmts[i_unconditional_exit]->Ist.Exit.dst );
3157e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      bb->jumpkind
3158e810c1940eab1792cfd312635708c540b9a9bfdfsewardj         = bb->stmts[i_unconditional_exit]->Ist.Exit.jk;
3159c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      bb->offsIP
3160c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         = bb->stmts[i_unconditional_exit]->Ist.Exit.offsIP;
3161e810c1940eab1792cfd312635708c540b9a9bfdfsewardj      for (i = i_unconditional_exit; i < bb->stmts_used; i++)
3162e810c1940eab1792cfd312635708c540b9a9bfdfsewardj         bb->stmts[i] = IRStmt_NoOp();
3163e810c1940eab1792cfd312635708c540b9a9bfdfsewardj   }
31640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
31652963239357452b96dbe6de1b3f8b626ea3305780sewardj
3166e810c1940eab1792cfd312635708c540b9a9bfdfsewardj
31670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
31680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Specialisation of helper function calls, in             ---*/
31690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- collaboration with the front end                        ---*/
31700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
31712963239357452b96dbe6de1b3f8b626ea3305780sewardj
31720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic
3173be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardjIRSB* spec_helpers_BB(
3174be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj         IRSB* bb,
31751ff4756e1731485e6bf3cd96717cd8398daec1f2florian         IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int)
3176be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      )
31770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
3178b92307503d4fb9265136e182d10c42ebb9dd8272sewardj   Int     i;
31790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt* st;
31800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr* ex;
3181b92307503d4fb9265136e182d10c42ebb9dd8272sewardj   Bool    any = False;
31822963239357452b96dbe6de1b3f8b626ea3305780sewardj
31830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = bb->stmts_used-1; i >= 0; i--) {
31840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
31852963239357452b96dbe6de1b3f8b626ea3305780sewardj
3186dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag != Ist_WrTmp
3187dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          || st->Ist.WrTmp.data->tag != Iex_CCall)
31888bee6d15808653a71717c256a3abe96993439d25sewardj         continue;
31892963239357452b96dbe6de1b3f8b626ea3305780sewardj
3190dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ex = (*specHelper)( st->Ist.WrTmp.data->Iex.CCall.cee->name,
3191be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                          st->Ist.WrTmp.data->Iex.CCall.args,
3192be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj                          &bb->stmts[0], i );
31930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (!ex)
31940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        /* the front end can't think of a suitable replacement */
31950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        continue;
3196f6501996bf1f0e2a8ce6817efe9edf6b619bc85bsewardj
31970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* We got something better.  Install it in the bb. */
3198b92307503d4fb9265136e182d10c42ebb9dd8272sewardj      any = True;
31990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      bb->stmts[i]
3200dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         = IRStmt_WrTmp(st->Ist.WrTmp.tmp, ex);
32012963239357452b96dbe6de1b3f8b626ea3305780sewardj
32020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (0) {
32030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("SPEC: ");
3204dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         ppIRExpr(st->Ist.WrTmp.data);
32050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("  -->  ");
32060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ppIRExpr(ex);
32070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n");
32080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
32090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
3210b92307503d4fb9265136e182d10c42ebb9dd8272sewardj
3211b92307503d4fb9265136e182d10c42ebb9dd8272sewardj   if (any)
3212b92307503d4fb9265136e182d10c42ebb9dd8272sewardj      bb = flatten_BB(bb);
3213b92307503d4fb9265136e182d10c42ebb9dd8272sewardj   return bb;
32142963239357452b96dbe6de1b3f8b626ea3305780sewardj}
32152963239357452b96dbe6de1b3f8b626ea3305780sewardj
32162963239357452b96dbe6de1b3f8b626ea3305780sewardj
32170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
32189b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/*--- Determination of guest state aliasing relationships     ---*/
32199b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/*---------------------------------------------------------------*/
32209b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32219b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/* These are helper functions for CSE and GetI/PutI transformations.
32229b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32239b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   Determine, to the extent possible, the relationship between two
32249b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   guest state accesses.  The possible outcomes are:
32259b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32269b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   * Exact alias.  These two accesses denote precisely the same
32279b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj     piece of the guest state.
32289b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32299b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   * Definitely no alias.  These two accesses are guaranteed not to
32309b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj     overlap any part of the guest state.
32319b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32329b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   * Unknown -- if neither of the above can be established.
32339b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32349b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   If in doubt, return Unknown.  */
32359b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32369b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardjtypedef
32379b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   enum { ExactAlias, NoAlias, UnknownAlias }
32389b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   GSAliasing;
32399b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32409b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32419b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/* Produces the alias relation between an indexed guest
32429b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   state access and a non-indexed access. */
32439b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32449b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardjstatic
3245dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjGSAliasing getAliasingRelation_IC ( IRRegArray* descr1, IRExpr* ix1,
32469b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                                    Int offset2, IRType ty2 )
32479b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj{
32489b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   UInt minoff1, maxoff1, minoff2, maxoff2;
32499b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32509b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   getArrayBounds( descr1, &minoff1, &maxoff1 );
32519b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   minoff2 = offset2;
32529b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   maxoff2 = minoff2 + sizeofIRType(ty2) - 1;
32539b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32549b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   if (maxoff1 < minoff2 || maxoff2 < minoff1)
32559b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      return NoAlias;
32569b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32579b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* Could probably do better here if required.  For the moment
32589b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      however just claim not to know anything more. */
32599b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   return UnknownAlias;
32609b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj}
32619b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32629b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32639b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/* Produces the alias relation between two indexed guest state
32649b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   accesses. */
32659b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32669b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardjstatic
32679b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardjGSAliasing getAliasingRelation_II (
3268dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj              IRRegArray* descr1, IRExpr* ix1, Int bias1,
3269dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj              IRRegArray* descr2, IRExpr* ix2, Int bias2
32709b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj           )
32719b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj{
32729b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   UInt minoff1, maxoff1, minoff2, maxoff2;
32739b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   Int  iters;
32749b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32759b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* First try hard to show they don't alias. */
32769b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   getArrayBounds( descr1, &minoff1, &maxoff1 );
32779b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   getArrayBounds( descr2, &minoff2, &maxoff2 );
32789b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   if (maxoff1 < minoff2 || maxoff2 < minoff1)
32799b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      return NoAlias;
32809b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32819b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* So the two arrays at least partially overlap.  To get any
32829b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      further we'll have to be sure that the descriptors are
32839b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      identical. */
3284dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   if (!eqIRRegArray(descr1, descr2))
32859b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      return UnknownAlias;
32869b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32879b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* The descriptors are identical.  Now the only difference can be
32889b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      in the index expressions.  If they cannot be shown to be
32899b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      identical, we have to say we don't know what the aliasing
32909b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      relation will be.  Now, since the IR is flattened, the index
32919b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      expressions should be atoms -- either consts or tmps.  So that
32929b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      makes the comparison simple. */
32939b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(isIRAtom(ix1));
32949b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(isIRAtom(ix2));
32959b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   if (!eqIRAtom(ix1,ix2))
32969b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      return UnknownAlias;
32979b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
32989b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* Ok, the index expressions are identical.  So now the only way
32999b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      they can be different is in the bias.  Normalise this
33009b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      paranoidly, to reliably establish equality/non-equality. */
33019b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
33029b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* So now we know that the GetI and PutI index the same array
33039b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      with the same base.  Are the offsets the same, modulo the
33049b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      array size?  Do this paranoidly. */
33059b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(descr1->nElems == descr2->nElems);
33069b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(descr1->elemTy == descr2->elemTy);
33079b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(descr1->base   == descr2->base);
33089b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   iters = 0;
33099b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   while (bias1 < 0 || bias2 < 0) {
33109b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      bias1 += descr1->nElems;
33119b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      bias2 += descr1->nElems;
33129b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      iters++;
33139b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      if (iters > 10)
33149b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         vpanic("getAliasingRelation: iters");
33159b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   }
33169b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(bias1 >= 0 && bias2 >= 0);
33179b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   bias1 %= descr1->nElems;
33189b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   bias2 %= descr1->nElems;
33199b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(bias1 >= 0 && bias1 < descr1->nElems);
33209b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   vassert(bias2 >= 0 && bias2 < descr1->nElems);
33219b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
33229b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   /* Finally, biasP and biasG are normalised into the range
33239b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      0 .. descrP/G->nElems - 1.  And so we can establish
33249b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      equality/non-equality. */
33259b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
33269b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   return bias1==bias2 ? ExactAlias : NoAlias;
33279b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj}
33289b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
33299b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
33309b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/*---------------------------------------------------------------*/
33310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Common Subexpression Elimination                        ---*/
33320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
33330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
33340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Expensive in time and space. */
33350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
33360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Uses two environments:
33370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   a IRTemp -> IRTemp mapping
33380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   a mapping from AvailExpr* to IRTemp
33392963239357452b96dbe6de1b3f8b626ea3305780sewardj*/
33402963239357452b96dbe6de1b3f8b626ea3305780sewardj
33410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjtypedef
33420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   struct {
3343e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      enum { TCc, TCt } tag;
3344e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      union { IRTemp tmp; IRConst* con; } u;
3345e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   }
3346e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   TmpOrConst;
3347e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj
3348e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardjstatic Bool eqTmpOrConst ( TmpOrConst* tc1, TmpOrConst* tc2 )
3349e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj{
3350e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   if (tc1->tag != tc2->tag)
3351e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      return False;
3352e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   switch (tc1->tag) {
3353e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      case TCc:
3354e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         return eqIRConst(tc1->u.con, tc2->u.con);
3355e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      case TCt:
3356e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         return tc1->u.tmp == tc2->u.tmp;
3357e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      default:
3358e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         vpanic("eqTmpOrConst");
3359e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   }
3360e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj}
3361e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj
3362e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardjstatic Bool eqIRCallee ( IRCallee* cee1, IRCallee* cee2 )
3363e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj{
3364e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   Bool eq = cee1->addr == cee2->addr;
3365e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   if (eq) {
3366e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      vassert(cee1->regparms == cee2->regparms);
3367e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      vassert(cee1->mcx_mask == cee2->mcx_mask);
3368e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      /* Names should be the same too, but we don't bother to
3369e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         check. */
3370e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   }
3371e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   return eq;
3372e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj}
3373e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj
3374581cf07354594dc2006498f0f2d081974b579b5asewardj/* Convert an atomic IRExpr* to a TmpOrConst. */
3375581cf07354594dc2006498f0f2d081974b579b5asewardjstatic void irExpr_to_TmpOrConst ( /*OUT*/TmpOrConst* tc, IRExpr* e )
3376581cf07354594dc2006498f0f2d081974b579b5asewardj{
3377581cf07354594dc2006498f0f2d081974b579b5asewardj   switch (e->tag) {
3378581cf07354594dc2006498f0f2d081974b579b5asewardj      case Iex_RdTmp:
3379581cf07354594dc2006498f0f2d081974b579b5asewardj         tc->tag   = TCt;
3380581cf07354594dc2006498f0f2d081974b579b5asewardj         tc->u.tmp = e->Iex.RdTmp.tmp;
3381581cf07354594dc2006498f0f2d081974b579b5asewardj         break;
3382581cf07354594dc2006498f0f2d081974b579b5asewardj      case Iex_Const:
3383581cf07354594dc2006498f0f2d081974b579b5asewardj         tc->tag   = TCc;
3384581cf07354594dc2006498f0f2d081974b579b5asewardj         tc->u.con = e->Iex.Const.con;
3385581cf07354594dc2006498f0f2d081974b579b5asewardj         break;
3386581cf07354594dc2006498f0f2d081974b579b5asewardj      default:
3387581cf07354594dc2006498f0f2d081974b579b5asewardj         /* Getting here is a serious error.  It means that the
3388581cf07354594dc2006498f0f2d081974b579b5asewardj            presented arg isn't an IR atom, as it should be. */
3389581cf07354594dc2006498f0f2d081974b579b5asewardj         vpanic("irExpr_to_TmpOrConst");
3390581cf07354594dc2006498f0f2d081974b579b5asewardj   }
3391581cf07354594dc2006498f0f2d081974b579b5asewardj}
3392581cf07354594dc2006498f0f2d081974b579b5asewardj
3393581cf07354594dc2006498f0f2d081974b579b5asewardj/* Convert a TmpOrConst to an atomic IRExpr*. */
3394581cf07354594dc2006498f0f2d081974b579b5asewardjstatic IRExpr* tmpOrConst_to_IRExpr ( TmpOrConst* tc )
3395581cf07354594dc2006498f0f2d081974b579b5asewardj{
3396581cf07354594dc2006498f0f2d081974b579b5asewardj   switch (tc->tag) {
3397581cf07354594dc2006498f0f2d081974b579b5asewardj      case TCc: return IRExpr_Const(tc->u.con);
3398581cf07354594dc2006498f0f2d081974b579b5asewardj      case TCt: return IRExpr_RdTmp(tc->u.tmp);
3399581cf07354594dc2006498f0f2d081974b579b5asewardj      default:  vpanic("tmpOrConst_to_IRExpr");
3400581cf07354594dc2006498f0f2d081974b579b5asewardj   }
3401581cf07354594dc2006498f0f2d081974b579b5asewardj}
3402581cf07354594dc2006498f0f2d081974b579b5asewardj
3403e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj/* Convert a NULL terminated IRExpr* vector to an array of
3404e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   TmpOrConsts, and a length. */
3405e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardjstatic void irExprVec_to_TmpOrConsts ( /*OUT*/TmpOrConst** outs,
3406e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                                       /*OUT*/Int* nOuts,
3407e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                                       IRExpr** ins )
3408e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj{
3409e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   Int i, n;
3410e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   /* We have to make two passes, one to count, one to copy. */
3411e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   for (n = 0; ins[n]; n++)
3412e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      ;
3413d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   *outs  = LibVEX_Alloc_inline(n * sizeof(TmpOrConst));
3414e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   *nOuts = n;
3415e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   /* and now copy .. */
3416e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   for (i = 0; i < n; i++) {
3417581cf07354594dc2006498f0f2d081974b579b5asewardj      IRExpr*     arg = ins[i];
3418e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      TmpOrConst* dst = &(*outs)[i];
3419581cf07354594dc2006498f0f2d081974b579b5asewardj      irExpr_to_TmpOrConst(dst, arg);
3420e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   }
3421e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj}
3422e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj
3423e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardjtypedef
3424e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   struct {
3425b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      enum { Ut, Btt, Btc, Bct, Cf64i, Ittt, Itct, Ittc, Itcc, GetIt,
34262608c6946f80e733875aa4969c39740fcb012c17sewardj             CCall, Load
3427da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian      } tag;
34280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      union {
34290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* unop(tmp) */
34300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         struct {
34310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IROp   op;
34320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRTemp arg;
34330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } Ut;
34340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* binop(tmp,tmp) */
34350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         struct {
34360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IROp   op;
34370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRTemp arg1;
34380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRTemp arg2;
34390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } Btt;
34400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* binop(tmp,const) */
34410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         struct {
34420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IROp    op;
34430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRTemp  arg1;
34440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRConst con2;
34450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } Btc;
34460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* binop(const,tmp) */
34470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         struct {
34480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IROp    op;
34490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRConst con1;
34500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            IRTemp  arg2;
34510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } Bct;
34520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* F64i-style const */
34530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         struct {
34540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ULong f64i;
34550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } Cf64i;
345699dd03e04a6914d90d5fee727d61d76905334becflorian         /* ITE(tmp,tmp,tmp) */
34579b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         struct {
34589b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            IRTemp co;
3459b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian            IRTemp e1;
34609b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            IRTemp e0;
3461b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         } Ittt;
346299dd03e04a6914d90d5fee727d61d76905334becflorian         /* ITE(tmp,tmp,const) */
3463da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian         struct {
3464da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian            IRTemp  co;
3465b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian            IRTemp  e1;
3466da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian            IRConst con0;
3467b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         } Ittc;
346899dd03e04a6914d90d5fee727d61d76905334becflorian         /* ITE(tmp,const,tmp) */
3469da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian         struct {
3470da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian            IRTemp  co;
3471b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian            IRConst con1;
3472da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian            IRTemp  e0;
3473b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         } Itct;
347499dd03e04a6914d90d5fee727d61d76905334becflorian         /* ITE(tmp,const,const) */
3475da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian         struct {
3476da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian            IRTemp  co;
3477b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian            IRConst con1;
3478da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian            IRConst con0;
3479b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         } Itcc;
34809b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         /* GetI(descr,tmp,bias)*/
34819b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         struct {
3482dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            IRRegArray* descr;
3483dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            IRTemp      ix;
3484dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            Int         bias;
34859b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         } GetIt;
3486e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         /* Clean helper call */
3487e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         struct {
3488e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            IRCallee*   cee;
3489e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            TmpOrConst* args;
3490e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            Int         nArgs;
3491e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            IRType      retty;
3492e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         } CCall;
34932608c6946f80e733875aa4969c39740fcb012c17sewardj         /* Load(end,ty,addr) */
34942608c6946f80e733875aa4969c39740fcb012c17sewardj         struct {
34952608c6946f80e733875aa4969c39740fcb012c17sewardj            IREndness  end;
34962608c6946f80e733875aa4969c39740fcb012c17sewardj            IRType     ty;
34972608c6946f80e733875aa4969c39740fcb012c17sewardj            TmpOrConst addr;
34982608c6946f80e733875aa4969c39740fcb012c17sewardj         } Load;
34990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      } u;
35000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
35010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   AvailExpr;
350217442fe8094d0f82266e5a05509f62cac8f7539esewardj
35030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic Bool eq_AvailExpr ( AvailExpr* a1, AvailExpr* a2 )
350417442fe8094d0f82266e5a05509f62cac8f7539esewardj{
3505e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   if (LIKELY(a1->tag != a2->tag))
35060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
35070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (a1->tag) {
35080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ut:
35099d2e769a9368d2b22c32a4764a70e9da38769628sewardj         return toBool(
35109d2e769a9368d2b22c32a4764a70e9da38769628sewardj                a1->u.Ut.op == a2->u.Ut.op
35119d2e769a9368d2b22c32a4764a70e9da38769628sewardj                && a1->u.Ut.arg == a2->u.Ut.arg);
35120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Btt:
35139d2e769a9368d2b22c32a4764a70e9da38769628sewardj         return toBool(
35149d2e769a9368d2b22c32a4764a70e9da38769628sewardj                a1->u.Btt.op == a2->u.Btt.op
35150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                && a1->u.Btt.arg1 == a2->u.Btt.arg1
35169d2e769a9368d2b22c32a4764a70e9da38769628sewardj                && a1->u.Btt.arg2 == a2->u.Btt.arg2);
35170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Btc:
35189d2e769a9368d2b22c32a4764a70e9da38769628sewardj         return toBool(
35199d2e769a9368d2b22c32a4764a70e9da38769628sewardj                a1->u.Btc.op == a2->u.Btc.op
35200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                && a1->u.Btc.arg1 == a2->u.Btc.arg1
35219d2e769a9368d2b22c32a4764a70e9da38769628sewardj                && eqIRConst(&a1->u.Btc.con2, &a2->u.Btc.con2));
35220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Bct:
35239d2e769a9368d2b22c32a4764a70e9da38769628sewardj         return toBool(
35249d2e769a9368d2b22c32a4764a70e9da38769628sewardj                a1->u.Bct.op == a2->u.Bct.op
35250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                && a1->u.Bct.arg2 == a2->u.Bct.arg2
35269d2e769a9368d2b22c32a4764a70e9da38769628sewardj                && eqIRConst(&a1->u.Bct.con1, &a2->u.Bct.con1));
35270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Cf64i:
35289d2e769a9368d2b22c32a4764a70e9da38769628sewardj         return toBool(a1->u.Cf64i.f64i == a2->u.Cf64i.f64i);
3529b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Ittt:
3530b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return toBool(a1->u.Ittt.co == a2->u.Ittt.co
3531b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && a1->u.Ittt.e1 == a2->u.Ittt.e1
3532b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && a1->u.Ittt.e0 == a2->u.Ittt.e0);
3533b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Ittc:
3534b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return toBool(a1->u.Ittc.co == a2->u.Ittc.co
3535b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && a1->u.Ittc.e1 == a2->u.Ittc.e1
3536b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && eqIRConst(&a1->u.Ittc.con0, &a2->u.Ittc.con0));
3537b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Itct:
3538b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return toBool(a1->u.Itct.co == a2->u.Itct.co
3539b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && eqIRConst(&a1->u.Itct.con1, &a2->u.Itct.con1)
3540b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && a1->u.Itct.e0 == a2->u.Itct.e0);
3541b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Itcc:
3542b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return toBool(a1->u.Itcc.co == a2->u.Itcc.co
3543b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && eqIRConst(&a1->u.Itcc.con1, &a2->u.Itcc.con1)
3544b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                       && eqIRConst(&a1->u.Itcc.con0, &a2->u.Itcc.con0));
35459b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      case GetIt:
3546dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return toBool(eqIRRegArray(a1->u.GetIt.descr, a2->u.GetIt.descr)
35479b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                       && a1->u.GetIt.ix == a2->u.GetIt.ix
35489b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                       && a1->u.GetIt.bias == a2->u.GetIt.bias);
3549e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      case CCall: {
3550e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         Int  i, n;
3551e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         Bool eq = a1->u.CCall.nArgs == a2->u.CCall.nArgs
3552e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                   && eqIRCallee(a1->u.CCall.cee, a2->u.CCall.cee);
3553e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         if (eq) {
3554e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            n = a1->u.CCall.nArgs;
3555e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            for (i = 0; i < n; i++) {
3556e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj               if (!eqTmpOrConst( &a1->u.CCall.args[i],
3557e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                                  &a2->u.CCall.args[i] )) {
3558e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                  eq = False;
3559e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                  break;
3560e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj               }
3561e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj            }
3562e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         }
3563e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         if (eq) vassert(a1->u.CCall.retty == a2->u.CCall.retty);
3564e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         return eq;
3565e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      }
35662608c6946f80e733875aa4969c39740fcb012c17sewardj      case Load: {
35672608c6946f80e733875aa4969c39740fcb012c17sewardj         Bool eq = toBool(a1->u.Load.end == a2->u.Load.end
35682608c6946f80e733875aa4969c39740fcb012c17sewardj                          && a1->u.Load.ty == a2->u.Load.ty
35692608c6946f80e733875aa4969c39740fcb012c17sewardj                          && eqTmpOrConst(&a1->u.Load.addr, &a2->u.Load.addr));
35702608c6946f80e733875aa4969c39740fcb012c17sewardj         return eq;
35712608c6946f80e733875aa4969c39740fcb012c17sewardj      }
35722608c6946f80e733875aa4969c39740fcb012c17sewardj      default:
35732608c6946f80e733875aa4969c39740fcb012c17sewardj         vpanic("eq_AvailExpr");
357417442fe8094d0f82266e5a05509f62cac8f7539esewardj   }
357517442fe8094d0f82266e5a05509f62cac8f7539esewardj}
35762963239357452b96dbe6de1b3f8b626ea3305780sewardj
35770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic IRExpr* availExpr_to_IRExpr ( AvailExpr* ae )
35782963239357452b96dbe6de1b3f8b626ea3305780sewardj{
3579b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian   IRConst *con, *con0, *con1;
35800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (ae->tag) {
35810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ut:
3582dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRExpr_Unop( ae->u.Ut.op, IRExpr_RdTmp(ae->u.Ut.arg) );
35830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Btt:
35840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_Binop( ae->u.Btt.op,
3585dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              IRExpr_RdTmp(ae->u.Btt.arg1),
3586dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              IRExpr_RdTmp(ae->u.Btt.arg2) );
35870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Btc:
3588d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         con = LibVEX_Alloc_inline(sizeof(IRConst));
35890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         *con = ae->u.Btc.con2;
35900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_Binop( ae->u.Btc.op,
3591dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              IRExpr_RdTmp(ae->u.Btc.arg1),
3592dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              IRExpr_Const(con) );
35930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Bct:
3594d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         con = LibVEX_Alloc_inline(sizeof(IRConst));
35950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         *con = ae->u.Bct.con1;
35960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_Binop( ae->u.Bct.op,
3597dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              IRExpr_Const(con),
3598dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              IRExpr_RdTmp(ae->u.Bct.arg2) );
35990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Cf64i:
36000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_Const(IRConst_F64i(ae->u.Cf64i.f64i));
3601b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Ittt:
3602b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Ittt.co),
3603b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                           IRExpr_RdTmp(ae->u.Ittt.e1),
3604b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                           IRExpr_RdTmp(ae->u.Ittt.e0));
3605b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Ittc:
3606d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         con0 = LibVEX_Alloc_inline(sizeof(IRConst));
3607b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         *con0 = ae->u.Ittc.con0;
3608b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Ittc.co),
3609b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                           IRExpr_RdTmp(ae->u.Ittc.e1),
361099dd03e04a6914d90d5fee727d61d76905334becflorian                           IRExpr_Const(con0));
3611b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Itct:
3612d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         con1 = LibVEX_Alloc_inline(sizeof(IRConst));
3613b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         *con1 = ae->u.Itct.con1;
3614b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Itct.co),
3615b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                           IRExpr_Const(con1),
3616b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                           IRExpr_RdTmp(ae->u.Itct.e0));
3617b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian
3618b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Itcc:
3619d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         con0 = LibVEX_Alloc_inline(sizeof(IRConst));
3620d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         con1 = LibVEX_Alloc_inline(sizeof(IRConst));
3621b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         *con0 = ae->u.Itcc.con0;
3622b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         *con1 = ae->u.Itcc.con1;
3623b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         return IRExpr_ITE(IRExpr_RdTmp(ae->u.Itcc.co),
3624b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                           IRExpr_Const(con1),
362599dd03e04a6914d90d5fee727d61d76905334becflorian                           IRExpr_Const(con0));
36269b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      case GetIt:
36279b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         return IRExpr_GetI(ae->u.GetIt.descr,
3628dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                            IRExpr_RdTmp(ae->u.GetIt.ix),
36299b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                            ae->u.GetIt.bias);
3630e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      case CCall: {
3631e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         Int i, n = ae->u.CCall.nArgs;
3632e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         vassert(n >= 0);
3633d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         IRExpr** vec = LibVEX_Alloc_inline((n+1) * sizeof(IRExpr*));
3634e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         vec[n] = NULL;
3635e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         for (i = 0; i < n; i++) {
3636581cf07354594dc2006498f0f2d081974b579b5asewardj            vec[i] = tmpOrConst_to_IRExpr(&ae->u.CCall.args[i]);
3637e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         }
3638e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         return IRExpr_CCall(ae->u.CCall.cee,
3639e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                             ae->u.CCall.retty,
3640e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj                             vec);
3641e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      }
36422608c6946f80e733875aa4969c39740fcb012c17sewardj      case Load:
36432608c6946f80e733875aa4969c39740fcb012c17sewardj         return IRExpr_Load(ae->u.Load.end, ae->u.Load.ty,
36442608c6946f80e733875aa4969c39740fcb012c17sewardj                            tmpOrConst_to_IRExpr(&ae->u.Load.addr));
36450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
36460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("availExpr_to_IRExpr");
36472963239357452b96dbe6de1b3f8b626ea3305780sewardj   }
36482963239357452b96dbe6de1b3f8b626ea3305780sewardj}
36492963239357452b96dbe6de1b3f8b626ea3305780sewardj
36500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjinline
36510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic IRTemp subst_AvailExpr_Temp ( HashHW* env, IRTemp tmp )
36522963239357452b96dbe6de1b3f8b626ea3305780sewardj{
36530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   HWord res;
36540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* env :: IRTemp -> IRTemp */
36550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (lookupHHW( env, &res, (HWord)tmp ))
36560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return (IRTemp)res;
36570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   else
36580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return tmp;
36590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
3660f6501996bf1f0e2a8ce6817efe9edf6b619bc85bsewardj
3661581cf07354594dc2006498f0f2d081974b579b5asewardjinline
3662581cf07354594dc2006498f0f2d081974b579b5asewardjstatic void subst_AvailExpr_TmpOrConst ( /*MB_MOD*/TmpOrConst* tc,
3663581cf07354594dc2006498f0f2d081974b579b5asewardj                                          HashHW* env )
3664581cf07354594dc2006498f0f2d081974b579b5asewardj{
3665581cf07354594dc2006498f0f2d081974b579b5asewardj   /* env :: IRTemp -> IRTemp */
3666581cf07354594dc2006498f0f2d081974b579b5asewardj   if (tc->tag == TCt) {
3667581cf07354594dc2006498f0f2d081974b579b5asewardj      tc->u.tmp = subst_AvailExpr_Temp( env, tc->u.tmp );
3668581cf07354594dc2006498f0f2d081974b579b5asewardj   }
3669581cf07354594dc2006498f0f2d081974b579b5asewardj}
3670581cf07354594dc2006498f0f2d081974b579b5asewardj
36710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void subst_AvailExpr ( HashHW* env, AvailExpr* ae )
36720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
36730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* env :: IRTemp -> IRTemp */
36740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (ae->tag) {
36750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ut:
36760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ae->u.Ut.arg = subst_AvailExpr_Temp( env, ae->u.Ut.arg );
36770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
36780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Btt:
36790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ae->u.Btt.arg1 = subst_AvailExpr_Temp( env, ae->u.Btt.arg1 );
36800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ae->u.Btt.arg2 = subst_AvailExpr_Temp( env, ae->u.Btt.arg2 );
36810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
36820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Btc:
36830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ae->u.Btc.arg1 = subst_AvailExpr_Temp( env, ae->u.Btc.arg1 );
36840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
36850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Bct:
36860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         ae->u.Bct.arg2 = subst_AvailExpr_Temp( env, ae->u.Bct.arg2 );
36870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
36880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Cf64i:
36890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
3690b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Ittt:
3691b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Ittt.co = subst_AvailExpr_Temp( env, ae->u.Ittt.co );
3692b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Ittt.e1 = subst_AvailExpr_Temp( env, ae->u.Ittt.e1 );
3693b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Ittt.e0 = subst_AvailExpr_Temp( env, ae->u.Ittt.e0 );
36949b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         break;
3695b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Ittc:
3696b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Ittc.co = subst_AvailExpr_Temp( env, ae->u.Ittc.co );
3697b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Ittc.e1 = subst_AvailExpr_Temp( env, ae->u.Ittc.e1 );
3698da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian         break;
3699b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Itct:
3700b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Itct.co = subst_AvailExpr_Temp( env, ae->u.Itct.co );
3701b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Itct.e0 = subst_AvailExpr_Temp( env, ae->u.Itct.e0 );
3702da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian         break;
3703b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian      case Itcc:
3704b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian         ae->u.Itcc.co = subst_AvailExpr_Temp( env, ae->u.Itcc.co );
3705da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian         break;
37069b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      case GetIt:
37079b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         ae->u.GetIt.ix = subst_AvailExpr_Temp( env, ae->u.GetIt.ix );
37089b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         break;
3709e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      case CCall: {
3710e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         Int i, n = ae->u.CCall.nArgs;;
3711e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         for (i = 0; i < n; i++) {
3712581cf07354594dc2006498f0f2d081974b579b5asewardj            subst_AvailExpr_TmpOrConst(&ae->u.CCall.args[i], env);
3713e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         }
3714e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj         break;
3715e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj      }
37162608c6946f80e733875aa4969c39740fcb012c17sewardj      case Load:
37172608c6946f80e733875aa4969c39740fcb012c17sewardj         subst_AvailExpr_TmpOrConst(&ae->u.Load.addr, env);
37182608c6946f80e733875aa4969c39740fcb012c17sewardj         break;
37192963239357452b96dbe6de1b3f8b626ea3305780sewardj      default:
37200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("subst_AvailExpr");
37212963239357452b96dbe6de1b3f8b626ea3305780sewardj   }
37222963239357452b96dbe6de1b3f8b626ea3305780sewardj}
37232963239357452b96dbe6de1b3f8b626ea3305780sewardj
37242608c6946f80e733875aa4969c39740fcb012c17sewardjstatic AvailExpr* irExpr_to_AvailExpr ( IRExpr* e, Bool allowLoadsToBeCSEd )
37252963239357452b96dbe6de1b3f8b626ea3305780sewardj{
37260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   AvailExpr* ae;
37270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3728c1b9e39e1a7407076cd48aa2704b398f547cb760florian   switch (e->tag) {
3729c1b9e39e1a7407076cd48aa2704b398f547cb760florian      case Iex_Unop:
3730c1b9e39e1a7407076cd48aa2704b398f547cb760florian         if (e->Iex.Unop.arg->tag == Iex_RdTmp) {
3731d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian            ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3732c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->tag      = Ut;
3733c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.Ut.op  = e->Iex.Unop.op;
3734c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.Ut.arg = e->Iex.Unop.arg->Iex.RdTmp.tmp;
3735c1b9e39e1a7407076cd48aa2704b398f547cb760florian            return ae;
3736c1b9e39e1a7407076cd48aa2704b398f547cb760florian         }
3737c1b9e39e1a7407076cd48aa2704b398f547cb760florian         break;
37380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3739c1b9e39e1a7407076cd48aa2704b398f547cb760florian      case Iex_Binop:
3740c1b9e39e1a7407076cd48aa2704b398f547cb760florian         if (e->Iex.Binop.arg1->tag == Iex_RdTmp) {
3741c1b9e39e1a7407076cd48aa2704b398f547cb760florian            if (e->Iex.Binop.arg2->tag == Iex_RdTmp) {
3742d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian               ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3743c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->tag        = Btt;
3744c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->u.Btt.op   = e->Iex.Binop.op;
3745c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->u.Btt.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3746c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->u.Btt.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
3747c1b9e39e1a7407076cd48aa2704b398f547cb760florian               return ae;
3748c1b9e39e1a7407076cd48aa2704b398f547cb760florian            }
3749c1b9e39e1a7407076cd48aa2704b398f547cb760florian            if (e->Iex.Binop.arg2->tag == Iex_Const) {
3750d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian               ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3751c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->tag        = Btc;
3752c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->u.Btc.op   = e->Iex.Binop.op;
3753c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->u.Btc.arg1 = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
3754c1b9e39e1a7407076cd48aa2704b398f547cb760florian               ae->u.Btc.con2 = *(e->Iex.Binop.arg2->Iex.Const.con);
3755c1b9e39e1a7407076cd48aa2704b398f547cb760florian               return ae;
3756c1b9e39e1a7407076cd48aa2704b398f547cb760florian            }
3757c1b9e39e1a7407076cd48aa2704b398f547cb760florian         } else if (e->Iex.Binop.arg1->tag == Iex_Const
3758c1b9e39e1a7407076cd48aa2704b398f547cb760florian                    && e->Iex.Binop.arg2->tag == Iex_RdTmp) {
3759d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian            ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3760c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->tag        = Bct;
3761c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.Bct.op   = e->Iex.Binop.op;
3762c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.Bct.arg2 = e->Iex.Binop.arg2->Iex.RdTmp.tmp;
3763c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.Bct.con1 = *(e->Iex.Binop.arg1->Iex.Const.con);
3764c1b9e39e1a7407076cd48aa2704b398f547cb760florian            return ae;
3765c1b9e39e1a7407076cd48aa2704b398f547cb760florian         }
3766c1b9e39e1a7407076cd48aa2704b398f547cb760florian         break;
37679b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
3768c1b9e39e1a7407076cd48aa2704b398f547cb760florian      case Iex_Const:
3769c1b9e39e1a7407076cd48aa2704b398f547cb760florian         if (e->Iex.Const.con->tag == Ico_F64i) {
3770d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian            ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3771c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->tag          = Cf64i;
3772c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.Cf64i.f64i = e->Iex.Const.con->Ico.F64i;
3773c1b9e39e1a7407076cd48aa2704b398f547cb760florian            return ae;
3774c1b9e39e1a7407076cd48aa2704b398f547cb760florian         }
3775c1b9e39e1a7407076cd48aa2704b398f547cb760florian         break;
3776da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian
377799dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
377899dd03e04a6914d90d5fee727d61d76905334becflorian         if (e->Iex.ITE.cond->tag == Iex_RdTmp) {
377999dd03e04a6914d90d5fee727d61d76905334becflorian            if (e->Iex.ITE.iffalse->tag == Iex_RdTmp) {
378099dd03e04a6914d90d5fee727d61d76905334becflorian               if (e->Iex.ITE.iftrue->tag == Iex_RdTmp) {
3781d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian                  ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3782b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->tag       = Ittt;
3783b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Ittt.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3784b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Ittt.e1 = e->Iex.ITE.iftrue->Iex.RdTmp.tmp;
3785b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Ittt.e0 = e->Iex.ITE.iffalse->Iex.RdTmp.tmp;
3786c1b9e39e1a7407076cd48aa2704b398f547cb760florian                  return ae;
3787c1b9e39e1a7407076cd48aa2704b398f547cb760florian               }
378899dd03e04a6914d90d5fee727d61d76905334becflorian               if (e->Iex.ITE.iftrue->tag == Iex_Const) {
3789d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian                  ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3790b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->tag       = Itct;
3791b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Itct.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3792b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Itct.con1 = *(e->Iex.ITE.iftrue->Iex.Const.con);
3793b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Itct.e0 = e->Iex.ITE.iffalse->Iex.RdTmp.tmp;
3794c1b9e39e1a7407076cd48aa2704b398f547cb760florian                  return ae;
3795c1b9e39e1a7407076cd48aa2704b398f547cb760florian               }
379699dd03e04a6914d90d5fee727d61d76905334becflorian            } else if (e->Iex.ITE.iffalse->tag == Iex_Const) {
379799dd03e04a6914d90d5fee727d61d76905334becflorian               if (e->Iex.ITE.iftrue->tag == Iex_RdTmp) {
3798d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian                  ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3799b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->tag       = Ittc;
3800b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Ittc.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3801b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Ittc.e1 = e->Iex.ITE.iftrue->Iex.RdTmp.tmp;
3802b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Ittc.con0 = *(e->Iex.ITE.iffalse->Iex.Const.con);
3803c1b9e39e1a7407076cd48aa2704b398f547cb760florian                  return ae;
3804c1b9e39e1a7407076cd48aa2704b398f547cb760florian               }
380599dd03e04a6914d90d5fee727d61d76905334becflorian               if (e->Iex.ITE.iftrue->tag == Iex_Const) {
3806d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian                  ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3807b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->tag       = Itcc;
3808b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Itcc.co = e->Iex.ITE.cond->Iex.RdTmp.tmp;
3809b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Itcc.con1 = *(e->Iex.ITE.iftrue->Iex.Const.con);
3810b05c20c80c7e76e2f2ef82eb7806672967638d6cflorian                  ae->u.Itcc.con0 = *(e->Iex.ITE.iffalse->Iex.Const.con);
3811c1b9e39e1a7407076cd48aa2704b398f547cb760florian                  return ae;
3812c1b9e39e1a7407076cd48aa2704b398f547cb760florian               }
3813c1b9e39e1a7407076cd48aa2704b398f547cb760florian            }
3814c1b9e39e1a7407076cd48aa2704b398f547cb760florian         }
3815c1b9e39e1a7407076cd48aa2704b398f547cb760florian         break;
3816da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian
3817c1b9e39e1a7407076cd48aa2704b398f547cb760florian      case Iex_GetI:
3818c1b9e39e1a7407076cd48aa2704b398f547cb760florian         if (e->Iex.GetI.ix->tag == Iex_RdTmp) {
3819d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian            ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3820c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->tag           = GetIt;
3821c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.GetIt.descr = e->Iex.GetI.descr;
3822c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.GetIt.ix    = e->Iex.GetI.ix->Iex.RdTmp.tmp;
3823c1b9e39e1a7407076cd48aa2704b398f547cb760florian            ae->u.GetIt.bias  = e->Iex.GetI.bias;
3824c1b9e39e1a7407076cd48aa2704b398f547cb760florian            return ae;
3825c1b9e39e1a7407076cd48aa2704b398f547cb760florian         }
3826c1b9e39e1a7407076cd48aa2704b398f547cb760florian         break;
3827da25eddcd3cf7661eb6c851b96d5431cc9f7773bflorian
3828c1b9e39e1a7407076cd48aa2704b398f547cb760florian      case Iex_CCall:
3829d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian         ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
3830c1b9e39e1a7407076cd48aa2704b398f547cb760florian         ae->tag = CCall;
3831c1b9e39e1a7407076cd48aa2704b398f547cb760florian         /* Ok to share only the cee, since it is immutable. */
3832c1b9e39e1a7407076cd48aa2704b398f547cb760florian         ae->u.CCall.cee   = e->Iex.CCall.cee;
3833c1b9e39e1a7407076cd48aa2704b398f547cb760florian         ae->u.CCall.retty = e->Iex.CCall.retty;
3834c1b9e39e1a7407076cd48aa2704b398f547cb760florian         /* irExprVec_to_TmpOrConsts will assert if the args are
3835c1b9e39e1a7407076cd48aa2704b398f547cb760florian            neither tmps nor constants, but that's ok .. that's all they
3836c1b9e39e1a7407076cd48aa2704b398f547cb760florian            should be. */
3837c1b9e39e1a7407076cd48aa2704b398f547cb760florian         irExprVec_to_TmpOrConsts(
3838c1b9e39e1a7407076cd48aa2704b398f547cb760florian                                  &ae->u.CCall.args, &ae->u.CCall.nArgs,
3839c1b9e39e1a7407076cd48aa2704b398f547cb760florian                                  e->Iex.CCall.args
3840c1b9e39e1a7407076cd48aa2704b398f547cb760florian                                 );
3841c1b9e39e1a7407076cd48aa2704b398f547cb760florian         return ae;
38429b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
38432608c6946f80e733875aa4969c39740fcb012c17sewardj      case Iex_Load:
38442608c6946f80e733875aa4969c39740fcb012c17sewardj         /* If the caller of do_cse_BB has requested that loads also
38452608c6946f80e733875aa4969c39740fcb012c17sewardj            be CSEd, convert them into AvailExprs.  If not, we'll just
38462608c6946f80e733875aa4969c39740fcb012c17sewardj            return NULL here, and the load never becomes considered
38472608c6946f80e733875aa4969c39740fcb012c17sewardj            "available", which effectively disables CSEing of them, as
38482608c6946f80e733875aa4969c39740fcb012c17sewardj            desired. */
38492608c6946f80e733875aa4969c39740fcb012c17sewardj         if (allowLoadsToBeCSEd) {
3850d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian            ae = LibVEX_Alloc_inline(sizeof(AvailExpr));
38512608c6946f80e733875aa4969c39740fcb012c17sewardj            ae->tag        = Load;
38522608c6946f80e733875aa4969c39740fcb012c17sewardj            ae->u.Load.end = e->Iex.Load.end;
38532608c6946f80e733875aa4969c39740fcb012c17sewardj            ae->u.Load.ty  = e->Iex.Load.ty;
38542608c6946f80e733875aa4969c39740fcb012c17sewardj            irExpr_to_TmpOrConst(&ae->u.Load.addr, e->Iex.Load.addr);
38552608c6946f80e733875aa4969c39740fcb012c17sewardj            return ae;
38562608c6946f80e733875aa4969c39740fcb012c17sewardj         }
38572608c6946f80e733875aa4969c39740fcb012c17sewardj         break;
38582608c6946f80e733875aa4969c39740fcb012c17sewardj
3859c1b9e39e1a7407076cd48aa2704b398f547cb760florian      default:
3860c1b9e39e1a7407076cd48aa2704b398f547cb760florian         break;
3861e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj   }
3862e85780480665d1a4c2d5f4b13db4f56adec97bf9sewardj
38630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return NULL;
38642963239357452b96dbe6de1b3f8b626ea3305780sewardj}
38652963239357452b96dbe6de1b3f8b626ea3305780sewardj
38662963239357452b96dbe6de1b3f8b626ea3305780sewardj
38679b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj/* The BB is modified in-place.  Returns True if any changes were
38682608c6946f80e733875aa4969c39740fcb012c17sewardj   made.  The caller can choose whether or not loads should be CSEd.
38692608c6946f80e733875aa4969c39740fcb012c17sewardj   In the normal course of things we don't do that, since CSEing loads
38702608c6946f80e733875aa4969c39740fcb012c17sewardj   is something of a dodgy proposition if the guest program is doing
38712608c6946f80e733875aa4969c39740fcb012c17sewardj   some screwy stuff to do with races and spinloops. */
38720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
38732608c6946f80e733875aa4969c39740fcb012c17sewardjstatic Bool do_cse_BB ( IRSB* bb, Bool allowLoadsToBeCSEd )
38742963239357452b96dbe6de1b3f8b626ea3305780sewardj{
38759b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   Int        i, j, paranoia;
38760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRTemp     t, q;
38770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt*    st;
38780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   AvailExpr* eprime;
38799b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   AvailExpr* ae;
38809b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   Bool       invalidate;
38819b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   Bool       anyDone = False;
38822963239357452b96dbe6de1b3f8b626ea3305780sewardj
38830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   HashHW* tenv = newHHW(); /* :: IRTemp -> IRTemp */
38840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   HashHW* aenv = newHHW(); /* :: AvailExpr* -> IRTemp */
38852963239357452b96dbe6de1b3f8b626ea3305780sewardj
38860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(sizeof(IRTemp) <= sizeof(HWord));
38872963239357452b96dbe6de1b3f8b626ea3305780sewardj
3888dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   if (0) { ppIRSB(bb); vex_printf("\n\n"); }
38892963239357452b96dbe6de1b3f8b626ea3305780sewardj
38900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Iterate forwards over the stmts.
3891cfe046e178666280b87da998b1b52ecda03ecd89sewardj      On seeing "t = E", where E is one of the AvailExpr forms:
38920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         let E' = apply tenv substitution to E
38930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         search aenv for E'
38940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if a mapping E' -> q is found,
38950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               replace this stmt by "t = q"
38960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               and add binding t -> q to tenv
38970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            else
38980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               add binding E' -> t to aenv
38990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               replace this stmt by "t = E'"
39009b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
39019b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      Other statements are only interesting to the extent that they
39029b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      might invalidate some of the expressions in aenv.  So there is
39039b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      an invalidate-bindings check for each statement seen.
39040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   */
39050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < bb->stmts_used; i++) {
39060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
39070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
39089b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      /* ------ BEGIN invalidate aenv bindings ------ */
39099b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      /* This is critical: remove from aenv any E' -> .. bindings
39109b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         which might be invalidated by this statement.  The only
39112608c6946f80e733875aa4969c39740fcb012c17sewardj         vulnerable kind of bindings are the GetI and Load kinds.
39129b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            Dirty call - dump (paranoia level -> 2)
39139b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            Store      - dump (ditto)
39149b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            Put, PutI  - dump unless no-overlap is proven (.. -> 1)
39159b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         Uses getAliasingRelation_IC and getAliasingRelation_II
39169b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         to do the no-overlap assessments needed for Put/PutI.
39179b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      */
39189b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      switch (st->tag) {
3919e768e92e054cde495849a5c842a477d287677f78sewardj         case Ist_Dirty: case Ist_Store: case Ist_MBE:
3920e768e92e054cde495849a5c842a477d287677f78sewardj         case Ist_CAS: case Ist_LLSC:
3921cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_StoreG:
39229b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            paranoia = 2; break;
39239b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         case Ist_Put: case Ist_PutI:
39249b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            paranoia = 1; break;
39259b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         case Ist_NoOp: case Ist_IMark: case Ist_AbiHint:
3926cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_WrTmp: case Ist_Exit: case Ist_LoadG:
39279b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            paranoia = 0; break;
39289b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         default:
39299b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            vpanic("do_cse_BB(1)");
39309b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      }
39319b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
39329b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      if (paranoia > 0) {
39339b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         for (j = 0; j < aenv->used; j++) {
39349b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            if (!aenv->inuse[j])
39359b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               continue;
39369b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            ae = (AvailExpr*)aenv->key[j];
39372608c6946f80e733875aa4969c39740fcb012c17sewardj            if (ae->tag != GetIt && ae->tag != Load)
39389b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               continue;
39399b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            invalidate = False;
39409b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            if (paranoia >= 2) {
39419b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               invalidate = True;
39429b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            } else {
39439b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               vassert(paranoia == 1);
39442608c6946f80e733875aa4969c39740fcb012c17sewardj               if (ae->tag == Load) {
39452608c6946f80e733875aa4969c39740fcb012c17sewardj                  /* Loads can be invalidated by anything that could
39462608c6946f80e733875aa4969c39740fcb012c17sewardj                     possibly touch memory.  But in that case we
39472608c6946f80e733875aa4969c39740fcb012c17sewardj                     should have |paranoia| == 2 and we won't get
39482608c6946f80e733875aa4969c39740fcb012c17sewardj                     here.  So there's nothing to do; we don't have to
39492608c6946f80e733875aa4969c39740fcb012c17sewardj                     invalidate the load. */
39502608c6946f80e733875aa4969c39740fcb012c17sewardj               }
39512608c6946f80e733875aa4969c39740fcb012c17sewardj               else
39529b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               if (st->tag == Ist_Put) {
39539b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                  if (getAliasingRelation_IC(
39549b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                         ae->u.GetIt.descr,
3955dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                         IRExpr_RdTmp(ae->u.GetIt.ix),
39569b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                         st->Ist.Put.offset,
39579b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                         typeOfIRExpr(bb->tyenv,st->Ist.Put.data)
39589b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                      ) != NoAlias)
39599b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                     invalidate = True;
39609b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               }
39619b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               else
39629b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               if (st->tag == Ist_PutI) {
3963d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                  IRPutI *puti = st->Ist.PutI.details;
39649b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                  if (getAliasingRelation_II(
39659b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                         ae->u.GetIt.descr,
3966dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                         IRExpr_RdTmp(ae->u.GetIt.ix),
39679b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                         ae->u.GetIt.bias,
3968d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                         puti->descr,
3969d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                         puti->ix,
3970d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                         puti->bias
39719b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                      ) != NoAlias)
39729b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                     invalidate = True;
39739b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               }
39749b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               else
39759b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj                  vpanic("do_cse_BB(2)");
39769b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            }
39779b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
39789b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            if (invalidate) {
39799b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               aenv->inuse[j] = False;
39809b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj               aenv->key[j]   = (HWord)NULL;  /* be sure */
39819b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            }
39829b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         } /* for j */
39839b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      } /* paranoia > 0 */
39849b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
39859b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      /* ------ ENV invalidate aenv bindings ------ */
39869b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj
39870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* ignore not-interestings */
3988dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag != Ist_WrTmp)
39890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
39900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
3991dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      t = st->Ist.WrTmp.tmp;
39922608c6946f80e733875aa4969c39740fcb012c17sewardj      eprime = irExpr_to_AvailExpr(st->Ist.WrTmp.data, allowLoadsToBeCSEd);
39930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* ignore if not of AvailExpr form */
39940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (!eprime)
39950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
39960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
39970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* vex_printf("considering: " ); ppIRStmt(st); vex_printf("\n"); */
39980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
39990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* apply tenv */
40000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      subst_AvailExpr( tenv, eprime );
40010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
40020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* search aenv for eprime, unfortunately the hard way */
40030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      for (j = 0; j < aenv->used; j++)
40040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (aenv->inuse[j] && eq_AvailExpr(eprime, (AvailExpr*)aenv->key[j]))
40050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
40062963239357452b96dbe6de1b3f8b626ea3305780sewardj
40070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (j < aenv->used) {
40080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* A binding E' -> q was found.  Replace stmt by "t = q" and
40090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            note the t->q binding in tenv. */
40100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* (this is the core of the CSE action) */
40110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         q = (IRTemp)aenv->val[j];
4012dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         bb->stmts[i] = IRStmt_WrTmp( t, IRExpr_RdTmp(q) );
40130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addToHHW( tenv, (HWord)t, (HWord)q );
40149b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         anyDone = True;
40150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      } else {
40160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* No binding was found, so instead we add E' -> t to our
40170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            collection of available expressions, replace this stmt
40180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            with "t = E'", and move on. */
4019dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         bb->stmts[i] = IRStmt_WrTmp( t, availExpr_to_IRExpr(eprime) );
40200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         addToHHW( aenv, (HWord)eprime, (HWord)t );
40210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
40220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
40230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
4024b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /*
4025dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   ppIRSB(bb);
4026dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   sanityCheckIRSB(bb, Ity_I32);
4027b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   vex_printf("\n\n");
4028b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   */
40299b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj   return anyDone;
40302963239357452b96dbe6de1b3f8b626ea3305780sewardj}
40312963239357452b96dbe6de1b3f8b626ea3305780sewardj
40322963239357452b96dbe6de1b3f8b626ea3305780sewardj
40330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
40340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Add32/Sub32 chain collapsing                            ---*/
40350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
40362963239357452b96dbe6de1b3f8b626ea3305780sewardj
40370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* ----- Helper functions for Add32/Sub32 chain collapsing ----- */
40382963239357452b96dbe6de1b3f8b626ea3305780sewardj
40390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Is this expression "Add32(tmp,const)" or "Sub32(tmp,const)" ?  If
40400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   yes, set *tmp and *i32 appropriately.  *i32 is set as if the
40410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   root node is Add32, not Sub32. */
4042c9ad1158a723378c239d80ef2b53dace839d6c0esewardj
40430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic Bool isAdd32OrSub32 ( IRExpr* e, IRTemp* tmp, Int* i32 )
40440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
40450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (e->tag != Iex_Binop)
40460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
40470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (e->Iex.Binop.op != Iop_Add32 && e->Iex.Binop.op != Iop_Sub32)
40480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
4049dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   if (e->Iex.Binop.arg1->tag != Iex_RdTmp)
40500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
40510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (e->Iex.Binop.arg2->tag != Iex_Const)
40520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
4053dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   *tmp = e->Iex.Binop.arg1->Iex.RdTmp.tmp;
40540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   *i32 = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32);
40550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (e->Iex.Binop.op == Iop_Sub32)
40560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      *i32 = -*i32;
40570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return True;
40580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
40592963239357452b96dbe6de1b3f8b626ea3305780sewardj
40602963239357452b96dbe6de1b3f8b626ea3305780sewardj
40610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Figure out if tmp can be expressed as tmp2 +32 const, for some
40620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   other tmp2.  Scan backwards from the specified start point -- an
40630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   optimisation. */
40642963239357452b96dbe6de1b3f8b626ea3305780sewardj
4065dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic Bool collapseChain ( IRSB* bb, Int startHere,
40660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                            IRTemp tmp,
40670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                            IRTemp* tmp2, Int* i32 )
40680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
40690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     j, ii;
40700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRTemp  vv;
40710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt* st;
40720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr* e;
40732963239357452b96dbe6de1b3f8b626ea3305780sewardj
40740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* the (var, con) pair contain the current 'representation' for
40750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      'tmp'.  We start with 'tmp + 0'.  */
40760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRTemp var = tmp;
40770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int    con = 0;
40782963239357452b96dbe6de1b3f8b626ea3305780sewardj
40790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Scan backwards to see if tmp can be replaced by some other tmp
40800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     +/- a constant. */
40810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (j = startHere; j >= 0; j--) {
40820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[j];
4083dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag != Ist_WrTmp)
40842963239357452b96dbe6de1b3f8b626ea3305780sewardj         continue;
4085dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->Ist.WrTmp.tmp != var)
40862963239357452b96dbe6de1b3f8b626ea3305780sewardj         continue;
4087dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      e = st->Ist.WrTmp.data;
40880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (!isAdd32OrSub32(e, &vv, &ii))
40890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
40900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      var = vv;
40910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      con += ii;
40922963239357452b96dbe6de1b3f8b626ea3305780sewardj   }
40930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (j == -1)
40940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* no earlier binding for var .. ill-formed IR */
40950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vpanic("collapseChain");
40962963239357452b96dbe6de1b3f8b626ea3305780sewardj
40970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* so, did we find anything interesting? */
40980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (var == tmp)
40990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False; /* no .. */
41000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
41010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   *tmp2 = var;
41020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   *i32  = con;
41030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return True;
41040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
41052963239357452b96dbe6de1b3f8b626ea3305780sewardj
41062963239357452b96dbe6de1b3f8b626ea3305780sewardj
41070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* ------- Main function for Add32/Sub32 chain collapsing ------ */
41082963239357452b96dbe6de1b3f8b626ea3305780sewardj
4109dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic void collapse_AddSub_chains_BB ( IRSB* bb )
41100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
41110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt *st;
41120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRTemp var, var2;
41130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int    i, con, con2;
41142963239357452b96dbe6de1b3f8b626ea3305780sewardj
41150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = bb->stmts_used-1; i >= 0; i--) {
41162963239357452b96dbe6de1b3f8b626ea3305780sewardj      st = bb->stmts[i];
41178bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
41182963239357452b96dbe6de1b3f8b626ea3305780sewardj         continue;
41192963239357452b96dbe6de1b3f8b626ea3305780sewardj
41200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Try to collapse 't1 = Add32/Sub32(t2, con)'. */
41212963239357452b96dbe6de1b3f8b626ea3305780sewardj
4122dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag == Ist_WrTmp
4123dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && isAdd32OrSub32(st->Ist.WrTmp.data, &var, &con)) {
41242963239357452b96dbe6de1b3f8b626ea3305780sewardj
41250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* So e1 is of the form Add32(var,con) or Sub32(var,-con).
41260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            Find out if var can be expressed as var2 + con2. */
41270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (collapseChain(bb, i-1, var, &var2, &con2)) {
41280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (DEBUG_IROPT) {
41290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("replacing1 ");
41300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               ppIRStmt(st);
41310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf(" with ");
41320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            }
41330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            con2 += con;
41340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            bb->stmts[i]
4135dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj               = IRStmt_WrTmp(
4136dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                    st->Ist.WrTmp.tmp,
41370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    (con2 >= 0)
41380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                      ? IRExpr_Binop(Iop_Add32,
4139dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                                     IRExpr_RdTmp(var2),
41400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                                     IRExpr_Const(IRConst_U32(con2)))
41410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                      : IRExpr_Binop(Iop_Sub32,
4142dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                                     IRExpr_RdTmp(var2),
41430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                                     IRExpr_Const(IRConst_U32(-con2)))
41440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 );
41450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            if (DEBUG_IROPT) {
41460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               ppIRStmt(bb->stmts[i]);
41470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("\n");
41480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            }
41490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
41502963239357452b96dbe6de1b3f8b626ea3305780sewardj
41510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
41520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
41530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
41540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Try to collapse 't1 = GetI[t2, con]'. */
41550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
4156dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag == Ist_WrTmp
4157dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && st->Ist.WrTmp.data->tag == Iex_GetI
4158dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp
4159dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && collapseChain(bb, i-1, st->Ist.WrTmp.data->Iex.GetI.ix
4160dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                                      ->Iex.RdTmp.tmp, &var2, &con2)) {
41610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (DEBUG_IROPT) {
41620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("replacing3 ");
41630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ppIRStmt(st);
41640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf(" with ");
41650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
4166dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         con2 += st->Ist.WrTmp.data->Iex.GetI.bias;
41670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         bb->stmts[i]
4168dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            = IRStmt_WrTmp(
4169dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                 st->Ist.WrTmp.tmp,
4170dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                 IRExpr_GetI(st->Ist.WrTmp.data->Iex.GetI.descr,
4171dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                             IRExpr_RdTmp(var2),
41720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                             con2));
41730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (DEBUG_IROPT) {
41740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ppIRStmt(bb->stmts[i]);
41750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("\n");
41760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
41770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
41782963239357452b96dbe6de1b3f8b626ea3305780sewardj      }
41792963239357452b96dbe6de1b3f8b626ea3305780sewardj
41800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Perhaps st is PutI[t, con] ? */
4181d6f38b3f822f7d57adfc0da3410995d85d6a4597florian      IRPutI *puti = st->Ist.PutI.details;
41820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_PutI
4183d6f38b3f822f7d57adfc0da3410995d85d6a4597florian          && puti->ix->tag == Iex_RdTmp
4184d6f38b3f822f7d57adfc0da3410995d85d6a4597florian          && collapseChain(bb, i-1, puti->ix->Iex.RdTmp.tmp,
41850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                               &var2, &con2)) {
41860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (DEBUG_IROPT) {
41870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("replacing2 ");
41880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ppIRStmt(st);
41890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf(" with ");
41900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
4191d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         con2 += puti->bias;
41920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         bb->stmts[i]
4193d6f38b3f822f7d57adfc0da3410995d85d6a4597florian            = IRStmt_PutI(mkIRPutI(puti->descr,
4194d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                                   IRExpr_RdTmp(var2),
4195d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                                   con2,
4196d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                                   puti->data));
41970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (DEBUG_IROPT) {
41980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ppIRStmt(bb->stmts[i]);
41990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("\n");
42000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
42010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
42020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
42032963239357452b96dbe6de1b3f8b626ea3305780sewardj
42040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   } /* for */
42052963239357452b96dbe6de1b3f8b626ea3305780sewardj}
42062963239357452b96dbe6de1b3f8b626ea3305780sewardj
42072963239357452b96dbe6de1b3f8b626ea3305780sewardj
4208f0e431671cb877601c2f2e551f42246469b4ee62sewardj/*---------------------------------------------------------------*/
42090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- PutI/GetI transformations                               ---*/
42104345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj/*---------------------------------------------------------------*/
42114345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Given the parts (descr, tmp, bias) for a GetI, scan backwards from
42130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   the given starting point to find, if any, a PutI which writes
42140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   exactly the same piece of guest state, and so return the expression
42150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   that the PutI writes.  This is the core of PutI-GetI forwarding. */
42160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
42170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic
4218dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjIRExpr* findPutI ( IRSB* bb, Int startHere,
4219dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                   IRRegArray* descrG, IRExpr* ixG, Int biasG )
42204345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj{
42210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int        j;
42220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt*    st;
42230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   GSAliasing relation;
42244345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (0) {
42260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf("\nfindPutI ");
4227dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRRegArray(descrG);
42280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf(" ");
42290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      ppIRExpr(ixG);
42300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf(" %d\n", biasG);
42314345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   }
42324345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Scan backwards in bb from startHere to find a suitable PutI
42340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      binding for (descrG, ixG, biasG), if any. */
42354345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (j = startHere; j >= 0; j--) {
42370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[j];
42388bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
42398bee6d15808653a71717c256a3abe96993439d25sewardj         continue;
42404345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Put) {
42420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* Non-indexed Put.  This can't give a binding, but we do
42430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            need to check it doesn't invalidate the search by
42440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            overlapping any part of the indexed guest state. */
4245c0b42285bc4b9aad872fbdd813b073eabc8d74basewardj
42460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         relation
42470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            = getAliasingRelation_IC(
42480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 descrG, ixG,
42490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 st->Ist.Put.offset,
42500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );
42518f31b3ba52f176a03faba5647aba6570bdeadba9sewardj
42520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (relation == NoAlias) {
42530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* we're OK; keep going */
42540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            continue;
42550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         } else {
42560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* relation == UnknownAlias || relation == ExactAlias */
42570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* If this assertion fails, we've found a Put which writes
42580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               an area of guest state which is read by a GetI.  Which
42590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               is unlikely (although not per se wrong). */
42600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vassert(relation != ExactAlias);
42610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* This Put potentially writes guest state that the GetI
42620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               reads; we must fail. */
42630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            return NULL;
42640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
42650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
42664345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_PutI) {
4268d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         IRPutI *puti = st->Ist.PutI.details;
42694345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         relation = getAliasingRelation_II(
42710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                       descrG, ixG, biasG,
4272d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                       puti->descr,
4273d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                       puti->ix,
4274d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                       puti->bias
42750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    );
42764345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (relation == NoAlias) {
42780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* This PutI definitely doesn't overlap.  Ignore it and
42790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               keep going. */
42800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            continue; /* the for j loop */
42810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
42824345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (relation == UnknownAlias) {
42840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* We don't know if this PutI writes to the same guest
42850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               state that the GetI, or not.  So we have to give up. */
42860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            return NULL;
42870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
4288ea602bc23ecabe934348ef9ea4113a22d4e0bb80sewardj
42890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* Otherwise, we've found what we're looking for.  */
42900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vassert(relation == ExactAlias);
4291d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         return puti->data;
42924345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      } /* if (st->tag == Ist_PutI) */
42944345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
42950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (st->tag == Ist_Dirty) {
42960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* Be conservative.  If the dirty call has any guest effects at
42970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            all, give up.  We could do better -- only give up if there
42980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            are any guest writes/modifies. */
42990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (st->Ist.Dirty.details->nFxState > 0)
43000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            return NULL;
43010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
43024345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
43030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   } /* for */
43044345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
43050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* No valid replacement was found. */
43060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return NULL;
43070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
43084345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
43094345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
43104345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
43110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Assuming pi is a PutI stmt, is s2 identical to it (in the sense
43120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   that it writes exactly the same piece of guest state) ?  Safe
43130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   answer: False. */
43144345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
43150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic Bool identicalPutIs ( IRStmt* pi, IRStmt* s2 )
43160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
43170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(pi->tag == Ist_PutI);
43180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (s2->tag != Ist_PutI)
43190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
43204345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
4321d6f38b3f822f7d57adfc0da3410995d85d6a4597florian   IRPutI *p1 = pi->Ist.PutI.details;
4322d6f38b3f822f7d57adfc0da3410995d85d6a4597florian   IRPutI *p2 = s2->Ist.PutI.details;
4323d6f38b3f822f7d57adfc0da3410995d85d6a4597florian
43249d2e769a9368d2b22c32a4764a70e9da38769628sewardj   return toBool(
43259d2e769a9368d2b22c32a4764a70e9da38769628sewardj          getAliasingRelation_II(
4326d6f38b3f822f7d57adfc0da3410995d85d6a4597florian             p1->descr, p1->ix, p1->bias,
4327d6f38b3f822f7d57adfc0da3410995d85d6a4597florian             p2->descr, p2->ix, p2->bias
43280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          )
43299d2e769a9368d2b22c32a4764a70e9da38769628sewardj          == ExactAlias
43309d2e769a9368d2b22c32a4764a70e9da38769628sewardj          );
43314345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj}
43324345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
4333a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
43340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Assuming pi is a PutI stmt, is s2 a Get/GetI/Put/PutI which might
43350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   overlap it?  Safe answer: True.  Note, we could do a lot better
43360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   than this if needed. */
4337728c9d59db14f528e3d47a5c2bf2027407ea133esewardj
43380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic
43390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjBool guestAccessWhichMightOverlapPutI (
43400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        IRTypeEnv* tyenv, IRStmt* pi, IRStmt* s2
43410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     )
43420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
43430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   GSAliasing relation;
43440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   UInt       minoffP, maxoffP;
43450ec972d3d99377267d6ba990045f6db970363047sewardj
43460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(pi->tag == Ist_PutI);
4347d6f38b3f822f7d57adfc0da3410995d85d6a4597florian
4348d6f38b3f822f7d57adfc0da3410995d85d6a4597florian   IRPutI *p1 = pi->Ist.PutI.details;
4349d6f38b3f822f7d57adfc0da3410995d85d6a4597florian
4350d6f38b3f822f7d57adfc0da3410995d85d6a4597florian   getArrayBounds(p1->descr, &minoffP, &maxoffP);
43510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (s2->tag) {
4352a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4353d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
4354f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
4355f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj         return False;
4356f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj
4357c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
43585a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
43595a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         /* just be paranoid ... these should be rare. */
4360bb3f52db829c572ec04002392e8a5056b63affb3sewardj         return True;
4361bb3f52db829c572ec04002392e8a5056b63affb3sewardj
4362e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
4363e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* This is unbelievably lame, but it's probably not
4364e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            significant from a performance point of view.  Really, a
4365e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            CAS is a load-store op, so it should be safe to say False.
4366e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            However .. */
4367e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return True;
4368e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
43690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Dirty:
43700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* If the dirty call has any guest effects at all, give up.
43710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            Probably could do better. */
43720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (s2->Ist.Dirty.details->nFxState > 0)
43730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            return True;
43740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return False;
4375728c9d59db14f528e3d47a5c2bf2027407ea133esewardj
43760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Put:
4377496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj         vassert(isIRAtom(s2->Ist.Put.data));
43780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         relation
43790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            = getAliasingRelation_IC(
4380d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                 p1->descr, p1->ix,
43810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 s2->Ist.Put.offset,
43820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 typeOfIRExpr(tyenv,s2->Ist.Put.data)
43830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj              );
43840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         goto have_relation;
4385a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4386d6f38b3f822f7d57adfc0da3410995d85d6a4597florian      case Ist_PutI: {
4387d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         IRPutI *p2 = s2->Ist.PutI.details;
4388d6f38b3f822f7d57adfc0da3410995d85d6a4597florian
4389d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         vassert(isIRAtom(p2->ix));
4390d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         vassert(isIRAtom(p2->data));
43910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         relation
43920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            = getAliasingRelation_II(
4393d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                 p1->descr, p1->ix, p1->bias,
4394d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                 p2->descr, p2->ix, p2->bias
43950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj              );
43960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         goto have_relation;
4397d6f38b3f822f7d57adfc0da3410995d85d6a4597florian      }
4398a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4399dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
4400dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (s2->Ist.WrTmp.data->tag == Iex_GetI) {
44010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            relation
44020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               = getAliasingRelation_II(
4403d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                    p1->descr, p1->ix, p1->bias,
4404dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                    s2->Ist.WrTmp.data->Iex.GetI.descr,
4405dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                    s2->Ist.WrTmp.data->Iex.GetI.ix,
4406dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                    s2->Ist.WrTmp.data->Iex.GetI.bias
44070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 );
44080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            goto have_relation;
44090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
4410dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (s2->Ist.WrTmp.data->tag == Iex_Get) {
44110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            relation
44120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               = getAliasingRelation_IC(
4413d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                    p1->descr, p1->ix,
4414dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                    s2->Ist.WrTmp.data->Iex.Get.offset,
4415dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                    s2->Ist.WrTmp.data->Iex.Get.ty
44160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                 );
44170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            goto have_relation;
44180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
44190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return False;
4420a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4421af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
4422af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(s2->Ist.Store.addr));
4423af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         vassert(isIRAtom(s2->Ist.Store.data));
44240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return False;
4425a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
44260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
44270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n"); ppIRStmt(s2); vex_printf("\n");
44280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("guestAccessWhichMightOverlapPutI");
4429a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj   }
4430a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
44310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj  have_relation:
44320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (relation == NoAlias)
44330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return False;
44340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   else
44350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return True; /* ExactAlias or UnknownAlias */
4436a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj}
4437a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4438a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4439575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
44400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* ---------- PutI/GetI transformations main functions --------- */
44410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
44420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Remove redundant GetIs, to the extent that they can be detected.
44430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   bb is modified in-place. */
44440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
44450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic
4446dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjvoid do_redundant_GetI_elimination ( IRSB* bb )
4447575670caec4ae3cb4f3b9395fc9a9837b12432besewardj{
44480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int     i;
44490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt* st;
4450575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4451575670caec4ae3cb4f3b9395fc9a9837b12432besewardj   for (i = bb->stmts_used-1; i >= 0; i--) {
4452575670caec4ae3cb4f3b9395fc9a9837b12432besewardj      st = bb->stmts[i];
44538bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
4454575670caec4ae3cb4f3b9395fc9a9837b12432besewardj         continue;
4455575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4456dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag == Ist_WrTmp
4457dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && st->Ist.WrTmp.data->tag == Iex_GetI
4458dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj          && st->Ist.WrTmp.data->Iex.GetI.ix->tag == Iex_RdTmp) {
4459dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         IRRegArray* descr = st->Ist.WrTmp.data->Iex.GetI.descr;
4460dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         IRExpr*     ix    = st->Ist.WrTmp.data->Iex.GetI.ix;
4461dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         Int         bias  = st->Ist.WrTmp.data->Iex.GetI.bias;
4462dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         IRExpr*     replacement = findPutI(bb, i-1, descr, ix, bias);
44630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (replacement
4464496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj             && isIRAtom(replacement)
44650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj             /* Make sure we're doing a type-safe transformation! */
44660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj             && typeOfIRExpr(bb->tyenv, replacement) == descr->elemTy) {
4467575670caec4ae3cb4f3b9395fc9a9837b12432besewardj            if (DEBUG_IROPT) {
44680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf("rGI:  ");
4469dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj               ppIRExpr(st->Ist.WrTmp.data);
44700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               vex_printf(" -> ");
44710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj               ppIRExpr(replacement);
4472575670caec4ae3cb4f3b9395fc9a9837b12432besewardj               vex_printf("\n");
4473575670caec4ae3cb4f3b9395fc9a9837b12432besewardj            }
4474dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            bb->stmts[i] = IRStmt_WrTmp(st->Ist.WrTmp.tmp, replacement);
4475575670caec4ae3cb4f3b9395fc9a9837b12432besewardj         }
4476575670caec4ae3cb4f3b9395fc9a9837b12432besewardj      }
44770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
4478575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
44790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
4480575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4481575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
44820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Remove redundant PutIs, to the extent which they can be detected.
44830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   bb is modified in-place. */
4484575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
44850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic
4486ca2c3c75784d35d136fc7c952717cdee5063c193sewardjvoid do_redundant_PutI_elimination ( IRSB* bb, VexRegisterUpdates pxControl )
44870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
44880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int    i, j;
44890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Bool   delete;
44900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt *st, *stj;
44910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
4492ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   vassert(pxControl < VexRegUpdAllregsAtEachInsn);
4493c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe
44940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < bb->stmts_used; i++) {
44950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
44968bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag != Ist_PutI)
44970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
44980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* Ok, search forwards from here to see if we can find another
44990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         PutI which makes this one redundant, and dodging various
45000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         hazards.  Search forwards:
45010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         * If conditional exit, give up (because anything after that
45020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           does not postdominate this put).
45030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         * If a Get which might overlap, give up (because this PutI
45040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           not necessarily dead).
45050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         * If a Put which is identical, stop with success.
45060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         * If a Put which might overlap, but is not identical, give up.
45070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         * If a dirty helper call which might write guest state, give up.
45080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         * If a Put which definitely doesn't overlap, or any other
45090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           kind of stmt, continue.
45100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      */
45110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      delete = False;
45120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      for (j = i+1; j < bb->stmts_used; j++) {
45130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         stj = bb->stmts[j];
45148bee6d15808653a71717c256a3abe96993439d25sewardj         if (stj->tag == Ist_NoOp)
45150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            continue;
45160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (identicalPutIs(st, stj)) {
45170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* success! */
45180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            delete = True;
45190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
4520575670caec4ae3cb4f3b9395fc9a9837b12432besewardj         }
45210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (stj->tag == Ist_Exit)
45220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* give up */
45230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
45240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (st->tag == Ist_Dirty)
45250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* give up; could do better here */
45260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            break;
45270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (guestAccessWhichMightOverlapPutI(bb->tyenv, st, stj))
45280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            /* give up */
45290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           break;
45300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
45310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
45320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (delete) {
4533575670caec4ae3cb4f3b9395fc9a9837b12432besewardj         if (DEBUG_IROPT) {
45340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            vex_printf("rPI:  ");
45350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            ppIRStmt(st);
4536575670caec4ae3cb4f3b9395fc9a9837b12432besewardj            vex_printf("\n");
4537575670caec4ae3cb4f3b9395fc9a9837b12432besewardj         }
4538d2445f60726580b450eca68ab40c568f9df338e2sewardj         bb->stmts[i] = IRStmt_NoOp();
45390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
4540c819ec16063dab2ec6687da273e58808a3f00a20sewardj
45410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
45420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
4543575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4544575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
45450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
45460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- Loop unrolling                                          ---*/
45470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
4548575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
45490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Adjust all tmp values (names) in e by delta.  e is destructively
45500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   modified. */
4551575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
45520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void deltaIRExpr ( IRExpr* e, Int delta )
45530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
45540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int i;
45550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (e->tag) {
4556dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp:
4557dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         e->Iex.RdTmp.tmp += delta;
45580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
45590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Get:
45600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Const:
45610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
45620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_GetI:
45630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(e->Iex.GetI.ix, delta);
45640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
45651a866b465f5c92df796a5867cd65ac6dec31450bsewardj      case Iex_Qop:
456696d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         deltaIRExpr(e->Iex.Qop.details->arg1, delta);
456796d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         deltaIRExpr(e->Iex.Qop.details->arg2, delta);
456896d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         deltaIRExpr(e->Iex.Qop.details->arg3, delta);
456996d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         deltaIRExpr(e->Iex.Qop.details->arg4, delta);
45701a866b465f5c92df796a5867cd65ac6dec31450bsewardj         break;
4571b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      case Iex_Triop:
4572420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         deltaIRExpr(e->Iex.Triop.details->arg1, delta);
4573420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         deltaIRExpr(e->Iex.Triop.details->arg2, delta);
4574420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         deltaIRExpr(e->Iex.Triop.details->arg3, delta);
4575b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         break;
45760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Binop:
45770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(e->Iex.Binop.arg1, delta);
45780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(e->Iex.Binop.arg2, delta);
45790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
45800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Unop:
45810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(e->Iex.Unop.arg, delta);
45820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
4583af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Iex_Load:
4584af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         deltaIRExpr(e->Iex.Load.addr, delta);
45850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
45860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_CCall:
45870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (i = 0; e->Iex.CCall.args[i]; i++)
45880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            deltaIRExpr(e->Iex.CCall.args[i], delta);
45890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
459099dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
459199dd03e04a6914d90d5fee727d61d76905334becflorian         deltaIRExpr(e->Iex.ITE.cond, delta);
459299dd03e04a6914d90d5fee727d61d76905334becflorian         deltaIRExpr(e->Iex.ITE.iftrue, delta);
459399dd03e04a6914d90d5fee727d61d76905334becflorian         deltaIRExpr(e->Iex.ITE.iffalse, delta);
45940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
45950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
45960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
45970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("deltaIRExpr");
45980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
45990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
4600575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Adjust all tmp values (names) in st by delta.  st is destructively
46020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   modified. */
4603575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjstatic void deltaIRStmt ( IRStmt* st, Int delta )
46050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
46060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      i;
46070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRDirty* d;
46080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (st->tag) {
4609d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
4610f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
4611c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
4612f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj         break;
46135a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
46145a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         deltaIRExpr(st->Ist.AbiHint.base, delta);
4615478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         deltaIRExpr(st->Ist.AbiHint.nia, delta);
46165a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         break;
46170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Put:
46180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(st->Ist.Put.data, delta);
46190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
46200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_PutI:
4621d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         deltaIRExpr(st->Ist.PutI.details->ix, delta);
4622d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         deltaIRExpr(st->Ist.PutI.details->data, delta);
46230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
4624dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
4625dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         st->Ist.WrTmp.tmp += delta;
4626dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         deltaIRExpr(st->Ist.WrTmp.data, delta);
46270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
46280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Exit:
46290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(st->Ist.Exit.guard, delta);
46300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
4631af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
4632af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         deltaIRExpr(st->Ist.Store.addr, delta);
4633af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         deltaIRExpr(st->Ist.Store.data, delta);
46340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
4635cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG: {
4636cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRStoreG* sg = st->Ist.StoreG.details;
4637cfe046e178666280b87da998b1b52ecda03ecd89sewardj         deltaIRExpr(sg->addr, delta);
4638cfe046e178666280b87da998b1b52ecda03ecd89sewardj         deltaIRExpr(sg->data, delta);
4639cfe046e178666280b87da998b1b52ecda03ecd89sewardj         deltaIRExpr(sg->guard, delta);
4640cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
4641cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
4642cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG: {
4643cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRLoadG* lg = st->Ist.LoadG.details;
4644cfe046e178666280b87da998b1b52ecda03ecd89sewardj         lg->dst += delta;
4645cfe046e178666280b87da998b1b52ecda03ecd89sewardj         deltaIRExpr(lg->addr, delta);
4646cfe046e178666280b87da998b1b52ecda03ecd89sewardj         deltaIRExpr(lg->alt, delta);
4647cfe046e178666280b87da998b1b52ecda03ecd89sewardj         deltaIRExpr(lg->guard, delta);
4648cfe046e178666280b87da998b1b52ecda03ecd89sewardj         break;
4649cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
4650e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
4651e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (st->Ist.CAS.details->oldHi != IRTemp_INVALID)
4652e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            st->Ist.CAS.details->oldHi += delta;
4653e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         st->Ist.CAS.details->oldLo += delta;
4654e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         deltaIRExpr(st->Ist.CAS.details->addr, delta);
4655e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (st->Ist.CAS.details->expdHi)
4656e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            deltaIRExpr(st->Ist.CAS.details->expdHi, delta);
4657e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         deltaIRExpr(st->Ist.CAS.details->expdLo, delta);
4658e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (st->Ist.CAS.details->dataHi)
4659e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            deltaIRExpr(st->Ist.CAS.details->dataHi, delta);
4660e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         deltaIRExpr(st->Ist.CAS.details->dataLo, delta);
4661e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         break;
4662e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
4663e768e92e054cde495849a5c842a477d287677f78sewardj         st->Ist.LLSC.result += delta;
4664e768e92e054cde495849a5c842a477d287677f78sewardj         deltaIRExpr(st->Ist.LLSC.addr, delta);
4665e768e92e054cde495849a5c842a477d287677f78sewardj         if (st->Ist.LLSC.storedata)
4666e768e92e054cde495849a5c842a477d287677f78sewardj            deltaIRExpr(st->Ist.LLSC.storedata, delta);
4667e768e92e054cde495849a5c842a477d287677f78sewardj         break;
46680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Dirty:
46690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         d = st->Ist.Dirty.details;
46700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRExpr(d->guard, delta);
46712accb5e847cb35149c673e0eefc21baaa723a967florian         for (i = 0; d->args[i]; i++) {
46722accb5e847cb35149c673e0eefc21baaa723a967florian            IRExpr* arg = d->args[i];
4673ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
46742accb5e847cb35149c673e0eefc21baaa723a967florian               deltaIRExpr(arg, delta);
46752accb5e847cb35149c673e0eefc21baaa723a967florian         }
46760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (d->tmp != IRTemp_INVALID)
46770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            d->tmp += delta;
46780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (d->mAddr)
46790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            deltaIRExpr(d->mAddr, delta);
46800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
46810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
46820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
46830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vpanic("deltaIRStmt");
46840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
46850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
4686575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4687575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* If possible, return a loop-unrolled version of bb0.  The original
46890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   is changed.  If not possible, return NULL.  */
4690575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* The two schemas considered are:
4692575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     X: BODY; goto X
4694575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj     which unrolls to (eg)  X: BODY;BODY; goto X
4696575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   and
4698575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
46990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj       X: BODY; if (c) goto X; goto Y
47000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   which trivially transforms to
47010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj       X: BODY; if (!c) goto Y; goto X;
47020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   so it falls in the scope of the first case.
4703575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
47040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   X and Y must be literal (guest) addresses.
47050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj*/
4706575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4707dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic Int calc_unroll_factor( IRSB* bb )
4708575670caec4ae3cb4f3b9395fc9a9837b12432besewardj{
47090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int n_stmts, i;
4710575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
47110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   n_stmts = 0;
47120ddbf79767d1dbfad1465e7871247e046536a135sewardj   for (i = 0; i < bb->stmts_used; i++) {
47130ddbf79767d1dbfad1465e7871247e046536a135sewardj      if (bb->stmts[i]->tag != Ist_NoOp)
47140ddbf79767d1dbfad1465e7871247e046536a135sewardj         n_stmts++;
47150ddbf79767d1dbfad1465e7871247e046536a135sewardj   }
4716575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
47170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (n_stmts <= vex_control.iropt_unroll_thresh/8) {
47180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (vex_control.iropt_verbosity > 0)
47190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("vex iropt: 8 x unrolling (%d sts -> %d sts)\n",
47200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    n_stmts, 8* n_stmts);
47210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return 8;
47220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
47230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (n_stmts <= vex_control.iropt_unroll_thresh/4) {
47240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (vex_control.iropt_verbosity > 0)
47250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("vex iropt: 4 x unrolling (%d sts -> %d sts)\n",
47260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    n_stmts, 4* n_stmts);
47270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return 4;
47280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
4729575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
47300821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (n_stmts <= vex_control.iropt_unroll_thresh/2) {
47310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (vex_control.iropt_verbosity > 0)
47320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("vex iropt: 2 x unrolling (%d sts -> %d sts)\n",
47330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    n_stmts, 2* n_stmts);
47340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return 2;
4735575670caec4ae3cb4f3b9395fc9a9837b12432besewardj   }
4736575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
47370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (vex_control.iropt_verbosity > 0)
47380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf("vex iropt: not unrolling (%d sts)\n", n_stmts);
4739575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
47400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return 1;
4741575670caec4ae3cb4f3b9395fc9a9837b12432besewardj}
4742575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4743575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
4744d4cc0deec55ec0be1f2ac3b20f0d340265341f83florianstatic IRSB* maybe_loop_unroll_BB ( IRSB* bb0, Addr my_addr )
4745e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj{
47460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      i, j, jmax, n_vars;
47470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Bool     xxx_known;
47480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Addr64   xxx_value, yyy_value;
47490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr*  udst;
47500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt*  st;
47510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRConst* con;
4752dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   IRSB     *bb1, *bb2;
47530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      unroll_factor;
47543e2ba0ab79fdd03585492b1434a04b0eb34894bfsewardj
47550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (vex_control.iropt_unroll_thresh <= 0)
47560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
47570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
47580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* First off, figure out if we can unroll this loop.  Do this
47590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      without modifying bb0. */
47600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
47610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (bb0->jumpkind != Ijk_Boring)
47620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
47630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
47640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   xxx_known = False;
47650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   xxx_value = 0;
47660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
47670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Extract the next-guest address.  If it isn't a literal, we
47680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      have to give up. */
47690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
47700821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   udst = bb0->next;
47710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (udst->tag == Iex_Const
47720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj       && (udst->Iex.Const.con->tag == Ico_U32
47730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           || udst->Iex.Const.con->tag == Ico_U64)) {
47740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* The BB ends in a jump to a literal location. */
47750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      xxx_known = True;
47760821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      xxx_value = udst->Iex.Const.con->tag == Ico_U64
47770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    ?  udst->Iex.Const.con->Ico.U64
47780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                    : (Addr64)(udst->Iex.Const.con->Ico.U32);
47793e2ba0ab79fdd03585492b1434a04b0eb34894bfsewardj   }
47803e2ba0ab79fdd03585492b1434a04b0eb34894bfsewardj
47810821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (!xxx_known)
47820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
4783e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
47840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Now we know the BB ends to a jump to a literal location.  If
47850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      it's a jump to itself (viz, idiom #1), move directly to the
47860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      unrolling stage, first cloning the bb so the original isn't
47870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      modified. */
47880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (xxx_value == my_addr) {
47890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      unroll_factor = calc_unroll_factor( bb0 );
47900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (unroll_factor < 2)
47910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return NULL;
4792dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      bb1 = deepCopyIRSB( bb0 );
47930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      bb0 = NULL;
47940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      udst = NULL; /* is now invalid */
47950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      goto do_unroll;
47960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
4797e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
47980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Search for the second idiomatic form:
47990821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        X: BODY; if (c) goto X; goto Y
48000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      We know Y, but need to establish that the last stmt
48010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      is 'if (c) goto X'.
48020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   */
48030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   yyy_value = xxx_value;
48040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = bb0->stmts_used-1; i >= 0; i--)
48050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (bb0->stmts[i])
48060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
48070ec972d3d99377267d6ba990045f6db970363047sewardj
48080821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (i < 0)
48090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL; /* block with no stmts.  Strange. */
48100ec972d3d99377267d6ba990045f6db970363047sewardj
48110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   st = bb0->stmts[i];
48120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (st->tag != Ist_Exit)
48130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
48140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (st->Ist.Exit.jk != Ijk_Boring)
48150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
4816e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
48170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   con = st->Ist.Exit.dst;
48180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
48190ec972d3d99377267d6ba990045f6db970363047sewardj
48200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   xxx_value = con->tag == Ico_U64
48210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  ? st->Ist.Exit.dst->Ico.U64
48220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                  : (Addr64)(st->Ist.Exit.dst->Ico.U32);
48230ec972d3d99377267d6ba990045f6db970363047sewardj
48240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* If this assertion fails, we have some kind of type error. */
48250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(con->tag == udst->Iex.Const.con->tag);
4826e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
48270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (xxx_value != my_addr)
48280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* We didn't find either idiom.  Give up. */
48290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
4830e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
48310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Ok, we found idiom #2.  Copy the BB, switch around the xxx and
48320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      yyy values (which makes it look like idiom #1), and go into
48330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      unrolling proper.  This means finding (again) the last stmt, in
48340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      the copied BB. */
48350ec972d3d99377267d6ba990045f6db970363047sewardj
48360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   unroll_factor = calc_unroll_factor( bb0 );
48370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (unroll_factor < 2)
48380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      return NULL;
4839e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
4840dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   bb1 = deepCopyIRSB( bb0 );
48410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   bb0 = NULL;
48420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   udst = NULL; /* is now invalid */
48430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = bb1->stmts_used-1; i >= 0; i--)
48440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      if (bb1->stmts[i])
48450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         break;
4846eb30964230574023e99952904bb108625b6403e7sewardj
48470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* The next bunch of assertions should be true since we already
48480821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      found and checked the last stmt in the original bb. */
4849e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
48500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(i >= 0);
4851e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
48520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   st = bb1->stmts[i];
48530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(st->tag == Ist_Exit);
4854e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
48550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   con = st->Ist.Exit.dst;
48560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(con->tag == Ico_U32 || con->tag == Ico_U64);
4857a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48580821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   udst = bb1->next;
48590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(udst->tag == Iex_Const);
48600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(udst->Iex.Const.con->tag == Ico_U32
48610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj          || udst->Iex.Const.con->tag == Ico_U64);
48620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(con->tag == udst->Iex.Const.con->tag);
4863575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
48640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* switch the xxx and yyy fields around */
48650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (con->tag == Ico_U64) {
48660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      udst->Iex.Const.con->Ico.U64 = xxx_value;
48670821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      con->Ico.U64 = yyy_value;
48680821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   } else {
48690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      udst->Iex.Const.con->Ico.U32 = (UInt)xxx_value;
487057b4c6dadda048b86f99d286c4ddbefc69cfe670cerion      con->Ico.U32 = (UInt)yyy_value;
48710821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
4872a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* negate the test condition */
48740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   st->Ist.Exit.guard
4875dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      = IRExpr_Unop(Iop_Not1,deepCopyIRExpr(st->Ist.Exit.guard));
4876a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* --- The unroller proper.  Both idioms are by now --- */
48780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* --- now converted to idiom 1. --- */
4879a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj  do_unroll:
4881a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   vassert(unroll_factor == 2
48830821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           || unroll_factor == 4
48840821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj           || unroll_factor == 8);
4885a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   jmax = unroll_factor==8 ? 3 : (unroll_factor==4 ? 2 : 1);
48870821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (j = 1; j <= jmax; j++) {
4888a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      n_vars = bb1->tyenv->types_used;
4890ae27ab65d3bb9cc82520ebd3454a6bee3e95e21asewardj
4891dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      bb2 = deepCopyIRSB(bb1);
48920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      for (i = 0; i < n_vars; i++)
48930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         (void)newIRTemp(bb1->tyenv, bb2->tyenv->types[i]);
4894a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
48950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      for (i = 0; i < bb2->stmts_used; i++) {
48960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         /* deltaIRStmt destructively modifies the stmt, but
48970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            that's OK since bb2 is a complete fresh copy of bb1. */
48980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         deltaIRStmt(bb2->stmts[i], n_vars);
4899dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addStmtToIRSB(bb1, bb2->stmts[i]);
49000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
49010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
4902575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
49030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (DEBUG_IROPT) {
4904d4cc0deec55ec0be1f2ac3b20f0d340265341f83florian      vex_printf("\nUNROLLED (%lx)\n", my_addr);
4905dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb1);
49060821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vex_printf("\n");
49070821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
4908a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
49090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Flattening; sigh.  The unroller succeeds in breaking flatness
49100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      by negating the test condition.  This should be fixed properly.
49110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      For the moment use this shotgun approach.  */
49120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   return flatten_BB(bb1);
49130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
4914a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
49150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
49160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
49170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*--- The tree builder                                        ---*/
49180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/*---------------------------------------------------------------*/
49190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
49200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* This isn't part of IR optimisation.  Really it's a pass done prior
49210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   to instruction selection, which improves the code that the
49220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   instruction selector can produce. */
49230821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
4924f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* --- The 'tmp' environment is the central data structure here --- */
4925f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
4926f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* The number of outstanding bindings we're prepared to track.
4927f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   The number of times the env becomes full and we have to dump
4928f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   the oldest binding (hence reducing code quality) falls very
4929f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   rapidly as the env size increases.  8 gives reasonable performance
4930f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   under most circumstances. */
4931f9517d0d452899780e8c34f02bef004ef7c5a163sewardj#define A_NENV 10
4932f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
4933740da72e3938e8474234420777c17c1a4be6cb6fflorian/* An interval. Used to record the bytes in the guest state accessed
4934740da72e3938e8474234420777c17c1a4be6cb6fflorian   by a Put[I] statement or by (one or more) Get[I] expression(s). In
4935740da72e3938e8474234420777c17c1a4be6cb6fflorian   case of several Get[I] expressions, the lower/upper bounds are recorded.
4936740da72e3938e8474234420777c17c1a4be6cb6fflorian   This is conservative but cheap.
4937740da72e3938e8474234420777c17c1a4be6cb6fflorian   E.g. a Put of 8 bytes at address 100 would be recorded as [100,107].
4938740da72e3938e8474234420777c17c1a4be6cb6fflorian   E.g. an expression that reads 8 bytes at offset 100 and 4 bytes at
4939740da72e3938e8474234420777c17c1a4be6cb6fflorian   offset 200 would be recorded as [100,203] */
4940740da72e3938e8474234420777c17c1a4be6cb6ffloriantypedef
4941740da72e3938e8474234420777c17c1a4be6cb6fflorian   struct {
4942740da72e3938e8474234420777c17c1a4be6cb6fflorian      Bool present;
4943740da72e3938e8474234420777c17c1a4be6cb6fflorian      Int  low;
4944740da72e3938e8474234420777c17c1a4be6cb6fflorian      Int  high;
4945740da72e3938e8474234420777c17c1a4be6cb6fflorian   }
4946740da72e3938e8474234420777c17c1a4be6cb6fflorian   Interval;
4947740da72e3938e8474234420777c17c1a4be6cb6fflorian
4948740da72e3938e8474234420777c17c1a4be6cb6fflorianstatic inline Bool
4949740da72e3938e8474234420777c17c1a4be6cb6fflorianintervals_overlap(Interval i1, Interval i2)
4950740da72e3938e8474234420777c17c1a4be6cb6fflorian{
4951740da72e3938e8474234420777c17c1a4be6cb6fflorian   return (i1.low >= i2.low && i1.low <= i2.high) ||
4952740da72e3938e8474234420777c17c1a4be6cb6fflorian          (i2.low >= i1.low && i2.low <= i1.high);
4953740da72e3938e8474234420777c17c1a4be6cb6fflorian}
4954740da72e3938e8474234420777c17c1a4be6cb6fflorian
4955740da72e3938e8474234420777c17c1a4be6cb6fflorianstatic inline void
4956740da72e3938e8474234420777c17c1a4be6cb6fflorianupdate_interval(Interval *i, Int low, Int high)
4957740da72e3938e8474234420777c17c1a4be6cb6fflorian{
4958740da72e3938e8474234420777c17c1a4be6cb6fflorian   vassert(low <= high);
4959740da72e3938e8474234420777c17c1a4be6cb6fflorian
4960740da72e3938e8474234420777c17c1a4be6cb6fflorian   if (i->present) {
4961740da72e3938e8474234420777c17c1a4be6cb6fflorian      if (low  < i->low)  i->low  = low;
4962740da72e3938e8474234420777c17c1a4be6cb6fflorian      if (high > i->high) i->high = high;
4963740da72e3938e8474234420777c17c1a4be6cb6fflorian   } else {
4964740da72e3938e8474234420777c17c1a4be6cb6fflorian      i->present = True;
4965740da72e3938e8474234420777c17c1a4be6cb6fflorian      i->low  = low;
4966740da72e3938e8474234420777c17c1a4be6cb6fflorian      i->high = high;
4967740da72e3938e8474234420777c17c1a4be6cb6fflorian   }
4968740da72e3938e8474234420777c17c1a4be6cb6fflorian}
4969740da72e3938e8474234420777c17c1a4be6cb6fflorian
4970740da72e3938e8474234420777c17c1a4be6cb6fflorian
4971f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* bindee == NULL   ===  slot is not in use
4972f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   bindee != NULL   ===  slot is in use
4973f9517d0d452899780e8c34f02bef004ef7c5a163sewardj*/
49740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardjtypedef
4975f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   struct {
4976f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      IRTemp  binder;
4977f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      IRExpr* bindee;
4978f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      Bool    doesLoad;
4979740da72e3938e8474234420777c17c1a4be6cb6fflorian      /* Record the bytes of the guest state BINDEE reads from. */
4980740da72e3938e8474234420777c17c1a4be6cb6fflorian      Interval getInterval;
4981575670caec4ae3cb4f3b9395fc9a9837b12432besewardj   }
4982f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   ATmpInfo;
4983a5dc3486e32efe9a5fc28f23addbdd1a857f0ab0sewardj
4984f9517d0d452899780e8c34f02bef004ef7c5a163sewardj__attribute__((unused))
4985f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic void ppAEnv ( ATmpInfo* env )
4986f9517d0d452899780e8c34f02bef004ef7c5a163sewardj{
4987f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Int i;
4988f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   for (i = 0; i < A_NENV; i++) {
4989f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      vex_printf("%d  tmp %d  val ", i, (Int)env[i].binder);
4990f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      if (env[i].bindee)
4991f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         ppIRExpr(env[i].bindee);
4992f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      else
4993f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vex_printf("(null)");
4994f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      vex_printf("\n");
4995f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   }
4996f9517d0d452899780e8c34f02bef004ef7c5a163sewardj}
4997f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
4998f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* --- Tree-traversal fns --- */
4999f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
5000f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* Traverse an expr, and detect if any part of it reads memory or does
5001f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   a Get.  Be careful ... this really controls how much the
5002f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   tree-builder can reorder the code, so getting it right is critical.
50030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj*/
5004740da72e3938e8474234420777c17c1a4be6cb6fflorianstatic void setHints_Expr (Bool* doesLoad, Interval* getInterval, IRExpr* e )
50050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
5006f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Int i;
5007f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   switch (e->tag) {
5008f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      case Iex_CCall:
5009f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         for (i = 0; e->Iex.CCall.args[i]; i++)
5010740da72e3938e8474234420777c17c1a4be6cb6fflorian            setHints_Expr(doesLoad, getInterval, e->Iex.CCall.args[i]);
5011f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
501299dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
5013740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.ITE.cond);
5014740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.ITE.iftrue);
5015740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.ITE.iffalse);
5016f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
501740c802659108a96bb87cbc1a30b7b77e2abd0829sewardj      case Iex_Qop:
5018740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg1);
5019740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg2);
5020740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg3);
5021740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Qop.details->arg4);
502240c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         return;
5023b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      case Iex_Triop:
5024740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Triop.details->arg1);
5025740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Triop.details->arg2);
5026740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Triop.details->arg3);
5027b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         return;
5028f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      case Iex_Binop:
5029740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Binop.arg1);
5030740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Binop.arg2);
5031f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
5032f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      case Iex_Unop:
5033740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Unop.arg);
5034f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
5035f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      case Iex_Load:
5036f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         *doesLoad = True;
5037740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.Load.addr);
5038f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
5039740da72e3938e8474234420777c17c1a4be6cb6fflorian      case Iex_Get: {
5040740da72e3938e8474234420777c17c1a4be6cb6fflorian         Int low = e->Iex.Get.offset;
5041740da72e3938e8474234420777c17c1a4be6cb6fflorian         Int high = low + sizeofIRType(e->Iex.Get.ty) - 1;
5042740da72e3938e8474234420777c17c1a4be6cb6fflorian         update_interval(getInterval, low, high);
5043f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
5044740da72e3938e8474234420777c17c1a4be6cb6fflorian      }
5045740da72e3938e8474234420777c17c1a4be6cb6fflorian      case Iex_GetI: {
5046740da72e3938e8474234420777c17c1a4be6cb6fflorian         IRRegArray *descr = e->Iex.GetI.descr;
5047740da72e3938e8474234420777c17c1a4be6cb6fflorian         Int size = sizeofIRType(descr->elemTy);
5048740da72e3938e8474234420777c17c1a4be6cb6fflorian         Int low  = descr->base;
5049740da72e3938e8474234420777c17c1a4be6cb6fflorian         Int high = low + descr->nElems * size - 1;
5050740da72e3938e8474234420777c17c1a4be6cb6fflorian         update_interval(getInterval, low, high);
5051740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(doesLoad, getInterval, e->Iex.GetI.ix);
5052f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
5053740da72e3938e8474234420777c17c1a4be6cb6fflorian      }
5054dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp:
5055f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      case Iex_Const:
5056f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return;
5057f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      default:
5058f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5059f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vpanic("setHints_Expr");
50600821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
5061575670caec4ae3cb4f3b9395fc9a9837b12432besewardj}
5062575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
5063f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
5064f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* Add a binding to the front of the env and slide all the rest
5065f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   backwards.  It should be the case that the last slot is free. */
5066f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic void addToEnvFront ( ATmpInfo* env, IRTemp binder, IRExpr* bindee )
5067f9517d0d452899780e8c34f02bef004ef7c5a163sewardj{
5068f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Int i;
5069f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   vassert(env[A_NENV-1].bindee == NULL);
5070f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   for (i = A_NENV-1; i >= 1; i--)
5071f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      env[i] = env[i-1];
5072f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   env[0].binder   = binder;
5073f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   env[0].bindee   = bindee;
5074f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   env[0].doesLoad = False; /* filled in later */
5075740da72e3938e8474234420777c17c1a4be6cb6fflorian   env[0].getInterval.present  = False; /* filled in later */
5076740da72e3938e8474234420777c17c1a4be6cb6fflorian   env[0].getInterval.low  = -1; /* filled in later */
5077740da72e3938e8474234420777c17c1a4be6cb6fflorian   env[0].getInterval.high = -1; /* filled in later */
5078f9517d0d452899780e8c34f02bef004ef7c5a163sewardj}
5079f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
5080f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* Given uses :: array of UShort, indexed by IRTemp
5081f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Add the use-occurrences of temps in this expression
5082f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   to the env.
5083f9517d0d452899780e8c34f02bef004ef7c5a163sewardj*/
5084f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic void aoccCount_Expr ( UShort* uses, IRExpr* e )
50850821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
50860821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int i;
5087575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
50880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (e->tag) {
5089575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
5090dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp: /* the only interesting case */
5091dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         uses[e->Iex.RdTmp.tmp]++;
50920821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5093728c9d59db14f528e3d47a5c2bf2027407ea133esewardj
509499dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
509599dd03e04a6914d90d5fee727d61d76905334becflorian         aoccCount_Expr(uses, e->Iex.ITE.cond);
509699dd03e04a6914d90d5fee727d61d76905334becflorian         aoccCount_Expr(uses, e->Iex.ITE.iftrue);
509799dd03e04a6914d90d5fee727d61d76905334becflorian         aoccCount_Expr(uses, e->Iex.ITE.iffalse);
50980821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5099575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
510040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj      case Iex_Qop:
510196d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         aoccCount_Expr(uses, e->Iex.Qop.details->arg1);
510296d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         aoccCount_Expr(uses, e->Iex.Qop.details->arg2);
510396d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         aoccCount_Expr(uses, e->Iex.Qop.details->arg3);
510496d7cc3e7d54ad5af2af2821223b21f9a8516a59florian         aoccCount_Expr(uses, e->Iex.Qop.details->arg4);
510540c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         return;
510640c802659108a96bb87cbc1a30b7b77e2abd0829sewardj
5107b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      case Iex_Triop:
5108420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         aoccCount_Expr(uses, e->Iex.Triop.details->arg1);
5109420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         aoccCount_Expr(uses, e->Iex.Triop.details->arg2);
5110420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian         aoccCount_Expr(uses, e->Iex.Triop.details->arg3);
5111b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         return;
5112b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
51130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Binop:
5114f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, e->Iex.Binop.arg1);
5115f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, e->Iex.Binop.arg2);
51160821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5117e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
51180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Unop:
5119f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, e->Iex.Unop.arg);
51200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5121e98dcf23f5f6c301ddbfebd77f246accfa61f4ccsewardj
5122af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Iex_Load:
5123f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, e->Iex.Load.addr);
51240821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5125575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
51260821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_CCall:
51270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (i = 0; e->Iex.CCall.args[i]; i++)
5128f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            aoccCount_Expr(uses, e->Iex.CCall.args[i]);
51290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5130575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
51310821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_GetI:
5132f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, e->Iex.GetI.ix);
51330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5134575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
51350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Const:
51360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Get:
51370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5138575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
51390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
51400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5141f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vpanic("aoccCount_Expr");
51420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj    }
51430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
5144575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
5145575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
5146f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* Given uses :: array of UShort, indexed by IRTemp
5147f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Add the use-occurrences of temps in this statement
5148f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   to the env.
51490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj*/
5150f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic void aoccCount_Stmt ( UShort* uses, IRStmt* st )
51510821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
51520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      i;
51530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRDirty* d;
5154e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRCAS*   cas;
51550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   switch (st->tag) {
51565a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
5157f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, st->Ist.AbiHint.base);
5158478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         aoccCount_Expr(uses, st->Ist.AbiHint.nia);
51595a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         return;
5160dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
5161dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         aoccCount_Expr(uses, st->Ist.WrTmp.data);
51620821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
51630821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Put:
5164f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, st->Ist.Put.data);
51650821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
51660821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_PutI:
5167d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         aoccCount_Expr(uses, st->Ist.PutI.details->ix);
5168d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         aoccCount_Expr(uses, st->Ist.PutI.details->data);
51690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5170af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
5171f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, st->Ist.Store.addr);
5172f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, st->Ist.Store.data);
51730821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5174cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG: {
5175cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRStoreG* sg = st->Ist.StoreG.details;
5176cfe046e178666280b87da998b1b52ecda03ecd89sewardj         aoccCount_Expr(uses, sg->addr);
5177cfe046e178666280b87da998b1b52ecda03ecd89sewardj         aoccCount_Expr(uses, sg->data);
5178cfe046e178666280b87da998b1b52ecda03ecd89sewardj         aoccCount_Expr(uses, sg->guard);
5179cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return;
5180cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
5181cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG: {
5182cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRLoadG* lg = st->Ist.LoadG.details;
5183cfe046e178666280b87da998b1b52ecda03ecd89sewardj         aoccCount_Expr(uses, lg->addr);
5184cfe046e178666280b87da998b1b52ecda03ecd89sewardj         aoccCount_Expr(uses, lg->alt);
5185cfe046e178666280b87da998b1b52ecda03ecd89sewardj         aoccCount_Expr(uses, lg->guard);
5186cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return;
5187cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
5188e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
5189e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas = st->Ist.CAS.details;
5190e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         aoccCount_Expr(uses, cas->addr);
5191e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (cas->expdHi)
5192e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            aoccCount_Expr(uses, cas->expdHi);
5193e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         aoccCount_Expr(uses, cas->expdLo);
5194e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (cas->dataHi)
5195e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            aoccCount_Expr(uses, cas->dataHi);
5196e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         aoccCount_Expr(uses, cas->dataLo);
5197e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
5198e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
5199e768e92e054cde495849a5c842a477d287677f78sewardj         aoccCount_Expr(uses, st->Ist.LLSC.addr);
5200e768e92e054cde495849a5c842a477d287677f78sewardj         if (st->Ist.LLSC.storedata)
5201e768e92e054cde495849a5c842a477d287677f78sewardj            aoccCount_Expr(uses, st->Ist.LLSC.storedata);
5202e768e92e054cde495849a5c842a477d287677f78sewardj         return;
52030821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Dirty:
52040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         d = st->Ist.Dirty.details;
52050821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (d->mFx != Ifx_None)
5206f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            aoccCount_Expr(uses, d->mAddr);
5207f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, d->guard);
520874142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         for (i = 0; d->args[i]; i++) {
520974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            IRExpr* arg = d->args[i];
5210ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
521174142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               aoccCount_Expr(uses, arg);
521274142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         }
52130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
5214d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
5215f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
5216c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
52173e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj         return;
52180821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Ist_Exit:
5219f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         aoccCount_Expr(uses, st->Ist.Exit.guard);
52200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return;
52210821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      default:
52220821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
5223f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vpanic("aoccCount_Stmt");
5224575670caec4ae3cb4f3b9395fc9a9837b12432besewardj   }
5225728c9d59db14f528e3d47a5c2bf2027407ea133esewardj}
52264345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
52270821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Look up a binding for tmp in the env.  If found, return the bound
52280821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   expression, and set the env's binding to NULL so it is marked as
52290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   used.  If not found, return NULL. */
5230575670caec4ae3cb4f3b9395fc9a9837b12432besewardj
5231f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic IRExpr* atbSubst_Temp ( ATmpInfo* env, IRTemp tmp )
52320821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
5233f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Int i;
5234f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   for (i = 0; i < A_NENV; i++) {
5235f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      if (env[i].binder == tmp && env[i].bindee != NULL) {
5236f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         IRExpr* bindee = env[i].bindee;
5237f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         env[i].bindee = NULL;
5238f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return bindee;
52390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
52400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
5241f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   return NULL;
52420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj}
5243edf4d69c8477cad95851d0f6ccf91ab323e5a446sewardj
52440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj/* Traverse e, looking for temps.  For each observed temp, see if env
52450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   contains a binding for the temp, and if so return the bound value.
52460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   The env has the property that any binding it holds is
52470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   'single-shot', so once a binding is used, it is marked as no longer
5248f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   available, by setting its .bindee field to NULL. */
5249f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
5250eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardjstatic inline Bool is_Unop ( IRExpr* e, IROp op ) {
5251eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   return e->tag == Iex_Unop && e->Iex.Unop.op == op;
5252eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj}
5253eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardjstatic inline Bool is_Binop ( IRExpr* e, IROp op ) {
5254eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   return e->tag == Iex_Binop && e->Iex.Binop.op == op;
5255eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj}
5256eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj
5257eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardjstatic IRExpr* fold_IRExpr_Binop ( IROp op, IRExpr* a1, IRExpr* a2 )
5258eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj{
5259eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   switch (op) {
5260eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_Or32:
5261eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* Or32( CmpwNEZ32(x), CmpwNEZ32(y) ) --> CmpwNEZ32( Or32( x, y ) )  */
5262eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(a1, Iop_CmpwNEZ32) && is_Unop(a2, Iop_CmpwNEZ32))
5263eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop( Iop_CmpwNEZ32,
5264eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                             IRExpr_Binop( Iop_Or32, a1->Iex.Unop.arg,
5265eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                                                     a2->Iex.Unop.arg ) );
5266eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
526751d26fd8c2df9a0d0844ba9198be9152d18dab04florian
526851d26fd8c2df9a0d0844ba9198be9152d18dab04florian   case Iop_CmpNE32:
526951d26fd8c2df9a0d0844ba9198be9152d18dab04florian      /* Since X has type Ity_I1 we can simplify:
527051d26fd8c2df9a0d0844ba9198be9152d18dab04florian         CmpNE32(1Uto32(X),0)) ==> X */
527151d26fd8c2df9a0d0844ba9198be9152d18dab04florian      if (is_Unop(a1, Iop_1Uto32) && isZeroU32(a2))
527251d26fd8c2df9a0d0844ba9198be9152d18dab04florian         return a1->Iex.Unop.arg;
527351d26fd8c2df9a0d0844ba9198be9152d18dab04florian      break;
527451d26fd8c2df9a0d0844ba9198be9152d18dab04florian
5275eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   default:
5276eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5277eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   }
5278eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   /* no reduction rule applies */
5279eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   return IRExpr_Binop( op, a1, a2 );
5280eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj}
5281eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj
5282eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardjstatic IRExpr* fold_IRExpr_Unop ( IROp op, IRExpr* aa )
5283eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj{
5284eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   switch (op) {
5285eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_CmpwNEZ64:
5286de6f7105b663609e3ff0137726522b3bae135195florian      /* CmpwNEZ64( CmpwNEZ64 ( x ) ) --> CmpwNEZ64 ( x ) */
5287de6f7105b663609e3ff0137726522b3bae135195florian      if (is_Unop(aa, Iop_CmpwNEZ64))
5288de6f7105b663609e3ff0137726522b3bae135195florian         return IRExpr_Unop( Iop_CmpwNEZ64, aa->Iex.Unop.arg );
5289eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* CmpwNEZ64( Or64 ( CmpwNEZ64(x), y ) ) --> CmpwNEZ64( Or64( x, y ) ) */
5290eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Binop(aa, Iop_Or64)
5291eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj          && is_Unop(aa->Iex.Binop.arg1, Iop_CmpwNEZ64))
5292eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return fold_IRExpr_Unop(
5293eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                   Iop_CmpwNEZ64,
5294eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                   IRExpr_Binop(Iop_Or64,
5295eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                                aa->Iex.Binop.arg1->Iex.Unop.arg,
5296eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                                aa->Iex.Binop.arg2));
5297eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* CmpwNEZ64( Or64 ( x, CmpwNEZ64(y) ) ) --> CmpwNEZ64( Or64( x, y ) ) */
5298eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Binop(aa, Iop_Or64)
5299eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj          && is_Unop(aa->Iex.Binop.arg2, Iop_CmpwNEZ64))
5300eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return fold_IRExpr_Unop(
5301eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                   Iop_CmpwNEZ64,
5302eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                   IRExpr_Binop(Iop_Or64,
5303eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                                aa->Iex.Binop.arg1,
5304eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj                                aa->Iex.Binop.arg2->Iex.Unop.arg));
5305eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5306eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_CmpNEZ64:
5307eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* CmpNEZ64( Left64(x) ) --> CmpNEZ64(x) */
5308eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_Left64))
5309eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop(Iop_CmpNEZ64, aa->Iex.Unop.arg);
5310de6f7105b663609e3ff0137726522b3bae135195florian      /* CmpNEZ64( 1Uto64(X) ) --> X */
5311de6f7105b663609e3ff0137726522b3bae135195florian      if (is_Unop(aa, Iop_1Uto64))
5312de6f7105b663609e3ff0137726522b3bae135195florian         return aa->Iex.Unop.arg;
5313eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5314eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_CmpwNEZ32:
5315eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* CmpwNEZ32( CmpwNEZ32 ( x ) ) --> CmpwNEZ32 ( x ) */
5316eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_CmpwNEZ32))
5317eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop( Iop_CmpwNEZ32, aa->Iex.Unop.arg );
5318eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5319eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_CmpNEZ32:
5320eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* CmpNEZ32( Left32(x) ) --> CmpNEZ32(x) */
5321eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_Left32))
5322eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop(Iop_CmpNEZ32, aa->Iex.Unop.arg);
532351d26fd8c2df9a0d0844ba9198be9152d18dab04florian      /* CmpNEZ32( 1Uto32(X) ) --> X */
532451d26fd8c2df9a0d0844ba9198be9152d18dab04florian      if (is_Unop(aa, Iop_1Uto32))
532551d26fd8c2df9a0d0844ba9198be9152d18dab04florian         return aa->Iex.Unop.arg;
5326de6f7105b663609e3ff0137726522b3bae135195florian      /* CmpNEZ32( 64to32( CmpwNEZ64(X) ) ) --> CmpNEZ64(X) */
5327de6f7105b663609e3ff0137726522b3bae135195florian      if (is_Unop(aa, Iop_64to32) && is_Unop(aa->Iex.Unop.arg, Iop_CmpwNEZ64))
5328de6f7105b663609e3ff0137726522b3bae135195florian         return IRExpr_Unop(Iop_CmpNEZ64, aa->Iex.Unop.arg->Iex.Unop.arg);
532951d26fd8c2df9a0d0844ba9198be9152d18dab04florian      break;
533051d26fd8c2df9a0d0844ba9198be9152d18dab04florian   case Iop_CmpNEZ8:
533151d26fd8c2df9a0d0844ba9198be9152d18dab04florian      /* CmpNEZ8( 1Uto8(X) ) --> X */
533251d26fd8c2df9a0d0844ba9198be9152d18dab04florian      if (is_Unop(aa, Iop_1Uto8))
533351d26fd8c2df9a0d0844ba9198be9152d18dab04florian         return aa->Iex.Unop.arg;
5334eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5335eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_Left32:
5336eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* Left32( Left32(x) ) --> Left32(x) */
5337eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_Left32))
5338eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop( Iop_Left32, aa->Iex.Unop.arg );
5339eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5340854912aab0e19f3f2dc4c3e2e6ed150871deb846florian   case Iop_Left64:
5341854912aab0e19f3f2dc4c3e2e6ed150871deb846florian      /* Left64( Left64(x) ) --> Left64(x) */
5342854912aab0e19f3f2dc4c3e2e6ed150871deb846florian      if (is_Unop(aa, Iop_Left64))
5343854912aab0e19f3f2dc4c3e2e6ed150871deb846florian         return IRExpr_Unop( Iop_Left64, aa->Iex.Unop.arg );
5344854912aab0e19f3f2dc4c3e2e6ed150871deb846florian      break;
53450caa0c050206658c1309702e84aa1957e3694c16sewardj   case Iop_ZeroHI64ofV128:
53460caa0c050206658c1309702e84aa1957e3694c16sewardj      /* ZeroHI64ofV128( ZeroHI64ofV128(x) ) --> ZeroHI64ofV128(x) */
53470caa0c050206658c1309702e84aa1957e3694c16sewardj      if (is_Unop(aa, Iop_ZeroHI64ofV128))
53480caa0c050206658c1309702e84aa1957e3694c16sewardj         return IRExpr_Unop( Iop_ZeroHI64ofV128, aa->Iex.Unop.arg );
53490caa0c050206658c1309702e84aa1957e3694c16sewardj      break;
5350eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_32to1:
5351eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* 32to1( 1Uto32 ( x ) ) --> x */
5352eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_1Uto32))
5353eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return aa->Iex.Unop.arg;
5354eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* 32to1( CmpwNEZ32 ( x )) --> CmpNEZ32(x) */
5355eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_CmpwNEZ32))
5356eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop( Iop_CmpNEZ32, aa->Iex.Unop.arg );
5357eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5358eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   case Iop_64to1:
5359eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* 64to1( 1Uto64 ( x ) ) --> x */
5360eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_1Uto64))
5361eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return aa->Iex.Unop.arg;
5362eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      /* 64to1( CmpwNEZ64 ( x )) --> CmpNEZ64(x) */
5363eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      if (is_Unop(aa, Iop_CmpwNEZ64))
5364eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return IRExpr_Unop( Iop_CmpNEZ64, aa->Iex.Unop.arg );
5365eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5366ef425db9c4d0ceefa2f1b941f29af318d63542efsewardj   case Iop_64to32:
5367ef425db9c4d0ceefa2f1b941f29af318d63542efsewardj      /* 64to32( 32Uto64 ( x )) --> x */
5368ef425db9c4d0ceefa2f1b941f29af318d63542efsewardj      if (is_Unop(aa, Iop_32Uto64))
5369ef425db9c4d0ceefa2f1b941f29af318d63542efsewardj         return aa->Iex.Unop.arg;
5370ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      /* 64to32( 8Uto64 ( x )) --> 8Uto32(x) */
5371ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      if (is_Unop(aa, Iop_8Uto64))
5372ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         return IRExpr_Unop(Iop_8Uto32, aa->Iex.Unop.arg);
5373ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      break;
5374ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj
5375ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj   case Iop_32Uto64:
5376ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      /* 32Uto64( 8Uto32( x )) --> 8Uto64(x) */
5377ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      if (is_Unop(aa, Iop_8Uto32))
5378ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         return IRExpr_Unop(Iop_8Uto64, aa->Iex.Unop.arg);
5379ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      /* 32Uto64( 16Uto32( x )) --> 16Uto64(x) */
5380ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      if (is_Unop(aa, Iop_16Uto32))
5381ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         return IRExpr_Unop(Iop_16Uto64, aa->Iex.Unop.arg);
5382bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj      /* 32Uto64(64to32( Shr64( 32Uto64(64to32(x)), sh ))
5383bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                     --> Shr64( 32Uto64(64to32(x)), sh )) */
5384bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj      if (is_Unop(aa, Iop_64to32)
5385bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj          && is_Binop(aa->Iex.Unop.arg, Iop_Shr64)
5386bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1, Iop_32Uto64)
5387bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg,
5388bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                     Iop_64to32)) {
5389bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj         return aa->Iex.Unop.arg;
5390bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj      }
5391bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj      /*     32Uto64(64to32( Shl64( 32Uto64(64to32(x)), sh ))
5392bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj         --> 32Uto64(64to32( Shl64(                x,   sh )) */
5393bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj      if (is_Unop(aa, Iop_64to32)
5394bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj          && is_Binop(aa->Iex.Unop.arg, Iop_Shl64)
5395bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1, Iop_32Uto64)
5396bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj          && is_Unop(aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg,
5397bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                     Iop_64to32)) {
5398bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj         return
5399bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj            IRExpr_Unop(
5400bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj               Iop_32Uto64,
5401bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj               IRExpr_Unop(
5402bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                  Iop_64to32,
5403bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                  IRExpr_Binop(
5404bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                     Iop_Shl64,
5405bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                     aa->Iex.Unop.arg->Iex.Binop.arg1->Iex.Unop.arg->Iex.Unop.arg,
5406bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj                     aa->Iex.Unop.arg->Iex.Binop.arg2
5407bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj            )));
5408bba356d54ba2a6f04f7c60806b5ad6a81f88644asewardj      }
5409ef425db9c4d0ceefa2f1b941f29af318d63542efsewardj      break;
54106c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
54116c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   case Iop_1Sto32:
54126c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /* 1Sto32( CmpNEZ8( 32to8( 1Uto32( CmpNEZ32( x ))))) -> CmpwNEZ32(x) */
54136c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (is_Unop(aa, Iop_CmpNEZ8)
54146c299f3acab617581ea504e45fbb6cab24c2b29fsewardj          && is_Unop(aa->Iex.Unop.arg, Iop_32to8)
54156c299f3acab617581ea504e45fbb6cab24c2b29fsewardj          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg, Iop_1Uto32)
54166c299f3acab617581ea504e45fbb6cab24c2b29fsewardj          && is_Unop(aa->Iex.Unop.arg->Iex.Unop.arg->Iex.Unop.arg,
54176c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     Iop_CmpNEZ32)) {
54186c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return IRExpr_Unop( Iop_CmpwNEZ32,
54196c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                             aa->Iex.Unop.arg->Iex.Unop.arg
54206c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                               ->Iex.Unop.arg->Iex.Unop.arg);
54216c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
54226c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      break;
54236c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5424eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   default:
5425eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj      break;
5426eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   }
5427eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   /* no reduction rule applies */
5428eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj   return IRExpr_Unop( op, aa );
5429eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj}
5430eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj
5431f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic IRExpr* atbSubst_Expr ( ATmpInfo* env, IRExpr* e )
5432695cff9303ef5dc8079117acfd632b44edb1f010sewardj{
54330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr*  e2;
54340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRExpr** args2;
54350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int      i;
54360821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5437f6275b741337e8fae0108bb9a96db3498c287fc1sewardj   switch (e->tag) {
54380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
54390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_CCall:
5440dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         args2 = shallowCopyIRExprVec(e->Iex.CCall.args);
54410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         for (i = 0; args2[i]; i++)
5442f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            args2[i] = atbSubst_Expr(env,args2[i]);
5443f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         return IRExpr_CCall(
5444f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   e->Iex.CCall.cee,
54450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   e->Iex.CCall.retty,
54460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   args2
54470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5448dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Iex_RdTmp:
5449dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         e2 = atbSubst_Temp(env, e->Iex.RdTmp.tmp);
54500821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return e2 ? e2 : e;
545199dd03e04a6914d90d5fee727d61d76905334becflorian      case Iex_ITE:
545299dd03e04a6914d90d5fee727d61d76905334becflorian         return IRExpr_ITE(
545399dd03e04a6914d90d5fee727d61d76905334becflorian                   atbSubst_Expr(env, e->Iex.ITE.cond),
545499dd03e04a6914d90d5fee727d61d76905334becflorian                   atbSubst_Expr(env, e->Iex.ITE.iftrue),
545599dd03e04a6914d90d5fee727d61d76905334becflorian                   atbSubst_Expr(env, e->Iex.ITE.iffalse)
54560821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
545740c802659108a96bb87cbc1a30b7b77e2abd0829sewardj      case Iex_Qop:
545840c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         return IRExpr_Qop(
545996d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   e->Iex.Qop.details->op,
546096d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   atbSubst_Expr(env, e->Iex.Qop.details->arg1),
546196d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   atbSubst_Expr(env, e->Iex.Qop.details->arg2),
546296d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   atbSubst_Expr(env, e->Iex.Qop.details->arg3),
546396d7cc3e7d54ad5af2af2821223b21f9a8516a59florian                   atbSubst_Expr(env, e->Iex.Qop.details->arg4)
546440c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                );
5465b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      case Iex_Triop:
5466b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         return IRExpr_Triop(
5467420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   e->Iex.Triop.details->op,
5468420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   atbSubst_Expr(env, e->Iex.Triop.details->arg1),
5469420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   atbSubst_Expr(env, e->Iex.Triop.details->arg2),
5470420bfa9e0f6bc49d7682d334aa61189b4d50f7b8florian                   atbSubst_Expr(env, e->Iex.Triop.details->arg3)
5471b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                );
54720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Binop:
5473eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return fold_IRExpr_Binop(
54740821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   e->Iex.Binop.op,
5475f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, e->Iex.Binop.arg1),
5476f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, e->Iex.Binop.arg2)
54770821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5478f6275b741337e8fae0108bb9a96db3498c287fc1sewardj      case Iex_Unop:
5479eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         return fold_IRExpr_Unop(
54800821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   e->Iex.Unop.op,
5481f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, e->Iex.Unop.arg)
54820821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5483af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Iex_Load:
5484af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         return IRExpr_Load(
5485af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   e->Iex.Load.end,
5486af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   e->Iex.Load.ty,
5487f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, e->Iex.Load.addr)
54880821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
54890821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_GetI:
54900821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRExpr_GetI(
54910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   e->Iex.GetI.descr,
5492f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, e->Iex.GetI.ix),
54930821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   e->Iex.GetI.bias
54940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
54950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Const:
54960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      case Iex_Get:
54970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return e;
5498f6275b741337e8fae0108bb9a96db3498c287fc1sewardj      default:
5499f6275b741337e8fae0108bb9a96db3498c287fc1sewardj         vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5500f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vpanic("atbSubst_Expr");
5501f6275b741337e8fae0108bb9a96db3498c287fc1sewardj   }
5502695cff9303ef5dc8079117acfd632b44edb1f010sewardj}
55034345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
5504f9517d0d452899780e8c34f02bef004ef7c5a163sewardj/* Same deal as atbSubst_Expr, except for stmts. */
5505f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
5506f9517d0d452899780e8c34f02bef004ef7c5a163sewardjstatic IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
5507695cff9303ef5dc8079117acfd632b44edb1f010sewardj{
5508e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   Int     i;
5509e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRDirty *d, *d2;
5510e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRCAS   *cas, *cas2;
5511d6f38b3f822f7d57adfc0da3410995d85d6a4597florian   IRPutI  *puti, *puti2;
5512d6f38b3f822f7d57adfc0da3410995d85d6a4597florian
5513f6275b741337e8fae0108bb9a96db3498c287fc1sewardj   switch (st->tag) {
55145a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj      case Ist_AbiHint:
55155a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         return IRStmt_AbiHint(
5516f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, st->Ist.AbiHint.base),
5517478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                   st->Ist.AbiHint.len,
5518478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                   atbSubst_Expr(env, st->Ist.AbiHint.nia)
55195a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj                );
5520af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj      case Ist_Store:
5521af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         return IRStmt_Store(
5522af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj                   st->Ist.Store.end,
5523f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, st->Ist.Store.addr),
5524f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, st->Ist.Store.data)
55250821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5526cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_StoreG: {
5527cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRStoreG* sg = st->Ist.StoreG.details;
5528cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return IRStmt_StoreG(sg->end,
5529cfe046e178666280b87da998b1b52ecda03ecd89sewardj                              atbSubst_Expr(env, sg->addr),
5530cfe046e178666280b87da998b1b52ecda03ecd89sewardj                              atbSubst_Expr(env, sg->data),
5531cfe046e178666280b87da998b1b52ecda03ecd89sewardj                              atbSubst_Expr(env, sg->guard));
5532cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
5533cfe046e178666280b87da998b1b52ecda03ecd89sewardj      case Ist_LoadG: {
5534cfe046e178666280b87da998b1b52ecda03ecd89sewardj         IRLoadG* lg = st->Ist.LoadG.details;
5535cfe046e178666280b87da998b1b52ecda03ecd89sewardj         return IRStmt_LoadG(lg->end, lg->cvt, lg->dst,
5536cfe046e178666280b87da998b1b52ecda03ecd89sewardj                             atbSubst_Expr(env, lg->addr),
5537cfe046e178666280b87da998b1b52ecda03ecd89sewardj                             atbSubst_Expr(env, lg->alt),
5538cfe046e178666280b87da998b1b52ecda03ecd89sewardj                             atbSubst_Expr(env, lg->guard));
5539cfe046e178666280b87da998b1b52ecda03ecd89sewardj      }
5540dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      case Ist_WrTmp:
5541dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         return IRStmt_WrTmp(
5542dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                   st->Ist.WrTmp.tmp,
5543dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                   atbSubst_Expr(env, st->Ist.WrTmp.data)
55440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5545f6275b741337e8fae0108bb9a96db3498c287fc1sewardj      case Ist_Put:
55460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRStmt_Put(
55470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   st->Ist.Put.offset,
5548f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, st->Ist.Put.data)
55490821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5550f6275b741337e8fae0108bb9a96db3498c287fc1sewardj      case Ist_PutI:
5551d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         puti  = st->Ist.PutI.details;
5552d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         puti2 = mkIRPutI(puti->descr,
5553d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                          atbSubst_Expr(env, puti->ix),
5554d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                          puti->bias,
5555d6f38b3f822f7d57adfc0da3410995d85d6a4597florian                          atbSubst_Expr(env, puti->data));
5556d6f38b3f822f7d57adfc0da3410995d85d6a4597florian         return IRStmt_PutI(puti2);
55570821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5558f6275b741337e8fae0108bb9a96db3498c287fc1sewardj      case Ist_Exit:
55590821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRStmt_Exit(
5560f9517d0d452899780e8c34f02bef004ef7c5a163sewardj                   atbSubst_Expr(env, st->Ist.Exit.guard),
55610821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                   st->Ist.Exit.jk,
5562c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                   st->Ist.Exit.dst,
5563c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                   st->Ist.Exit.offsIP
55640821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                );
5565f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj      case Ist_IMark:
55662f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj         return IRStmt_IMark(st->Ist.IMark.addr,
55672f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj                             st->Ist.IMark.len,
55682f10aa6f4e9ea78030c46cce9b073b19c63c0f60sewardj                             st->Ist.IMark.delta);
5569d2445f60726580b450eca68ab40c568f9df338e2sewardj      case Ist_NoOp:
5570d2445f60726580b450eca68ab40c568f9df338e2sewardj         return IRStmt_NoOp();
5571c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      case Ist_MBE:
5572c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         return IRStmt_MBE(st->Ist.MBE.event);
5573e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ist_CAS:
5574e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas  = st->Ist.CAS.details;
5575e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         cas2 = mkIRCAS(
5576e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   cas->oldHi, cas->oldLo, cas->end,
5577e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   atbSubst_Expr(env, cas->addr),
5578e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   cas->expdHi ? atbSubst_Expr(env, cas->expdHi) : NULL,
5579e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   atbSubst_Expr(env, cas->expdLo),
5580e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   cas->dataHi ? atbSubst_Expr(env, cas->dataHi) : NULL,
5581e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                   atbSubst_Expr(env, cas->dataLo)
5582e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                );
5583e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return IRStmt_CAS(cas2);
5584e768e92e054cde495849a5c842a477d287677f78sewardj      case Ist_LLSC:
5585e768e92e054cde495849a5c842a477d287677f78sewardj         return IRStmt_LLSC(
5586e768e92e054cde495849a5c842a477d287677f78sewardj                   st->Ist.LLSC.end,
5587e768e92e054cde495849a5c842a477d287677f78sewardj                   st->Ist.LLSC.result,
5588e768e92e054cde495849a5c842a477d287677f78sewardj                   atbSubst_Expr(env, st->Ist.LLSC.addr),
5589e768e92e054cde495849a5c842a477d287677f78sewardj                   st->Ist.LLSC.storedata
5590e768e92e054cde495849a5c842a477d287677f78sewardj                      ? atbSubst_Expr(env, st->Ist.LLSC.storedata) : NULL
5591e768e92e054cde495849a5c842a477d287677f78sewardj                );
55927447b5b3355ac4201e3bd717989232cf7a0d748csewardj      case Ist_Dirty:
5593f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         d  = st->Ist.Dirty.details;
55940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         d2 = emptyIRDirty();
55950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         *d2 = *d;
55960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         if (d2->mFx != Ifx_None)
5597f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            d2->mAddr = atbSubst_Expr(env, d2->mAddr);
5598f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         d2->guard = atbSubst_Expr(env, d2->guard);
559974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         for (i = 0; d2->args[i]; i++) {
560074142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            IRExpr* arg = d2->args[i];
5601ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
560274142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               d2->args[i] = atbSubst_Expr(env, arg);
560374142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         }
56040821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         return IRStmt_Dirty(d2);
5605f6275b741337e8fae0108bb9a96db3498c287fc1sewardj      default:
5606f6275b741337e8fae0108bb9a96db3498c287fc1sewardj         vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
5607f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vpanic("atbSubst_Stmt");
56082d04d11c8ca8ff9643bc257780e60a77605b3af7sewardj   }
56092d04d11c8ca8ff9643bc257780e60a77605b3af7sewardj}
56102d04d11c8ca8ff9643bc257780e60a77605b3af7sewardj
5611088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorianinline
5612088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorianstatic Bool dirty_helper_stores ( const IRDirty *d )
5613088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian{
5614088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian   return d->mFx == Ifx_Write || d->mFx == Ifx_Modify;
5615088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian}
5616088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian
5617088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorianinline
5618ca2c3c75784d35d136fc7c952717cdee5063c193sewardjstatic Interval dirty_helper_puts (
5619ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   const IRDirty *d,
5620ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
5621ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   VexRegisterUpdates pxControl,
5622ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   /*OUT*/Bool *requiresPreciseMemExns
5623ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                )
5624088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian{
5625088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian   Int i;
5626740da72e3938e8474234420777c17c1a4be6cb6fflorian   Interval interval;
5627088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian
5628088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian   /* Passing the guest state pointer opens the door to modifying the
562974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj      guest state under the covers.  It's not allowed, but let's be
5630088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian      extra conservative and assume the worst. */
563174142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj   for (i = 0; d->args[i]; i++) {
5632ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      if (UNLIKELY(d->args[i]->tag == Iex_GSPTR)) {
563374142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         *requiresPreciseMemExns = True;
5634740da72e3938e8474234420777c17c1a4be6cb6fflorian         /* Assume all guest state is written. */
5635740da72e3938e8474234420777c17c1a4be6cb6fflorian         interval.present = True;
5636740da72e3938e8474234420777c17c1a4be6cb6fflorian         interval.low  = 0;
5637740da72e3938e8474234420777c17c1a4be6cb6fflorian         interval.high = 0x7FFFFFFF;
5638740da72e3938e8474234420777c17c1a4be6cb6fflorian         return interval;
563974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj      }
564062140c196b8c18a23ba0fe54295f0ffa000a0054florian   }
5641088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian
5642088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian   /* Check the side effects on the guest state */
5643740da72e3938e8474234420777c17c1a4be6cb6fflorian   interval.present = False;
5644740da72e3938e8474234420777c17c1a4be6cb6fflorian   interval.low = interval.high = -1;
564562140c196b8c18a23ba0fe54295f0ffa000a0054florian   *requiresPreciseMemExns = False;
564662140c196b8c18a23ba0fe54295f0ffa000a0054florian
5647088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian   for (i = 0; i < d->nFxState; ++i) {
564862140c196b8c18a23ba0fe54295f0ffa000a0054florian      if (d->fxState[i].fx != Ifx_Read) {
564962140c196b8c18a23ba0fe54295f0ffa000a0054florian         Int offset = d->fxState[i].offset;
565062140c196b8c18a23ba0fe54295f0ffa000a0054florian         Int size = d->fxState[i].size;
565162140c196b8c18a23ba0fe54295f0ffa000a0054florian         Int nRepeats = d->fxState[i].nRepeats;
565262140c196b8c18a23ba0fe54295f0ffa000a0054florian         Int repeatLen = d->fxState[i].repeatLen;
565362140c196b8c18a23ba0fe54295f0ffa000a0054florian
565474142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj         if (preciseMemExnsFn(offset,
5655ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                              offset + nRepeats * repeatLen + size - 1,
5656ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                              pxControl)) {
565762140c196b8c18a23ba0fe54295f0ffa000a0054florian            *requiresPreciseMemExns = True;
565862140c196b8c18a23ba0fe54295f0ffa000a0054florian         }
5659740da72e3938e8474234420777c17c1a4be6cb6fflorian         update_interval(&interval, offset,
5660740da72e3938e8474234420777c17c1a4be6cb6fflorian                         offset + nRepeats * repeatLen + size - 1);
566162140c196b8c18a23ba0fe54295f0ffa000a0054florian      }
5662088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian   }
5663088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian
5664740da72e3938e8474234420777c17c1a4be6cb6fflorian   return interval;
566562140c196b8c18a23ba0fe54295f0ffa000a0054florian}
566662140c196b8c18a23ba0fe54295f0ffa000a0054florian
5667ca2c3c75784d35d136fc7c952717cdee5063c193sewardj/* Return an interval if st modifies the guest state.  Via
5668ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   requiresPreciseMemExns return whether or not that modification
5669ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   requires precise exceptions. */
5670ca2c3c75784d35d136fc7c952717cdee5063c193sewardjstatic Interval stmt_modifies_guest_state (
5671ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   IRSB *bb, const IRStmt *st,
5672ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
5673ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   VexRegisterUpdates pxControl,
5674ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                   /*OUT*/Bool *requiresPreciseMemExns
5675ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                )
567662140c196b8c18a23ba0fe54295f0ffa000a0054florian{
5677740da72e3938e8474234420777c17c1a4be6cb6fflorian   Interval interval;
5678740da72e3938e8474234420777c17c1a4be6cb6fflorian
567962140c196b8c18a23ba0fe54295f0ffa000a0054florian   switch (st->tag) {
568062140c196b8c18a23ba0fe54295f0ffa000a0054florian   case Ist_Put: {
568162140c196b8c18a23ba0fe54295f0ffa000a0054florian      Int offset = st->Ist.Put.offset;
568262140c196b8c18a23ba0fe54295f0ffa000a0054florian      Int size = sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Put.data));
568362140c196b8c18a23ba0fe54295f0ffa000a0054florian
5684ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      *requiresPreciseMemExns
5685ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         = preciseMemExnsFn(offset, offset + size - 1, pxControl);
5686740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.present = True;
5687740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.low  = offset;
5688740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.high = offset + size - 1;
5689740da72e3938e8474234420777c17c1a4be6cb6fflorian      return interval;
569062140c196b8c18a23ba0fe54295f0ffa000a0054florian   }
569162140c196b8c18a23ba0fe54295f0ffa000a0054florian
569262140c196b8c18a23ba0fe54295f0ffa000a0054florian   case Ist_PutI: {
569362140c196b8c18a23ba0fe54295f0ffa000a0054florian      IRRegArray *descr = st->Ist.PutI.details->descr;
569462140c196b8c18a23ba0fe54295f0ffa000a0054florian      Int offset = descr->base;
569562140c196b8c18a23ba0fe54295f0ffa000a0054florian      Int size = sizeofIRType(descr->elemTy);
569662140c196b8c18a23ba0fe54295f0ffa000a0054florian
569762140c196b8c18a23ba0fe54295f0ffa000a0054florian      /* We quietly assume here that all segments are contiguous and there
569862140c196b8c18a23ba0fe54295f0ffa000a0054florian         are no holes. This is to avoid a loop. The assumption is conservative
569962140c196b8c18a23ba0fe54295f0ffa000a0054florian         in the sense that we might report that precise memory exceptions are
570062140c196b8c18a23ba0fe54295f0ffa000a0054florian         needed when in fact they are not. */
5701ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      *requiresPreciseMemExns
5702ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         = preciseMemExnsFn(offset, offset + descr->nElems * size - 1,
5703ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                            pxControl);
5704740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.present = True;
5705740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.low  = offset;
5706740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.high = offset + descr->nElems * size - 1;
5707740da72e3938e8474234420777c17c1a4be6cb6fflorian      return interval;
570862140c196b8c18a23ba0fe54295f0ffa000a0054florian   }
570962140c196b8c18a23ba0fe54295f0ffa000a0054florian
571062140c196b8c18a23ba0fe54295f0ffa000a0054florian   case Ist_Dirty:
5711ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      return dirty_helper_puts(st->Ist.Dirty.details,
5712ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                               preciseMemExnsFn, pxControl,
571362140c196b8c18a23ba0fe54295f0ffa000a0054florian                               requiresPreciseMemExns);
571462140c196b8c18a23ba0fe54295f0ffa000a0054florian
571562140c196b8c18a23ba0fe54295f0ffa000a0054florian   default:
571662140c196b8c18a23ba0fe54295f0ffa000a0054florian      *requiresPreciseMemExns = False;
5717740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.present = False;
5718740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.low  = -1;
5719740da72e3938e8474234420777c17c1a4be6cb6fflorian      interval.high = -1;
5720740da72e3938e8474234420777c17c1a4be6cb6fflorian      return interval;
572162140c196b8c18a23ba0fe54295f0ffa000a0054florian   }
5722088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian}
5723088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian
5724ca2c3c75784d35d136fc7c952717cdee5063c193sewardj/* notstatic */ Addr ado_treebuild_BB (
5725ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                        IRSB* bb,
5726ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                        Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
5727ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                        VexRegisterUpdates pxControl
5728ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                     )
57290821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj{
5730f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   Int      i, j, k, m;
5731740da72e3938e8474234420777c17c1a4be6cb6fflorian   Bool     stmtStores, invalidateMe;
5732740da72e3938e8474234420777c17c1a4be6cb6fflorian   Interval putInterval;
57330821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt*  st;
57340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   IRStmt*  st2;
5735f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   ATmpInfo env[A_NENV];
57362d04d11c8ca8ff9643bc257780e60a77605b3af7sewardj
5737c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   Bool   max_ga_known = False;
5738dcd6d236c9aef7d4c84369d4c51f6b92ac910127florian   Addr   max_ga       = 0;
5739c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
57400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   Int       n_tmps = bb->tyenv->types_used;
5741d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   UShort*   uses   = LibVEX_Alloc_inline(n_tmps * sizeof(UShort));
5742f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
57430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Phase 1.  Scan forwards in bb, counting use occurrences of each
5744c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      temp.  Also count occurrences in the bb->next field.  Take the
5745c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      opportunity to also find the maximum guest address in the block,
5746c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      since that will be needed later for deciding when we can safely
5747c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      elide event checks. */
5748f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
5749f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   for (i = 0; i < n_tmps; i++)
5750f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      uses[i] = 0;
5751f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
57520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < bb->stmts_used; i++) {
57530821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
5754c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      switch (st->tag) {
5755c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ist_NoOp:
5756c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            continue;
5757c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ist_IMark: {
5758dcd6d236c9aef7d4c84369d4c51f6b92ac910127florian            UInt len = st->Ist.IMark.len;
5759dcd6d236c9aef7d4c84369d4c51f6b92ac910127florian            Addr mga = st->Ist.IMark.addr + (len < 1 ? 1 : len) - 1;
5760c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            max_ga_known = True;
5761c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            if (mga > max_ga)
5762c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj               max_ga = mga;
5763c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            break;
5764c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         }
5765c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         default:
5766c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            break;
5767c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      }
5768f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      aoccCount_Stmt( uses, st );
57690821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
5770f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   aoccCount_Expr(uses, bb->next );
5771f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
57720821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  if 0
5773f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   for (i = 0; i < n_tmps; i++) {
5774f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      if (uses[i] == 0)
57750821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj        continue;
5776f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      ppIRTemp( (IRTemp)i );
5777f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      vex_printf("  used %d\n", (Int)uses[i] );
57780821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   }
57790821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj#  endif
5780f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
5781f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   /* Phase 2.  Scan forwards in bb.  For each statement in turn:
5782f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
5783f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         If the env is full, emit the end element.  This guarantees
5784f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         there is at least one free slot in the following.
5785695cff9303ef5dc8079117acfd632b44edb1f010sewardj
5786f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         On seeing 't = E', occ(t)==1,
5787f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            let E'=env(E)
5788f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            delete this stmt
5789f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            add t -> E' to the front of the env
5790f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            Examine E' and set the hints for E' appropriately
57910821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj              (doesLoad? doesGet?)
5792695cff9303ef5dc8079117acfd632b44edb1f010sewardj
5793f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         On seeing any other stmt,
57940821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            let stmt' = env(stmt)
57950821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            remove from env any 't=E' binds invalidated by stmt
57960821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj                emit the invalidated stmts
57970821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj            emit stmt'
5798f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            compact any holes in env
5799f9517d0d452899780e8c34f02bef004ef7c5a163sewardj              by sliding entries towards the front
5800695cff9303ef5dc8079117acfd632b44edb1f010sewardj
5801f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      Finally, apply env to bb->next.
58020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   */
5803695cff9303ef5dc8079117acfd632b44edb1f010sewardj
5804f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   for (i = 0; i < A_NENV; i++) {
5805f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      env[i].bindee = NULL;
5806f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      env[i].binder = IRTemp_INVALID;
5807f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   }
5808f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
58090821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* The stmts in bb are being reordered, and we are guaranteed to
58100821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      end up with no more than the number we started with.  Use i to
58110821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      be the cursor of the current stmt examined and j <= i to be that
58120821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      for the current stmt being written.
58130821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   */
58140821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   j = 0;
58150821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   for (i = 0; i < bb->stmts_used; i++) {
5816f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
58170821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      st = bb->stmts[i];
58188bee6d15808653a71717c256a3abe96993439d25sewardj      if (st->tag == Ist_NoOp)
58190821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         continue;
58200821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5821f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      /* Ensure there's at least one space in the env, by emitting
5822f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         the oldest binding if necessary. */
5823f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      if (env[A_NENV-1].bindee != NULL) {
5824dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         bb->stmts[j] = IRStmt_WrTmp( env[A_NENV-1].binder,
5825dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                                      env[A_NENV-1].bindee );
5826f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         j++;
5827f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         vassert(j <= i);
5828f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         env[A_NENV-1].bindee = NULL;
5829f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      }
5830f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
5831f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      /* Consider current stmt. */
5832dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (st->tag == Ist_WrTmp && uses[st->Ist.WrTmp.tmp] <= 1) {
5833633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj         IRExpr *e, *e2;
5834f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
5835f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         /* optional extra: dump dead bindings as we find them.
5836f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            Removes the need for a prior dead-code removal pass. */
5837dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (uses[st->Ist.WrTmp.tmp] == 0) {
5838b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj	    if (0) vex_printf("DEAD binding\n");
5839f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
58400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj         }
5841dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         vassert(uses[st->Ist.WrTmp.tmp] == 1);
5842f9517d0d452899780e8c34f02bef004ef7c5a163sewardj
5843f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         /* ok, we have 't = E', occ(t)==1.  Do the abovementioned
5844f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            actions. */
5845dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         e  = st->Ist.WrTmp.data;
5846633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj         e2 = atbSubst_Expr(env, e);
5847dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         addToEnvFront(env, st->Ist.WrTmp.tmp, e2);
5848740da72e3938e8474234420777c17c1a4be6cb6fflorian         setHints_Expr(&env[0].doesLoad, &env[0].getInterval, e2);
5849f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         /* don't advance j, as we are deleting this stmt and instead
5850f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            holding it temporarily in the env. */
5851f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         continue; /* for (i = 0; i < bb->stmts_used; i++) loop */
58520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      }
5853f6275b741337e8fae0108bb9a96db3498c287fc1sewardj
58540821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* we get here for any other kind of statement. */
58550821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* 'use up' any bindings required by the current statement. */
5856f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      st2 = atbSubst_Stmt(env, st);
58573e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj
5858f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      /* Now, before this stmt, dump any bindings in env that it
5859f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         invalidates.  These need to be dumped in the order in which
5860f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         they originally entered env -- that means from oldest to
5861f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         youngest. */
58623e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj
5863740da72e3938e8474234420777c17c1a4be6cb6fflorian      /* putInterval/stmtStores characterise what the stmt under
5864e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         consideration does, or might do (sidely safe @ True). */
586562140c196b8c18a23ba0fe54295f0ffa000a0054florian
586662140c196b8c18a23ba0fe54295f0ffa000a0054florian      Bool putRequiresPreciseMemExns;
5867ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      putInterval = stmt_modifies_guest_state(
5868ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                       bb, st, preciseMemExnsFn, pxControl,
5869ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                       &putRequiresPreciseMemExns
5870ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                    );
5871e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
5872e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      /* be True if this stmt writes memory or might do (==> we don't
5873e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         want to reorder other loads or stores relative to it).  Also,
5874e768e92e054cde495849a5c842a477d287677f78sewardj         both LL and SC fall under this classification, since we
5875e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         really ought to be conservative and not reorder any other
5876e768e92e054cde495849a5c842a477d287677f78sewardj         memory transactions relative to them. */
5877e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      stmtStores
5878e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         = toBool( st->tag == Ist_Store
5879088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian                   || (st->tag == Ist_Dirty
5880088809c82b9d92d415df3a0a947bc3c6dd4ccbbeflorian                       && dirty_helper_stores(st->Ist.Dirty.details))
58810f6219808968a4bf2b597a7e5ff2258fa2dda505sewardj                   || st->tag == Ist_LLSC
58820f6219808968a4bf2b597a7e5ff2258fa2dda505sewardj                   || st->tag == Ist_CAS );
58833e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj
5884f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      for (k = A_NENV-1; k >= 0; k--) {
5885f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         if (env[k].bindee == NULL)
5886f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            continue;
5887f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         /* Compare the actions of this stmt with the actions of
5888f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            binding 'k', to see if they invalidate the binding. */
5889f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         invalidateMe
58909d2e769a9368d2b22c32a4764a70e9da38769628sewardj            = toBool(
58919d2e769a9368d2b22c32a4764a70e9da38769628sewardj              /* a store invalidates loaded data */
5892f9517d0d452899780e8c34f02bef004ef7c5a163sewardj              (env[k].doesLoad && stmtStores)
5893740da72e3938e8474234420777c17c1a4be6cb6fflorian              /* a put invalidates get'd data, if they overlap */
5894740da72e3938e8474234420777c17c1a4be6cb6fflorian              || ((env[k].getInterval.present && putInterval.present) &&
5895740da72e3938e8474234420777c17c1a4be6cb6fflorian                  intervals_overlap(env[k].getInterval, putInterval))
589662140c196b8c18a23ba0fe54295f0ffa000a0054florian              /* a put invalidates loaded data. That means, in essense, that
589762140c196b8c18a23ba0fe54295f0ffa000a0054florian                 a load expression cannot be substituted into a statement
589862140c196b8c18a23ba0fe54295f0ffa000a0054florian                 that follows the put. But there is nothing wrong doing so
589962140c196b8c18a23ba0fe54295f0ffa000a0054florian                 except when the put statement requries precise exceptions.
590062140c196b8c18a23ba0fe54295f0ffa000a0054florian                 Think of a load that is moved past a put where the put
590162140c196b8c18a23ba0fe54295f0ffa000a0054florian                 updates the IP in the guest state. If the load generates
590262140c196b8c18a23ba0fe54295f0ffa000a0054florian                 a segfault, the wrong address (line number) would be
590362140c196b8c18a23ba0fe54295f0ffa000a0054florian                 reported. */
5904740da72e3938e8474234420777c17c1a4be6cb6fflorian              || (env[k].doesLoad && putInterval.present &&
5905740da72e3938e8474234420777c17c1a4be6cb6fflorian                  putRequiresPreciseMemExns)
5906c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj              /* probably overly conservative: a memory bus event
59073e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj                 invalidates absolutely everything, so that all
59083e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj                 computation prior to it is forced to complete before
5909c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj                 proceeding with the event (fence,lock,unlock). */
5910c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj              || st->tag == Ist_MBE
59115a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj              /* also be (probably overly) paranoid re AbiHints */
59125a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj              || st->tag == Ist_AbiHint
59139d2e769a9368d2b22c32a4764a70e9da38769628sewardj              );
5914f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         if (invalidateMe) {
5915dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            bb->stmts[j] = IRStmt_WrTmp( env[k].binder, env[k].bindee );
5916f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            j++;
5917f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            vassert(j <= i);
5918f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            env[k].bindee = NULL;
5919f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         }
59202d04d11c8ca8ff9643bc257780e60a77605b3af7sewardj      }
5921695cff9303ef5dc8079117acfd632b44edb1f010sewardj
5922f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      /* Slide in-use entries in env up to the front */
5923f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      m = 0;
5924f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      for (k = 0; k < A_NENV; k++) {
5925f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         if (env[k].bindee != NULL) {
5926f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            env[m] = env[k];
5927f9517d0d452899780e8c34f02bef004ef7c5a163sewardj            m++;
5928f9517d0d452899780e8c34f02bef004ef7c5a163sewardj	 }
5929f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      }
5930f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      for (m = m; m < A_NENV; m++) {
5931f9517d0d452899780e8c34f02bef004ef7c5a163sewardj         env[m].bindee = NULL;
5932f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      }
5933695cff9303ef5dc8079117acfd632b44edb1f010sewardj
59340821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      /* finally, emit the substituted statement */
59350821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      bb->stmts[j] = st2;
5936f9517d0d452899780e8c34f02bef004ef7c5a163sewardj      /* vex_printf("**2  "); ppIRStmt(bb->stmts[j]); vex_printf("\n"); */
59370821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      j++;
59380821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
59390821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      vassert(j <= i+1);
59400821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   } /* for each stmt in the original bb ... */
59410821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
59420821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* Finally ... substitute the ->next field as much as possible, and
59430821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      dump any left-over bindings.  Hmm.  Perhaps there should be no
59440821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      left over bindings?  Or any left-over bindings are
59450821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj      by definition dead? */
5946f9517d0d452899780e8c34f02bef004ef7c5a163sewardj   bb->next = atbSubst_Expr(env, bb->next);
59470821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   bb->stmts_used = j;
5948c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
5949dcd6d236c9aef7d4c84369d4c51f6b92ac910127florian   return max_ga_known ? max_ga : ~(Addr)0;
5950695cff9303ef5dc8079117acfd632b44edb1f010sewardj}
5951695cff9303ef5dc8079117acfd632b44edb1f010sewardj
59520821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
5953695cff9303ef5dc8079117acfd632b44edb1f010sewardj/*---------------------------------------------------------------*/
595416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/*--- MSVC specific transformation hacks                      ---*/
595516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/*---------------------------------------------------------------*/
595616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
595716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/* The purpose of all this is to find MSVC's idiom for non-constant
595816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   bitfield assignment, "a ^ ((a ^ b) & c)", and transform it into
595916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   gcc's idiom "(a & ~c) | (b & c)".  Motivation is that Memcheck has
596016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   generates a lot of false positives from the MSVC version because it
596116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   doesn't understand that XORing an undefined bit with itself gives a
596216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   defined result.
596316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
596416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   This isn't a problem for the simple case "x ^ x", because iropt
596516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   folds it to a constant zero before Memcheck ever sees it.  But in
596616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   this case we have an intervening "& c" which defeats the simple
596716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   case.  So we have to carefully inspect all expressions rooted at an
596816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   XOR to see if any of them match "a ^ ((a ^ b) & c)", or any of the
596916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   7 other variants resulting from swapping the order of arguments to
597016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   the three binary operations.  If we get a match, we then replace
597116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   the tree with "(a & ~c) | (b & c)", and Memcheck is happy.
597216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
597316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   The key difficulty is to spot the two uses of "a".  To normalise
597416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   the IR to maximise the chances of success, we first do a CSE pass,
597516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   with CSEing of loads enabled, since the two "a" expressions may be
597616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   loads, which need to be commoned up.  Then we do a constant folding
597716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   pass, so as to remove any tmp-to-tmp assignment chains that would
597816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   make matching the original expression more difficult.
597916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj*/
598016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
598116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
598216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/* Helper function for debug printing */
598316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj__attribute__((unused))
598416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardjstatic void print_flat_expr ( IRExpr** env, IRExpr* e )
598516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj{
598616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (e == NULL) {
598716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vex_printf("?");
598816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return;
598916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
599016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   switch (e->tag) {
599116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_Binop: {
599216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         ppIROp(e->Iex.Binop.op);
599316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf("(");
599416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         print_flat_expr(env, e->Iex.Binop.arg1);
599516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf(",");
599616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         print_flat_expr(env, e->Iex.Binop.arg2);
599716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf(")");
599816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
599916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      }
600016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_Unop: {
600116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         ppIROp(e->Iex.Unop.op);
600216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf("(");
600316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         print_flat_expr(env, e->Iex.Unop.arg);
600416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf(")");
600516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
600616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      }
600716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_RdTmp:
600816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         ppIRTemp(e->Iex.RdTmp.tmp);
600916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf("=");
6010ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         print_flat_expr(env, chase1(env, e));
601116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
601216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_Const:
601316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_CCall:
601416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_Load:
601516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_ITE:
601616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iex_Get:
601716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         ppIRExpr(e);
601816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
601916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      default:
602016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf("FAIL: "); ppIRExpr(e); vex_printf("\n");
602116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vassert(0);
602216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
602316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj}
602416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
602516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/* Spot   a ^ ((a ^ b) & c)   for a,b and c tmp-or-const (atoms)
602616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   or any of the other 7 variants generated by switching the order
602716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   of arguments to the outer ^, the inner ^ and the &.
602816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj*/
602916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardjstatic UInt spotBitfieldAssignment ( /*OUT*/IRExpr** aa, /*OUT*/IRExpr** bb,
603016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                                     /*OUT*/IRExpr** cc,
603116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                                     IRExpr** env, IRExpr* e,
603216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                                     IROp opAND, IROp opXOR)
603316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj{
603416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  define ISBIN(_e,_op) ((_e) && (_e)->tag == Iex_Binop \
603516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                              && (_e)->Iex.Binop.op == (_op))
603616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  define ISATOM(_e)    isIRAtom(_e)
603716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  define STEP(_e)      chase1(env, (_e))
603816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  define LL(_e)        ((_e)->Iex.Binop.arg1)
603916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  define RR(_e)        ((_e)->Iex.Binop.arg2)
604016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
604116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IRExpr *a1, *and, *xor, *c, *a2bL, *a2bR;
604216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
604316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* This is common to all 8 cases */
604416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(e, opXOR)) goto fail;
604516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
604616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                        -----and------ */
604716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                         --xor---      */
604816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 1:   a1 ^ ((a2 ^ b) & c) */
604916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 2:   a1 ^ ((b ^ a2) & c) */
605016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1 = and = xor = c = a2bL = a2bR = NULL;
605116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
605216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1   = LL(e);
605316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   and  = STEP(RR(e));
605416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(and, opAND)) goto v34;
605516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   xor  = STEP(LL(and));
605616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   c    = RR(and);
605716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(xor, opXOR)) goto v34;
605816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bL = LL(xor);
605916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bR = RR(xor);
606016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
606116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bL) && !eqIRAtom(a1, a2bR)) {
606216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
606316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bR;
606416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
606516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 1;
606616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
606716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bR) && !eqIRAtom(a1, a2bL)) {
606816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
606916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bL;
607016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
607116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 2;
607216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
607316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
607416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj  v34:
607516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                   -----and------      */
607616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                    --xor---           */
607716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 3:   ((a2 ^ b) & c) ^ a1 */
607816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 4:   ((b ^ a2) & c) ^ a1 */
607916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1 = and = xor = c = a2bL = a2bR = NULL;
608016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
608116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1   = RR(e);
608216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   and  = STEP(LL(e));
608316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(and, opAND)) goto v56;
608416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   xor  = STEP(LL(and));
608516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   c    = RR(and);
608616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(xor, opXOR)) goto v56;
608716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bL = LL(xor);
608816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bR = RR(xor);
608916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
609016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bL) && !eqIRAtom(a1, a2bR)) {
609116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
609216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bR;
609316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
609416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 3;
609516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
609616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bR) && !eqIRAtom(a1, a2bL)) {
609716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
609816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bL;
609916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
610016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 4;
610116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
610216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
610316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj  v56:
610416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                        -----and------ */
610516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                         --xor---      */
610616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 5:   a1 ^ (c & (a2 ^ b)) */
610716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 6:   a1 ^ (c & (b ^ a2)) */
610816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1 = and = xor = c = a2bL = a2bR = NULL;
610916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
611016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1   = LL(e);
611116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   and  = STEP(RR(e));
611216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(and, opAND)) goto v78;
611316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   xor  = STEP(RR(and));
611416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   c    = LL(and);
611516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(xor, opXOR)) goto v78;
611616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bL = LL(xor);
611716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bR = RR(xor);
611816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
611916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bL) && !eqIRAtom(a1, a2bR)) {
612016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
612116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bR;
612216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
612316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vassert(5-5); // ATC
612416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 5;
612516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
612616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bR) && !eqIRAtom(a1, a2bL)) {
612716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
612816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bL;
612916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
613016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vassert(6-6); // ATC
613116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 6;
613216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
613316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
613416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj v78:
613516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                   -----and------      */
613616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /*                    --xor---           */
613716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 7:   (c & (a2 ^ b)) ^ a1 */
613816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* find variant 8:   (c & (b ^ a2)) ^ a1 */
613916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1 = and = xor = c = a2bL = a2bR = NULL;
614016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
614116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a1   = RR(e);
614216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   and  = STEP(LL(e));
614316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(and, opAND)) goto fail;
614416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   xor  = STEP(RR(and));
614516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   c    = LL(and);
614616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (!ISBIN(xor, opXOR)) goto fail;
614716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bL = LL(xor);
614816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   a2bR = RR(xor);
614916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
615016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bL) && !eqIRAtom(a1, a2bR)) {
615116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
615216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bR;
615316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
615416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 7;
615516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
615616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (eqIRAtom(a1, a2bR) && !eqIRAtom(a1, a2bL)) {
615716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *aa = a1;
615816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *bb = a2bL;
615916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      *cc = c;
616016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return 8;
616116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
616216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
616316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj fail:
616416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   return 0;
616516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
616616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  undef ISBIN
616716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  undef ISATOM
616816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  undef STEP
616916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  undef LL
617016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj#  undef RR
617116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj}
617216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
617316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/* If |e| is of the form a ^ ((a ^ b) & c) (or any of the 7 other
617416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   variants thereof generated by switching arguments around), return
617516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   the IRExpr* for (a & ~c) | (b & c).  Else return NULL. */
617616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardjstatic IRExpr* do_XOR_TRANSFORMS_IRExpr ( IRExpr** env, IRExpr* e )
617716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj{
617816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (e->tag != Iex_Binop)
617916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return NULL;
618016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
618116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   const HChar* tyNm = NULL;
618216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IROp   opOR  = Iop_INVALID;
618316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IROp   opAND = Iop_INVALID;
618416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IROp   opNOT = Iop_INVALID;
618516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IROp   opXOR = Iop_INVALID;
618616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   switch (e->Iex.Binop.op) {
618716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iop_Xor32:
618816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         tyNm  = "I32";
618916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         opOR  = Iop_Or32;  opAND = Iop_And32;
619016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         opNOT = Iop_Not32; opXOR = Iop_Xor32;
619116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
619216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iop_Xor16:
619316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         tyNm  = "I16";
619416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         opOR  = Iop_Or16;  opAND = Iop_And16;
619516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         opNOT = Iop_Not16; opXOR = Iop_Xor16;
619616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
619716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      case Iop_Xor8:
619816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         tyNm  = "I8";
619916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         opOR  = Iop_Or8;  opAND = Iop_And8;
620016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         opNOT = Iop_Not8; opXOR = Iop_Xor8;
620116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         break;
620216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      default:
620316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         return NULL;
620416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
620516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
620616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IRExpr* aa = NULL;
620716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IRExpr* bb = NULL;
620816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   IRExpr* cc = NULL;
620916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   UInt variant = spotBitfieldAssignment(&aa, &bb, &cc, env, e, opAND, opXOR);
621016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (variant > 0) {
621116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      static UInt ctr = 0;
621216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      if (0)
621316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         vex_printf("XXXXXXXXXX Bitfield Assignment number %u, "
621416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                    "type %s, variant %u\n",
621516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                    ++ctr, tyNm, variant);
621616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      /* It's vitally important that the returned aa, bb and cc are
621716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         atoms -- either constants or tmps.  If it's anything else
621816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         (eg, a GET) then incorporating them in a tree at this point
621916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         in the SB may erroneously pull them forwards (eg of a PUT
622016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         that originally was after the GET) and so transform the IR
622116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         wrongly.  spotBitfieldAssignment should guarantee only to
622216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         give us atoms, but we check here anyway. */
622316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vassert(aa && isIRAtom(aa));
622416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vassert(bb && isIRAtom(bb));
622516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vassert(cc && isIRAtom(cc));
622616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      return IRExpr_Binop(
622716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                opOR,
622816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                IRExpr_Binop(opAND, aa, IRExpr_Unop(opNOT, cc)),
622916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                IRExpr_Binop(opAND, bb, cc)
623016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj             );
623116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
623216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   return NULL;
623316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj}
623416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
623516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
623616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/* SB is modified in-place.  Visit all the IRExprs and, for those
623716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   which are allowed to be non-atomic, perform the XOR transform if
623816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   possible.  This makes |sb| be non-flat, but that's ok, the caller
623916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   can re-flatten it.  Returns True iff any changes were made. */
624016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardjstatic Bool do_XOR_TRANSFORM_IRSB ( IRSB* sb )
624116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj{
624216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   Int  i;
624316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   Bool changed = False;
624416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
624516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   /* Make the tmp->expr environment, so we can use it for
624616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      chasing expressions. */
624716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   Int      n_tmps = sb->tyenv->types_used;
6248d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   IRExpr** env = LibVEX_Alloc_inline(n_tmps * sizeof(IRExpr*));
624916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   for (i = 0; i < n_tmps; i++)
625016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      env[i] = NULL;
625116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
625216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   for (i = 0; i < sb->stmts_used; i++) {
625316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      IRStmt* st = sb->stmts[i];
625416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      if (st->tag != Ist_WrTmp)
625516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         continue;
625616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      IRTemp t = st->Ist.WrTmp.tmp;
625716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      vassert(t >= 0 && t < n_tmps);
625816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      env[t] = st->Ist.WrTmp.data;
625916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
626016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
626116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   for (i = 0; i < sb->stmts_used; i++) {
626216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      IRStmt* st = sb->stmts[i];
626316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
626416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      switch (st->tag) {
626516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_AbiHint:
626616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.AbiHint.base));
626716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.AbiHint.nia));
626816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
626916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_Put:
627016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.Put.data));
627116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
627216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_PutI: {
627316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            IRPutI* puti = st->Ist.PutI.details;
627416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(puti->ix));
627516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(puti->data));
627616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
627716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         }
627816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_WrTmp: {
627916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            /* This is the one place where an expr (st->Ist.WrTmp.data) is
628016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               allowed to be more than just a constant or a tmp. */
628116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            IRExpr* mb_new_data
628216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               = do_XOR_TRANSFORMS_IRExpr(env, st->Ist.WrTmp.data);
628316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            if (mb_new_data) {
628416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               //ppIRSB(sb);
628516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               st->Ist.WrTmp.data = mb_new_data;
628616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               //ppIRSB(sb);
628716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               changed = True;
628816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            }
628916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
629016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         }
629116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_Store:
629216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.Store.addr));
629316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.Store.data));
629416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
629516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_StoreG: {
629616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            IRStoreG* sg = st->Ist.StoreG.details;
629716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(sg->addr));
629816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(sg->data));
629916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(sg->guard));
630016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
630116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         }
630216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_LoadG: {
630316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            IRLoadG* lg = st->Ist.LoadG.details;
630416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(lg->addr));
630516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(lg->alt));
630616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(lg->guard));
630716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
630816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         }
630916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_CAS: {
631016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            IRCAS* cas = st->Ist.CAS.details;
631116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(cas->addr));
631216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
631316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(cas->expdLo));
631416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
631516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(cas->dataLo));
631616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
631716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         }
631816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_LLSC:
631916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.LLSC.addr));
632016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            if (st->Ist.LLSC.storedata)
632116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               vassert(isIRAtom(st->Ist.LLSC.storedata));
632216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
632316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_Dirty: {
632416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            IRDirty* d = st->Ist.Dirty.details;
632516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            if (d->mFx != Ifx_None) {
632616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               vassert(isIRAtom(d->mAddr));
632716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            }
632816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(d->guard));
632916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            for (Int j = 0; d->args[j]; j++) {
633016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               IRExpr* arg = d->args[j];
6331ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg))) {
633216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj                  vassert(isIRAtom(arg));
633316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj               }
633416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            }
633516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
633616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         }
633716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_IMark:
633816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_NoOp:
633916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_MBE:
634016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
634116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         case Ist_Exit:
634216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vassert(isIRAtom(st->Ist.Exit.guard));
634316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            break;
634416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         default:
634516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vex_printf("\n"); ppIRStmt(st);
634616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj            vpanic("do_XOR_TRANSFORMS_IRSB");
634716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      }
634816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
634916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
635016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   vassert(isIRAtom(sb->next));
635116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   return changed;
635216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj}
635316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
635416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
635516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardjstatic IRSB* do_MSVC_HACKS ( IRSB* sb )
635616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj{
635716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   // Normalise as much as we can.  This is the one-and-only place
635816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   // where we call do_cse_BB with allowLoadsToBeCSEd set to True.
635916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   Bool any_cse_changes = do_cse_BB( sb, True/*allowLoadsToBeCSEd*/ );
636016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (any_cse_changes) {
636116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      // CSEing might have created dead code.  Remove it.
636216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      sb = cprop_BB ( sb );
636316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      do_deadcode_BB(sb);
636416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
636516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
636616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   // Visit all atoms, do the transformation proper.  bb is modified
636716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   // in-place.
636816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   Bool changed = do_XOR_TRANSFORM_IRSB(sb);
636916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
637016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   if (changed) {
637116caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      // The transformation generates non-flat expressions, so we now
637216caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      // need to re-flatten the block.
637316caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      sb = flatten_BB(sb);
637416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   }
637516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
637616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj   return sb;
637716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj}
637816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
637916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
638016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj/*---------------------------------------------------------------*/
6381695cff9303ef5dc8079117acfd632b44edb1f010sewardj/*--- iropt main                                              ---*/
6382695cff9303ef5dc8079117acfd632b44edb1f010sewardj/*---------------------------------------------------------------*/
6383695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6384b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic Bool iropt_verbose = False; /* True; */
6385695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6386695cff9303ef5dc8079117acfd632b44edb1f010sewardj
63874345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj/* Do a simple cleanup pass on bb.  This is: redundant Get removal,
63884345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   redundant Put removal, constant propagation, dead code removal,
63894345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   clean helper specialisation, and dead code removal (again).
6390b92307503d4fb9265136e182d10c42ebb9dd8272sewardj*/
6391695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6392d721703a7a904a66c49d0e6318c184d0076b40b0sewardj
63934345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardjstatic
6394dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjIRSB* cheap_transformations (
6395dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         IRSB* bb,
63961ff4756e1731485e6bf3cd96717cd8398daec1f2florian         IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
6397ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
6398ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         VexRegisterUpdates pxControl
63998d2291c9199adf1d0d9a5c684932d7ffe6d8e0c9sewardj      )
64004345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj{
64014345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   redundant_get_removal_BB ( bb );
64024345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   if (iropt_verbose) {
6403d721703a7a904a66c49d0e6318c184d0076b40b0sewardj      vex_printf("\n========= REDUNDANT GET\n\n" );
6404dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb);
6405d721703a7a904a66c49d0e6318c184d0076b40b0sewardj   }
6406044a215317abdd84dd7224a416595c43eedc96d3sewardj
6407ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   if (pxControl < VexRegUpdAllregsAtEachInsn) {
6408ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      redundant_put_removal_BB ( bb, preciseMemExnsFn, pxControl );
6409c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe   }
64104345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   if (iropt_verbose) {
6411f0e431671cb877601c2f2e551f42246469b4ee62sewardj      vex_printf("\n========= REDUNDANT PUT\n\n" );
6412dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb);
6413f0e431671cb877601c2f2e551f42246469b4ee62sewardj   }
6414044a215317abdd84dd7224a416595c43eedc96d3sewardj
64154345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   bb = cprop_BB ( bb );
64164345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   if (iropt_verbose) {
641784be73746586afb2ea1f197907fd7271c8d1e2ffsewardj      vex_printf("\n========= CPROPD\n\n" );
6418dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb);
641984be73746586afb2ea1f197907fd7271c8d1e2ffsewardj   }
64202963239357452b96dbe6de1b3f8b626ea3305780sewardj
642149651f4b59b1ab7e0e70cccd34001630eafbe957sewardj   do_deadcode_BB ( bb );
64224345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   if (iropt_verbose) {
642339e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj      vex_printf("\n========= DEAD\n\n" );
6424dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb);
642539e3f248ea24946bf856dd9c9baaa8cacb9a0e39sewardj   }
64262963239357452b96dbe6de1b3f8b626ea3305780sewardj
6427b92307503d4fb9265136e182d10c42ebb9dd8272sewardj   bb = spec_helpers_BB ( bb, specHelper );
642849651f4b59b1ab7e0e70cccd34001630eafbe957sewardj   do_deadcode_BB ( bb );
64294345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   if (iropt_verbose) {
643084ff0657940e62f38e618ea18bac6f27ce0e741fsewardj      vex_printf("\n========= SPECd \n\n" );
6431dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb);
643284ff0657940e62f38e618ea18bac6f27ce0e741fsewardj   }
643384ff0657940e62f38e618ea18bac6f27ce0e741fsewardj
64344345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   return bb;
64354345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj}
64364345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
6437695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6438695cff9303ef5dc8079117acfd632b44edb1f010sewardj/* Do some more expensive transformations on bb, which are aimed at
6439695cff9303ef5dc8079117acfd632b44edb1f010sewardj   optimising as much as possible in the presence of GetI and PutI.  */
6440695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6441695cff9303ef5dc8079117acfd632b44edb1f010sewardjstatic
6442ca2c3c75784d35d136fc7c952717cdee5063c193sewardjIRSB* expensive_transformations( IRSB* bb, VexRegisterUpdates pxControl )
6443695cff9303ef5dc8079117acfd632b44edb1f010sewardj{
64442608c6946f80e733875aa4969c39740fcb012c17sewardj   (void)do_cse_BB( bb, False/*!allowLoadsToBeCSEd*/ );
6445695cff9303ef5dc8079117acfd632b44edb1f010sewardj   collapse_AddSub_chains_BB( bb );
64460821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   do_redundant_GetI_elimination( bb );
6447ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   if (pxControl < VexRegUpdAllregsAtEachInsn) {
6448ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      do_redundant_PutI_elimination( bb, pxControl );
6449c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe   }
645049651f4b59b1ab7e0e70cccd34001630eafbe957sewardj   do_deadcode_BB( bb );
6451b92307503d4fb9265136e182d10c42ebb9dd8272sewardj   return bb;
6452695cff9303ef5dc8079117acfd632b44edb1f010sewardj}
6453695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6454695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6455b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj/* Scan a flattened BB to look for signs that more expensive
6456b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   optimisations might be useful:
6457b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   - find out if there are any GetIs and PutIs
6458b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   - find out if there are any floating or vector-typed temporaries
6459b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj*/
6460695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6461b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic void considerExpensives ( /*OUT*/Bool* hasGetIorPutI,
6462b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                                 /*OUT*/Bool* hasVorFtemps,
6463dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                                 IRSB* bb )
64644345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj{
6465e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   Int      i, j;
6466e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRStmt*  st;
64674345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   IRDirty* d;
6468e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRCAS*   cas;
64694345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
6470b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   *hasGetIorPutI = False;
6471b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   *hasVorFtemps  = False;
6472b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
64734345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   for (i = 0; i < bb->stmts_used; i++) {
64744345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj      st = bb->stmts[i];
64754345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj      switch (st->tag) {
64765a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj         case Ist_AbiHint:
64775a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj            vassert(isIRAtom(st->Ist.AbiHint.base));
6478478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            vassert(isIRAtom(st->Ist.AbiHint.nia));
64795a9ffab9150b7cca31d44d48da998d011bbe8e6asewardj            break;
64804345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj         case Ist_PutI:
6481b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            *hasGetIorPutI = True;
6482b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            break;
6483dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         case Ist_WrTmp:
6484dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            if (st->Ist.WrTmp.data->tag == Iex_GetI)
6485b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               *hasGetIorPutI = True;
6486dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            switch (typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp)) {
6487b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               case Ity_I1: case Ity_I8: case Ity_I16:
6488b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               case Ity_I32: case Ity_I64: case Ity_I128:
6489b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  break;
64903738bfcea70600334c830de5421adc0204890c95sewardj               case Ity_F16: case Ity_F32: case Ity_F64: case Ity_F128:
6491c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj               case Ity_V128: case Ity_V256:
6492b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  *hasVorFtemps = True;
6493c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                  break;
6494c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               case Ity_D32: case Ity_D64: case Ity_D128:
6495c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                  *hasVorFtemps = True;
6496b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  break;
6497b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               default:
6498b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  goto bad;
6499b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            }
65004345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            break;
65014345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj         case Ist_Put:
6502496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj            vassert(isIRAtom(st->Ist.Put.data));
65034345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            break;
6504af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj         case Ist_Store:
6505af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj            vassert(isIRAtom(st->Ist.Store.addr));
6506af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj            vassert(isIRAtom(st->Ist.Store.data));
65074345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            break;
6508cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_StoreG: {
6509cfe046e178666280b87da998b1b52ecda03ecd89sewardj            IRStoreG* sg = st->Ist.StoreG.details;
6510cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(isIRAtom(sg->addr));
6511cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(isIRAtom(sg->data));
6512cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(isIRAtom(sg->guard));
6513cfe046e178666280b87da998b1b52ecda03ecd89sewardj            break;
6514cfe046e178666280b87da998b1b52ecda03ecd89sewardj         }
6515cfe046e178666280b87da998b1b52ecda03ecd89sewardj         case Ist_LoadG: {
6516cfe046e178666280b87da998b1b52ecda03ecd89sewardj            IRLoadG* lg = st->Ist.LoadG.details;
6517cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(isIRAtom(lg->addr));
6518cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(isIRAtom(lg->alt));
6519cfe046e178666280b87da998b1b52ecda03ecd89sewardj            vassert(isIRAtom(lg->guard));
6520cfe046e178666280b87da998b1b52ecda03ecd89sewardj            break;
6521cfe046e178666280b87da998b1b52ecda03ecd89sewardj         }
6522e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         case Ist_CAS:
6523e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            cas = st->Ist.CAS.details;
6524e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            vassert(isIRAtom(cas->addr));
6525e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            vassert(cas->expdHi == NULL || isIRAtom(cas->expdHi));
6526e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            vassert(isIRAtom(cas->expdLo));
6527e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
6528e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            vassert(isIRAtom(cas->dataLo));
6529e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            break;
6530e768e92e054cde495849a5c842a477d287677f78sewardj         case Ist_LLSC:
6531e768e92e054cde495849a5c842a477d287677f78sewardj            vassert(isIRAtom(st->Ist.LLSC.addr));
6532e768e92e054cde495849a5c842a477d287677f78sewardj            if (st->Ist.LLSC.storedata)
6533e768e92e054cde495849a5c842a477d287677f78sewardj               vassert(isIRAtom(st->Ist.LLSC.storedata));
6534e768e92e054cde495849a5c842a477d287677f78sewardj            break;
65354345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj         case Ist_Dirty:
65364345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            d = st->Ist.Dirty.details;
6537496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj            vassert(isIRAtom(d->guard));
653874142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            for (j = 0; d->args[j]; j++) {
653974142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj               IRExpr* arg = d->args[j];
6540ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
654174142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj                  vassert(isIRAtom(arg));
654274142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj            }
65434345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            if (d->mFx != Ifx_None)
6544496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj               vassert(isIRAtom(d->mAddr));
65454345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            break;
6546d2445f60726580b450eca68ab40c568f9df338e2sewardj         case Ist_NoOp:
6547f168931fd8a8256c020c9b90d5f2e05f1e6c48c7sewardj         case Ist_IMark:
6548c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         case Ist_MBE:
65493e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj            break;
65503e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj         case Ist_Exit:
6551496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj            vassert(isIRAtom(st->Ist.Exit.guard));
65523e83893fff6c7bbc955d4529cd922df4ed9b23cdsewardj            break;
65534345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj         default:
6554b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         bad:
65554345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj            ppIRStmt(st);
6556e768e92e054cde495849a5c842a477d287677f78sewardj            vpanic("considerExpensives");
65574345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj      }
65584345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   }
65594345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj}
65604345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
65614345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
6562695cff9303ef5dc8079117acfd632b44edb1f010sewardj/* ---------------- The main iropt entry point. ---------------- */
6563695cff9303ef5dc8079117acfd632b44edb1f010sewardj
65644345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj/* exported from this file */
6565695cff9303ef5dc8079117acfd632b44edb1f010sewardj/* Rules of the game:
6566695cff9303ef5dc8079117acfd632b44edb1f010sewardj
6567695cff9303ef5dc8079117acfd632b44edb1f010sewardj   - IRExpr/IRStmt trees should be treated as immutable, as they
6568695cff9303ef5dc8079117acfd632b44edb1f010sewardj     may get shared.  So never change a field of such a tree node;
6569695cff9303ef5dc8079117acfd632b44edb1f010sewardj     instead construct and return a new one if needed.
6570695cff9303ef5dc8079117acfd632b44edb1f010sewardj*/
6571695cff9303ef5dc8079117acfd632b44edb1f010sewardj
65724345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
6573be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardjIRSB* do_iropt_BB(
6574be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj         IRSB* bb0,
65751ff4756e1731485e6bf3cd96717cd8398daec1f2florian         IRExpr* (*specHelper) (const HChar*, IRExpr**, IRStmt**, Int),
6576ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         Bool (*preciseMemExnsFn)(Int,Int,VexRegisterUpdates),
6577ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         VexRegisterUpdates pxControl,
6578d4cc0deec55ec0be1f2ac3b20f0d340265341f83florian         Addr    guest_addr,
6579be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj         VexArch guest_arch
6580be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      )
65814345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj{
65829d2e769a9368d2b22c32a4764a70e9da38769628sewardj   static Int n_total     = 0;
65839d2e769a9368d2b22c32a4764a70e9da38769628sewardj   static Int n_expensive = 0;
65844345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
6585b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool hasGetIorPutI, hasVorFtemps;
6586dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   IRSB *bb, *bb2;
65878c2c10bcac223041c2d8f5e0a41a2c28261dab0fsewardj
65884345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   n_total++;
65894345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
65904345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   /* First flatten the block out, since all other
65914345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj      phases assume flat code. */
65924345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
65934345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   bb = flatten_BB ( bb0 );
65944345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
65954345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   if (iropt_verbose) {
65964345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj      vex_printf("\n========= FLAT\n\n" );
6597dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      ppIRSB(bb);
65984345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   }
65994345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
66000821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   /* If at level 0, stop now. */
66010821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj   if (vex_control.iropt_level <= 0) return bb;
66020821053bd75b33ab1f5a7d84cdb1550d2b066a8fsewardj
6603695cff9303ef5dc8079117acfd632b44edb1f010sewardj   /* Now do a preliminary cleanup pass, and figure out if we also
6604695cff9303ef5dc8079117acfd632b44edb1f010sewardj      need to do 'expensive' optimisations.  Expensive optimisations
6605695cff9303ef5dc8079117acfd632b44edb1f010sewardj      are deemed necessary if the block contains any GetIs or PutIs.
6606695cff9303ef5dc8079117acfd632b44edb1f010sewardj      If needed, do expensive transformations and then another cheap
6607695cff9303ef5dc8079117acfd632b44edb1f010sewardj      cleanup pass. */
66084345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj
6609ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   bb = cheap_transformations( bb, specHelper, preciseMemExnsFn, pxControl );
661039555aa10bcda6a509563698398ea2d5fdd45fdbsewardj
6611be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj   if (guest_arch == VexArchARM) {
6612be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      /* Translating Thumb2 code produces a lot of chaff.  We have to
6613be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj         work extra hard to get rid of it. */
6614be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      bb = cprop_BB(bb);
6615be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      bb = spec_helpers_BB ( bb, specHelper );
6616ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      if (pxControl < VexRegUpdAllregsAtEachInsn) {
6617ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         redundant_put_removal_BB ( bb, preciseMemExnsFn, pxControl );
6618c8e2f983c84affb3cbe4cebee1516aedaf944f79philippe      }
66192608c6946f80e733875aa4969c39740fcb012c17sewardj      do_cse_BB( bb, False/*!allowLoadsToBeCSEd*/ );
6620be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj      do_deadcode_BB( bb );
6621be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj   }
6622be9179130bdfb61d0e03ecb32eced8dd5c7bfc74sewardj
662308613749b639323cc7582c1bbe56c6e21c69774fsewardj   if (vex_control.iropt_level > 1) {
6624b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
6625b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* Peer at what we have, to decide how much more effort to throw
6626b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         at it. */
6627b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      considerExpensives( &hasGetIorPutI, &hasVorFtemps, bb );
6628b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
66299b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj      if (hasVorFtemps && !hasGetIorPutI) {
6630b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* If any evidence of FP or Vector activity, CSE, as that
6631b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            tends to mop up all manner of lardy code to do with
66329b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            rounding modes.  Don't bother if hasGetIorPutI since that
66339b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            case leads into the expensive transformations, which do
66349b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj            CSE anyway. */
66352608c6946f80e733875aa4969c39740fcb012c17sewardj         (void)do_cse_BB( bb, False/*!allowLoadsToBeCSEd*/ );
6636b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         do_deadcode_BB( bb );
6637b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      }
6638b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
6639b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (hasGetIorPutI) {
66409b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         Bool cses;
664139555aa10bcda6a509563698398ea2d5fdd45fdbsewardj         n_expensive++;
664239555aa10bcda6a509563698398ea2d5fdd45fdbsewardj         if (DEBUG_IROPT)
664339555aa10bcda6a509563698398ea2d5fdd45fdbsewardj            vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive);
6644ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         bb = expensive_transformations( bb, pxControl );
6645ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         bb = cheap_transformations( bb, specHelper,
6646ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                                     preciseMemExnsFn, pxControl );
66479b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         /* Potentially common up GetIs */
66482608c6946f80e733875aa4969c39740fcb012c17sewardj         cses = do_cse_BB( bb, False/*!allowLoadsToBeCSEd*/ );
66499b0cc5856f608e2779f8e1855d224299c7cbe8d4sewardj         if (cses)
6650ca2c3c75784d35d136fc7c952717cdee5063c193sewardj            bb = cheap_transformations( bb, specHelper,
6651ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                                        preciseMemExnsFn, pxControl );
6652695cff9303ef5dc8079117acfd632b44edb1f010sewardj      }
665339555aa10bcda6a509563698398ea2d5fdd45fdbsewardj
665416caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      ///////////////////////////////////////////////////////////
665516caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      // BEGIN MSVC optimised code transformation hacks
665616caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      if (0)
665716caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj         bb = do_MSVC_HACKS(bb);
665816caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      // END   MSVC optimised code transformation hacks
665916caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj      ///////////////////////////////////////////////////////////
666016caded3d5c2be18c9f4ee0f1d957d23d2b6bbccsewardj
666139555aa10bcda6a509563698398ea2d5fdd45fdbsewardj      /* Now have a go at unrolling simple (single-BB) loops.  If
666239555aa10bcda6a509563698398ea2d5fdd45fdbsewardj         successful, clean up the results as much as possible. */
666339555aa10bcda6a509563698398ea2d5fdd45fdbsewardj
666439555aa10bcda6a509563698398ea2d5fdd45fdbsewardj      bb2 = maybe_loop_unroll_BB( bb, guest_addr );
666539555aa10bcda6a509563698398ea2d5fdd45fdbsewardj      if (bb2) {
6666ca2c3c75784d35d136fc7c952717cdee5063c193sewardj         bb = cheap_transformations( bb2, specHelper,
6667ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                                     preciseMemExnsFn, pxControl );
6668b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (hasGetIorPutI) {
6669ca2c3c75784d35d136fc7c952717cdee5063c193sewardj            bb = expensive_transformations( bb, pxControl );
6670ca2c3c75784d35d136fc7c952717cdee5063c193sewardj            bb = cheap_transformations( bb, specHelper,
6671ca2c3c75784d35d136fc7c952717cdee5063c193sewardj                                        preciseMemExnsFn, pxControl );
667239555aa10bcda6a509563698398ea2d5fdd45fdbsewardj         } else {
667339555aa10bcda6a509563698398ea2d5fdd45fdbsewardj            /* at least do CSE and dead code removal */
66742608c6946f80e733875aa4969c39740fcb012c17sewardj            do_cse_BB( bb, False/*!allowLoadsToBeCSEd*/ );
667549651f4b59b1ab7e0e70cccd34001630eafbe957sewardj            do_deadcode_BB( bb );
667639555aa10bcda6a509563698398ea2d5fdd45fdbsewardj         }
667739555aa10bcda6a509563698398ea2d5fdd45fdbsewardj         if (0) vex_printf("vex iropt: unrolled a loop\n");
667839555aa10bcda6a509563698398ea2d5fdd45fdbsewardj      }
667939555aa10bcda6a509563698398ea2d5fdd45fdbsewardj
66802963239357452b96dbe6de1b3f8b626ea3305780sewardj   }
66812963239357452b96dbe6de1b3f8b626ea3305780sewardj
66824345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj   return bb;
6683edf4d69c8477cad95851d0f6ccf91ab323e5a446sewardj}
6684edf4d69c8477cad95851d0f6ccf91ab323e5a446sewardj
6685edf4d69c8477cad95851d0f6ccf91ab323e5a446sewardj
6686a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*---------------------------------------------------------------*/
6687cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                            ir_opt.c ---*/
6688a1a370fcecc7b4ed6989498b4fc0166558758bfdsewardj/*---------------------------------------------------------------*/
6689