📄 iropt.c
字号:
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_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; case Iop_Xor64: e2 = IRExpr_Const(IRConst_U64( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 ^ e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))); break; /* -- And -- */ case Iop_And8: 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_And32: 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_And64: e2 = IRExpr_Const(IRConst_U64( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 & e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))); break; /* -- Add -- */ case Iop_Add8: 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_Add32: 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_Add64: e2 = IRExpr_Const(IRConst_U64( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 + e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))); break; /* -- Sub -- */ case Iop_Sub8: 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_Sub32: 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_Sub64:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -