From: Josef Weidendorfer Date: Thu, 2 Sep 2010 17:06:49 +0000 (+0000) Subject: Fix branch predictor simulation in Cachegrind X-Git-Tag: svn/VALGRIND_3_6_0~126 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=afc1a37745ced0a7d0e0b4bc29c8386799a035df;p=thirdparty%2Fvalgrind.git Fix branch predictor simulation in Cachegrind * do indirect branch prediction simulation on calls via function pointers * only call into conditional branch prediction simulation on real guest code branches (eg. not for VEX emulation of some instructions using branches of jumpkind Ijk_EmWarn) git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11331 --- diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index cb0af56821..07d008f1ad 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -1070,60 +1070,66 @@ IRSB* cg_instrument ( VgCallbackClosure* closure, } case Ist_Exit: { - /* Stuff to widen the guard expression to a host word, so - we can pass it to the branch predictor simulation - functions easily. */ - Bool inverted; - Addr64 nia, sea; - IRConst* dst; - IRType tyW = hWordTy; - IROp widen = tyW==Ity_I32 ? Iop_1Uto32 : Iop_1Uto64; - IROp opXOR = tyW==Ity_I32 ? Iop_Xor32 : Iop_Xor64; - IRTemp guard1 = newIRTemp(cgs.sbOut->tyenv, Ity_I1); - IRTemp guardW = newIRTemp(cgs.sbOut->tyenv, tyW); - IRTemp guard = newIRTemp(cgs.sbOut->tyenv, tyW); - IRExpr* one = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1)) - : IRExpr_Const(IRConst_U64(1)); - - /* First we need to figure out whether the side exit got - inverted by the ir optimiser. To do that, figure out - the next (fallthrough) instruction's address and the - side exit address and see if they are the same. */ - nia = cia + (Addr64)isize; - if (tyW == Ity_I32) - nia &= 0xFFFFFFFFULL; - - /* Side exit address */ - dst = st->Ist.Exit.dst; - if (tyW == Ity_I32) { - tl_assert(dst->tag == Ico_U32); - sea = (Addr64)(UInt)dst->Ico.U32; - } else { - tl_assert(tyW == Ity_I64); - tl_assert(dst->tag == Ico_U64); - sea = dst->Ico.U64; + // call branch predictor only if this is a branch in guest code + if ( (st->Ist.Exit.jk == Ijk_Boring) || + (st->Ist.Exit.jk == Ijk_Call) || + (st->Ist.Exit.jk == Ijk_Ret) ) + { + /* Stuff to widen the guard expression to a host word, so + we can pass it to the branch predictor simulation + functions easily. */ + Bool inverted; + Addr64 nia, sea; + IRConst* dst; + IRType tyW = hWordTy; + IROp widen = tyW==Ity_I32 ? Iop_1Uto32 : Iop_1Uto64; + IROp opXOR = tyW==Ity_I32 ? Iop_Xor32 : Iop_Xor64; + IRTemp guard1 = newIRTemp(cgs.sbOut->tyenv, Ity_I1); + IRTemp guardW = newIRTemp(cgs.sbOut->tyenv, tyW); + IRTemp guard = newIRTemp(cgs.sbOut->tyenv, tyW); + IRExpr* one = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1)) + : IRExpr_Const(IRConst_U64(1)); + + /* First we need to figure out whether the side exit got + inverted by the ir optimiser. To do that, figure out + the next (fallthrough) instruction's address and the + side exit address and see if they are the same. */ + nia = cia + (Addr64)isize; + if (tyW == Ity_I32) + nia &= 0xFFFFFFFFULL; + + /* Side exit address */ + dst = st->Ist.Exit.dst; + if (tyW == Ity_I32) { + tl_assert(dst->tag == Ico_U32); + sea = (Addr64)(UInt)dst->Ico.U32; + } else { + tl_assert(tyW == Ity_I64); + tl_assert(dst->tag == Ico_U64); + sea = dst->Ico.U64; + } + + inverted = nia == sea; + + /* Widen the guard expression. */ + addStmtToIRSB( cgs.sbOut, + IRStmt_WrTmp( guard1, st->Ist.Exit.guard )); + addStmtToIRSB( cgs.sbOut, + IRStmt_WrTmp( guardW, + IRExpr_Unop(widen, + IRExpr_RdTmp(guard1))) ); + /* If the exit is inverted, invert the sense of the guard. */ + addStmtToIRSB( + cgs.sbOut, + IRStmt_WrTmp( + guard, + inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one) + : IRExpr_RdTmp(guardW) + )); + /* And post the event. */ + addEvent_Bc( &cgs, curr_inode, IRExpr_RdTmp(guard) ); } - inverted = nia == sea; - - /* Widen the guard expression. */ - addStmtToIRSB( cgs.sbOut, - IRStmt_WrTmp( guard1, st->Ist.Exit.guard )); - addStmtToIRSB( cgs.sbOut, - IRStmt_WrTmp( guardW, - IRExpr_Unop(widen, - IRExpr_RdTmp(guard1))) ); - /* If the exit is inverted, invert the sense of the guard. */ - addStmtToIRSB( - cgs.sbOut, - IRStmt_WrTmp( - guard, - inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one) - : IRExpr_RdTmp(guardW) - )); - /* And post the event. */ - addEvent_Bc( &cgs, curr_inode, IRExpr_RdTmp(guard) ); - /* We may never reach the next statement, so need to flush all outstanding transactions now. */ flushEvents( &cgs ); @@ -1147,7 +1153,7 @@ IRSB* cg_instrument ( VgCallbackClosure* closure, /* Deal with branches to unknown destinations. Except ignore ones which are function returns as we assume the return stack predictor never mispredicts. */ - if (sbIn->jumpkind == Ijk_Boring) { + if ((sbIn->jumpkind == Ijk_Boring) || (sbIn->jumpkind == Ijk_Call)) { if (0) { ppIRExpr( sbIn->next ); VG_(printf)("\n"); } switch (sbIn->next->tag) { case Iex_Const: