📄 iropt.c
字号:
e2 = IRExpr_Const(IRConst_U64( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 - e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))); break; /* -- Mul -- */ case Iop_Mul32: 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_Mul64: e2 = IRExpr_Const(IRConst_U64( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 * e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))); break; case Iop_MullS32: { /* very paranoid */ UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; Int s32a = (Int)u32a; Int s32b = (Int)u32b; Long s64a = (Long)s32a; Long s64b = (Long)s32b; Long sres = s64a * s64b; ULong ures = (ULong)sres; e2 = IRExpr_Const(IRConst_U64(ures)); break; } /* -- Shl -- */ case Iop_Shl32: vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); if (shift >= 0 && shift <= 31) e2 = IRExpr_Const(IRConst_U32( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 << shift))); break; case Iop_Shl64: vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); if (shift >= 0 && shift <= 63) e2 = IRExpr_Const(IRConst_U64( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 << shift))); break; /* -- Sar -- */ case Iop_Sar32: { /* paranoid ... */ /*signed*/ Int s32; vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); s32 = (Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); if (shift >= 0 && shift <= 31) { s32 >>=/*signed*/ shift; e2 = IRExpr_Const(IRConst_U32((UInt)s32)); } break; } case Iop_Sar64: { /* paranoid ... */ /*signed*/ Long s64; vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); s64 = (Long)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); if (shift >= 0 && shift <= 63) { s64 >>=/*signed*/ shift; e2 = IRExpr_Const(IRConst_U64((ULong)s64)); } break; } /* -- Shr -- */ case Iop_Shr32: { /* paranoid ... */ /*unsigned*/ UInt u32; vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); u32 = (UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); if (shift >= 0 && shift <= 31) { u32 >>=/*unsigned*/ shift; e2 = IRExpr_Const(IRConst_U32(u32)); } break; } case Iop_Shr64: { /* paranoid ... */ /*unsigned*/ ULong u64; vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); u64 = (ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U64); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); if (shift >= 0 && shift <= 63) { u64 >>=/*unsigned*/ shift; e2 = IRExpr_Const(IRConst_U64(u64)); } break; } /* -- CmpEQ -- */ case Iop_CmpEQ32: e2 = IRExpr_Const(IRConst_U1(toBool( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 == e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))); break; case Iop_CmpEQ64: e2 = IRExpr_Const(IRConst_U1(toBool( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 == e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))); break; /* -- CmpNE -- */ case Iop_CmpNE8: e2 = IRExpr_Const(IRConst_U1(toBool( ((0xFF & e->Iex.Binop.arg1->Iex.Const.con->Ico.U8) != (0xFF & e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))))); break; case Iop_CmpNE32: e2 = IRExpr_Const(IRConst_U1(toBool( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 != e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)))); break; case Iop_CmpNE64: e2 = IRExpr_Const(IRConst_U1(toBool( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 != e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)))); break; /* -- CmpLEU -- */ case Iop_CmpLE32U: e2 = IRExpr_Const(IRConst_U1(toBool( ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32) <= (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))))); break; /* -- CmpLES -- */ case Iop_CmpLE32S: e2 = IRExpr_Const(IRConst_U1(toBool( ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32) <= (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))))); break; /* -- CmpLTS -- */ case Iop_CmpLT32S: e2 = IRExpr_Const(IRConst_U1(toBool( ((Int)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32) < (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))))); break; /* -- CmpLTU -- */ case Iop_CmpLT32U: e2 = IRExpr_Const(IRConst_U1(toBool( ((UInt)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32) < (UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))))); break; /* -- CmpORD -- */ case Iop_CmpORD32S: { /* very paranoid */ UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; Int s32a = (Int)u32a; Int s32b = (Int)u32b; Int r = 0x2; /* EQ */ if (s32a < s32b) { r = 0x8; /* LT */ } else if (s32a > s32b) { r = 0x4; /* GT */ } e2 = IRExpr_Const(IRConst_U32(r)); break; } /* -- nHLto2n -- */ case Iop_32HLto64: e2 = IRExpr_Const(IRConst_U64( (((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)) << 32) | ((ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)) )); break; case Iop_64HLto128: /* We can't fold this, because there is no way to express he result in IR, but at least pretend to handle it, so as to stop getting blasted with no-rule-for-this-primop messages. */ break; default: goto unhandled; } } else { /* other cases (identities, etc) */ /* Shl64/Shr64(x,0) ==> x */ if ((e->Iex.Binop.op == Iop_Shl64 || e->Iex.Binop.op == Iop_Shr64) && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 == 0) { e2 = e->Iex.Binop.arg1; } else /* Shl32/Shr32(x,0) ==> x */ if ((e->Iex.Binop.op == Iop_Shl32 || e->Iex.Binop.op == Iop_Shr32) && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 == 0) { e2 = e->Iex.Binop.arg1; } else /* Or8(x,0) ==> x */ if ((e->Iex.Binop.op == Iop_Or8) && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 == 0) { e2 = e->Iex.Binop.arg1; } else /* Or16(x,0) ==> x */ if ((e->Iex.Binop.op == Iop_Or16) && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U16 == 0) { e2 = e->Iex.Binop.arg1; } else /* Or32/Add32(x,0) ==> x */ if ((e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Or32) && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U32 == 0) { e2 = e->Iex.Binop.arg1; } else /* Or64/Add64(x,0) ==> x */ if ((e->Iex.Binop.op == Iop_Add64 || e->Iex.Binop.op == Iop_Or64) && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U64 == 0) { e2 = e->Iex.Binop.arg1; } else /* And32(x,0xFFFFFFFF) ==> x */ if (e->Iex.Binop.op == Iop_And32 && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U32 == 0xFFFFFFFF) { e2 = e->Iex.Binop.arg1; } else /* And32(x,0) ==> 0 */ if (e->Iex.Binop.op == Iop_And32 && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->Ico.U32 == 0) { e2 = IRExpr_Const(IRConst_U32(0)); } else /* Or32(0,x) ==> x */ if (e->Iex.Binop.op == Iop_Or32 && e->Iex.Binop.arg1->tag == Iex_Const && e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 == 0) { e2 = e->Iex.Binop.arg2; } else /* Or8/16/32/64(t,t) ==> t, for some IRTemp t */ /* And8/16/32/64(t,t) ==> t, for some IRTemp t */ if ( (e->Iex.Binop.op == Iop_And64 || e->Iex.Binop.op == Iop_And32 || e->Iex.Binop.op == Iop_And16 || e->Iex.Binop.op == Iop_And8 || e->Iex.Binop.op == Iop_Or64 || e->Iex.Binop.op == Iop_Or32 || e->Iex.Binop.op == Iop_Or16 || e->Iex.Binop.op == Iop_Or8) && sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2)) { e2 = e->Iex.Binop.arg1; } /* Xor8/16/32/64(t,t) ==> 0, for some IRTemp t */ if ( (e->Iex.Binop.op == Iop_Xor64 || e->Iex.Binop.op == Iop_Xor32 || e->Iex.Binop.op == Iop_Xor16 || e->Iex.Binop.op == Iop_Xor8) && sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2)) { e2 = mkZeroForXor(e->Iex.Binop.op); } } } /* Mux0X */ if (e->tag == Iex_Mux0X && e->Iex.Mux0X.cond->tag == Iex_Const) { Bool zero; /* assured us by the IR type rules */ vassert(e->Iex.Mux0X.cond->Iex.Const.con->tag == Ico_U8); zero = toBool(0 == (0xFF & e->Iex.Mux0X.cond ->Iex.Const.con->Ico.U8)); e2 = zero ? e->Iex.Mux0X.expr0 : e->Iex.Mux0X.exprX; } if (DEBUG_IROPT && e2 != e) { vex_printf("FOLD: "); ppIRExpr(e); vex_printf(" -> "); ppIRExpr(e2); vex_printf("\n"); } return e2; unhandled:# if 0 vex_printf("\n\n"); ppIRExpr(e); vpanic("fold_Expr: no rule for the above");# else if (vex_control.iropt_verbosity > 0) { vex_printf("vex iropt: fold_Expr: no rule for: "); ppIRExpr(e); vex_printf("\n"); } return e2;# endif}/* Apply the subst to a simple 1-level expression -- guaranteed to be 1-level due to previous flattening pass. */static IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex ){ switch (ex->tag) { case Iex_Tmp: if (env[(Int)ex->Iex.Tmp.tmp] != NULL) { return env[(Int)ex->Iex.Tmp.tmp]; } else { /* not bound in env */ return ex; } case Iex_Const: case Iex_Get: return ex; case Iex_GetI: vassert(isIRAtom(ex->Iex.GetI.ix)); return IRExpr_GetI( ex->Iex.GetI.descr, subst_Expr(env, ex->Iex.GetI.ix), ex->Iex.GetI.bias ); case Iex_Binop: vassert(isIRAtom(ex->Iex.Binop.arg1)); vassert(isIRAtom(ex->Iex.Binop.arg2)); return IRExpr_Binop( ex->Iex.Binop.op, subst_Expr(env, ex->Iex.Binop.arg1), subst_Expr(env, ex->Iex.Binop.arg2) ); case Iex_Unop: vassert(isIRAtom(ex->Iex.Unop.arg)); return IRExpr_Unop( ex->Iex.Unop.op, subst_Expr(env, ex->Iex.Unop.arg) ); case Iex_Load: vassert(isIRAtom(ex->Iex.Load.addr)); return IRExpr_Load( ex->Iex.Load.end, ex->Iex.Load.ty, subst_Expr(env, ex->Iex.Load.addr) ); case Iex_CCall: { Int i; IRExpr** args2 = sopyIRExprVec(ex->Iex.CCall.args); for (i = 0; args2[i]; i++) { vassert(isIRAtom(args2[i])); args2[i] = subst_Expr(env, args2[i]); } return IRExpr_CCall( ex->Iex.CCall.cee, ex->Iex.CCall.retty, args2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -