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