iropt.c

来自「The Valgrind distribution has multiple t」· C语言 代码 · 共 1,868 行 · 第 1/5 页

C
1,868
字号
         of the environment corresponding to guest state that may not         be reordered with respect to memory references.  That means         at least the stack pointer. */      for (j = 0; j < env->used; j++) {         if (!env->inuse[j])            continue;         if (vex_control.iropt_precise_memory_exns) {            /* Precise exceptions required.  Flush all guest state. */            env->inuse[j] = False;         } else {            /* Just flush the minimal amount required, as computed by               preciseMemExnsFn. */            HWord k_lo = (env->key[j] >> 16) & 0xFFFF;            HWord k_hi = env->key[j] & 0xFFFF;            if (preciseMemExnsFn( k_lo, k_hi ))               env->inuse[j] = False;         }      }   } /* if (memRW) */}/* Scan backwards, building up a set of (min offset, max   offset) pairs, indicating those parts of the guest state   for which the next event is a write.   On seeing a conditional exit, empty the set.   On seeing 'Put (minoff,maxoff) = t or c', if (minoff,maxoff) is   completely within the set, remove the Put.  Otherwise, add   (minoff,maxoff) to the set.   On seeing 'Get (minoff,maxoff)', remove any part of the set   overlapping (minoff,maxoff).  The same has to happen for any events   which implicitly read parts of the guest state: dirty helper calls   and loads/stores.*/static void redundant_put_removal_BB (                IRBB* bb,               Bool (*preciseMemExnsFn)(Int,Int)            ){   Int     i, j;   Bool    isPut;   IRStmt* st;   UInt    key = 0; /* keep gcc -O happy */   HashHW* env = newHHW();   for (i = bb->stmts_used-1; i >= 0; i--) {      st = bb->stmts[i];      if (st->tag == Ist_NoOp)         continue;      /* Deal with conditional exits. */      if (st->tag == Ist_Exit) {         /* Since control may not get beyond this point, we must empty            out the set, since we can no longer claim that the next            event for any part of the guest state is definitely a            write. */         vassert(isIRAtom(st->Ist.Exit.guard));         for (j = 0; j < env->used; j++)            env->inuse[j] = False;         continue;      }      /* Deal with Puts */      switch (st->tag) {         case Ist_Put:             isPut = True;            key = mk_key_GetPut( st->Ist.Put.offset,                                  typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );            vassert(isIRAtom(st->Ist.Put.data));            break;         case Ist_PutI:            isPut = True;            key = mk_key_GetIPutI( st->Ist.PutI.descr );            vassert(isIRAtom(st->Ist.PutI.ix));            vassert(isIRAtom(st->Ist.PutI.data));            break;         default:             isPut = False;      }      if (isPut && st->tag != Ist_PutI) {         /* See if any single entry in env overlaps this Put.  This is            simplistic in that the transformation is valid if, say, two            or more entries in the env overlap this Put, but the use of            lookupHHW will only find a single entry which exactly            overlaps this Put.  This is suboptimal but safe. */         if (lookupHHW(env, NULL, (HWord)key)) {            /* This Put is redundant because a later one will overwrite               it.  So NULL (nop) it out. */            if (DEBUG_IROPT) {               vex_printf("rPUT: "); ppIRStmt(st);               vex_printf("\n");            }            bb->stmts[i] = IRStmt_NoOp();         } else {            /* We can't demonstrate that this Put is redundant, so add it               to the running collection. */            addToHHW(env, (HWord)key, 0);         }         continue;      }      /* Deal with Gets.  These remove bits of the environment since         appearance of a Get means that the next event for that slice         of the guest state is no longer a write, but a read.  Also         deals with implicit reads of guest state needed to maintain         precise exceptions. */      handle_gets_Stmt( env, st, preciseMemExnsFn );   }}/*---------------------------------------------------------------*//*--- Constant propagation and folding                        ---*//*---------------------------------------------------------------*//* The env in this section is a map from IRTemp to IRExpr*,   that is, an array indexed by IRTemp. *//* Are both expressions simply the same IRTemp ? */static Bool sameIRTemps ( IRExpr* e1, IRExpr* e2 ){   return toBool( e1->tag == Iex_Tmp                  && e2->tag == Iex_Tmp                  && e1->Iex.Tmp.tmp == e2->Iex.Tmp.tmp );}static Bool notBool ( Bool b ){   if (b == True) return False;   if (b == False) return True;   vpanic("notBool");}/* Make a zero which has the same type as the result of the given   primop. */static IRExpr* mkZeroForXor ( IROp op ){   switch (op) {      case Iop_Xor8:  return IRExpr_Const(IRConst_U8(0));      case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));      case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));      case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));      default: vpanic("mkZeroForXor: bad primop");   }}static IRExpr* fold_Expr ( IRExpr* e ){   Int     shift;   IRExpr* e2 = e; /* e2 is the result of folding e, if possible */   /* UNARY ops */   if (e->tag == Iex_Unop       && e->Iex.Unop.arg->tag == Iex_Const) {      switch (e->Iex.Unop.op) {         case Iop_1Uto8:            e2 = IRExpr_Const(IRConst_U8(toUChar(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 1 : 0)));            break;         case Iop_1Uto32:            e2 = IRExpr_Const(IRConst_U32(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 1 : 0));            break;         case Iop_1Uto64:            e2 = IRExpr_Const(IRConst_U64(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 1 : 0));            break;         case Iop_1Sto8:            e2 = IRExpr_Const(IRConst_U8(toUChar(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 0xFF : 0)));            break;         case Iop_1Sto16:            e2 = IRExpr_Const(IRConst_U16(toUShort(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 0xFFFF : 0)));            break;         case Iop_1Sto32:            e2 = IRExpr_Const(IRConst_U32(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 0xFFFFFFFF : 0));            break;         case Iop_1Sto64:            e2 = IRExpr_Const(IRConst_U64(                    e->Iex.Unop.arg->Iex.Const.con->Ico.U1                    ? 0xFFFFFFFFFFFFFFFFULL : 0));            break;         case Iop_8Sto32: {            /* signed */ Int s32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U8;            s32 <<= 24;            s32 >>= 24;            e2 = IRExpr_Const(IRConst_U32((UInt)s32));            break;         }         case Iop_8Uto64:            e2 = IRExpr_Const(IRConst_U64(                    0xFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));            break;         case Iop_16Uto64:            e2 = IRExpr_Const(IRConst_U64(                    0xFFFFULL & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));            break;         case Iop_8Uto32:            e2 = IRExpr_Const(IRConst_U32(                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8));            break;         case Iop_16Uto32:            e2 = IRExpr_Const(IRConst_U32(                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U16));            break;         case Iop_32to16:            e2 = IRExpr_Const(IRConst_U16(toUShort(                    0xFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));            break;         case Iop_32to8:            e2 = IRExpr_Const(IRConst_U8(toUChar(                    0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));            break;         case Iop_32to1:            e2 = IRExpr_Const(IRConst_U1(toBool(                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)                 )));            break;         case Iop_64to1:            e2 = IRExpr_Const(IRConst_U1(toBool(                    1 == (1 & e->Iex.Unop.arg->Iex.Const.con->Ico.U64)                 )));            break;         case Iop_Not64:            e2 = IRExpr_Const(IRConst_U64(                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U64)));            break;         case Iop_Not32:            e2 = IRExpr_Const(IRConst_U32(                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));            break;         case Iop_Not16:            e2 = IRExpr_Const(IRConst_U16(toUShort(                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U16))));            break;         case Iop_Not8:            e2 = IRExpr_Const(IRConst_U8(toUChar(                    ~ (e->Iex.Unop.arg->Iex.Const.con->Ico.U8))));            break;         case Iop_Not1:            e2 = IRExpr_Const(IRConst_U1(                    notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));            break;         case Iop_Neg64:            e2 = IRExpr_Const(IRConst_U64(                    - (e->Iex.Unop.arg->Iex.Const.con->Ico.U64)));            break;         case Iop_Neg32:            e2 = IRExpr_Const(IRConst_U32(                    - (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));            break;         case Iop_Neg8:            e2 = IRExpr_Const(IRConst_U8(toUChar(                    - (e->Iex.Unop.arg->Iex.Const.con->Ico.U8))));            break;         case Iop_64to8: {            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;            w64 &= 0xFFULL;            e2 = IRExpr_Const(IRConst_U8( (UChar)w64 ));            break;         }         case Iop_64to16: {            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;            w64 &= 0xFFFFULL;            e2 = IRExpr_Const(IRConst_U16( (UShort)w64 ));            break;         }         case Iop_64to32: {            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;            w64 &= 0x00000000FFFFFFFFULL;            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));            break;         }         case Iop_64HIto32: {            ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;            w64 >>= 32;            e2 = IRExpr_Const(IRConst_U32( (UInt)w64 ));            break;         }         case Iop_32Uto64:            e2 = IRExpr_Const(IRConst_U64(                    0xFFFFFFFFULL                     & e->Iex.Unop.arg->Iex.Const.con->Ico.U32));            break;         case Iop_CmpNEZ8:            e2 = IRExpr_Const(IRConst_U1(toBool(                    0 !=                     (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)                 )));            break;         case Iop_CmpNEZ32:            e2 = IRExpr_Const(IRConst_U1(toBool(                    0 !=                     (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)                 )));            break;         case Iop_CmpNEZ64:            e2 = IRExpr_Const(IRConst_U1(toBool(                    0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64                 )));            break;         default:             goto unhandled;      }   }   /* BINARY ops */   if (e->tag == Iex_Binop) {      if (e->Iex.Binop.arg1->tag == Iex_Const          && e->Iex.Binop.arg2->tag == Iex_Const) {         /* cases where both args are consts */         switch (e->Iex.Binop.op) {            /* -- Or -- */            case Iop_Or8:               e2 = IRExpr_Const(IRConst_U8(toUChar(                        (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));               break;            case Iop_Or16:               e2 = IRExpr_Const(IRConst_U16(toUShort(                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));               break;            case Iop_Or32:               e2 = IRExpr_Const(IRConst_U32(                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));               break;            case Iop_Or64:               e2 = IRExpr_Const(IRConst_U64(                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64                        | e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)));               break;            /* -- Xor -- */            case Iop_Xor8:               e2 = IRExpr_Const(IRConst_U8(toUChar(                        (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))));               break;            case Iop_Xor16:               e2 = IRExpr_Const(IRConst_U16(toUShort(                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U16))));               break;            case Iop_Xor32:               e2 = IRExpr_Const(IRConst_U32(                       (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32                        ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));               break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?