You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
1
(7) |
2
(7) |
3
(11) |
4
(3) |
5
(6) |
|
6
(14) |
7
(25) |
8
(14) |
9
(21) |
10
(16) |
11
(3) |
12
(12) |
|
13
|
14
(5) |
15
(11) |
16
(4) |
17
(18) |
18
(15) |
19
|
|
20
(1) |
21
(14) |
22
(7) |
23
(14) |
24
(9) |
25
(14) |
26
(5) |
|
27
(12) |
28
(1) |
29
(5) |
30
|
|
|
|
|
From: <sv...@va...> - 2011-11-14 21:21:09
|
Author: weidendo
Date: 2011-11-14 21:16:25 +0000 (Mon, 14 Nov 2011)
New Revision: 12269
Log:
Callgrind: use jmpkind from VEX for side exits.
To detect calls and returns, Callgrind's heuristic
starts with using the jumpkind got from VEX for
a control flow change instruction. However, for
side exits, it always assumed a (conditional) jump,
which holds true for x86, but e.g. not for ARM.
This fixes Callgrind to use the jumpkind found
by VEX for all exits, which should help making
Callgrind work for ARM. It also moves the check
whether a boring jump is actually a fall-through
to instrumentation time. This changes (fixes) the
result for indirect jumps to the next instruction,
which should not be classified as fall-through
(anyway, this case is probably very rare).
This patch introduces an own enum for jump kinds
in Callgrind. This is less confusing than misusing
the VEX jump kind type, as Callgrinds wants
to distinguish BB fall-throughs from real jumps
(which both are Ijk_Boring in VEX).
Also, setup_bbcc now stores separately whether the
jump kind is conditional or not.
Modified:
trunk/callgrind/bbcc.c
trunk/callgrind/callstack.c
trunk/callgrind/dump.c
trunk/callgrind/global.h
trunk/callgrind/jumps.c
trunk/callgrind/main.c
Modified: trunk/callgrind/bbcc.c
===================================================================
--- trunk/callgrind/bbcc.c 2011-11-14 19:01:21 UTC (rev 12268)
+++ trunk/callgrind/bbcc.c 2011-11-14 21:16:25 UTC (rev 12269)
@@ -555,7 +555,9 @@
Addr sp;
BB* last_bb;
ThreadId tid;
- Int jmpkind, passed = 0, csp;
+ ClgJumpKind jmpkind;
+ Bool isConditionalJump;
+ Int passed = 0, csp;
Bool ret_without_call = False;
Int popcount_on_return = 1;
@@ -581,17 +583,9 @@
if (last_bb) {
passed = CLG_(current_state).jmps_passed;
CLG_ASSERT(passed <= last_bb->cjmp_count);
- if (passed == last_bb->cjmp_count) {
- jmpkind = last_bb->jmpkind;
+ jmpkind = last_bb->jmp[passed].jmpkind;
+ isConditionalJump = (passed < last_bb->cjmp_count);
- /* VEX always gives a Boring jump kind also when passed trough */
- if ((jmpkind == Ijk_Boring) &&
- (last_bb->offset + last_bb->instr_len == bb->offset))
- jmpkind = JmpNone;
- }
- else
- jmpkind = JmpCond;
-
/* if we are in a function which is skipped in the call graph, we
* do not increment the exe counter to produce cost (if simulation off),
* which would lead to dumping this BB to be skipped
@@ -612,7 +606,8 @@
}
}
else {
- jmpkind = JmpNone;
+ jmpkind = jk_None;
+ isConditionalJump = False;
}
/* Manipulate JmpKind if needed, only using BB specific info */
@@ -620,7 +615,7 @@
csp = CLG_(current_call_stack).sp;
/* A return not matching the top call in our callstack is a jump */
- if ( (jmpkind == Ijk_Ret) && (csp >0)) {
+ if ( (jmpkind == jk_Return) && (csp >0)) {
Int csp_up = csp-1;
call_entry* top_ce = &(CLG_(current_call_stack).entry[csp_up]);
@@ -650,14 +645,14 @@
}
}
if (popcount_on_return == 0) {
- jmpkind = Ijk_Boring;
+ jmpkind = jk_Jump;
ret_without_call = True;
}
}
/* Should this jump be converted to call or pop/call ? */
- if (( jmpkind != Ijk_Ret) &&
- ( jmpkind != Ijk_Call) && last_bb) {
+ if (( jmpkind != jk_Return) &&
+ ( jmpkind != jk_Call) && last_bb) {
/* We simulate a JMP/Cont to be a CALL if
* - jump is in another ELF object or section kind
@@ -701,30 +696,32 @@
}
}
- jmpkind = Ijk_Call;
+ jmpkind = jk_Call;
call_emulation = True;
}
}
- if (jmpkind == Ijk_Call)
+ if (jmpkind == jk_Call)
skip = CLG_(get_fn_node)(bb)->skip;
CLG_DEBUGIF(1) {
- if (jmpkind == JmpCond)
- VG_(printf)("Conditional");
- else if (jmpkind == JmpNone)
- VG_(printf)("None");
- else
- ppIRJumpKind( jmpkind );
-
- VG_(printf)(" %08lx -> %08lx, SP %08lx\n",
- last_bb ? bb_jmpaddr(last_bb) : 0,
- bb_addr(bb), sp);
+ if (isConditionalJump)
+ VG_(printf)("Cond-");
+ switch(jmpkind) {
+ case jk_None: VG_(printf)("Fall-through"); break;
+ case jk_Jump: VG_(printf)("Jump"); break;
+ case jk_Call: VG_(printf)("Call"); break;
+ case jk_Return: VG_(printf)("Return"); break;
+ default: tl_assert(0);
+ }
+ VG_(printf)(" %08lx -> %08lx, SP %08lx\n",
+ last_bb ? bb_jmpaddr(last_bb) : 0,
+ bb_addr(bb), sp);
}
/* Handle CALL/RET and update context to get correct BBCC */
- if (jmpkind == Ijk_Ret) {
+ if (jmpkind == jk_Return) {
if ((csp == 0) ||
((CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom) &&
@@ -745,10 +742,10 @@
Int unwind_count = CLG_(unwind_call_stack)(sp, 0);
if (unwind_count > 0) {
/* if unwinding was done, this actually is a return */
- jmpkind = Ijk_Ret;
+ jmpkind = jk_Return;
}
- if (jmpkind == Ijk_Call) {
+ if (jmpkind == jk_Call) {
delayed_push = True;
csp = CLG_(current_call_stack).sp;
@@ -848,8 +845,7 @@
bbcc, sp, skip);
}
- if (CLG_(clo).collect_jumps &&
- ((jmpkind == JmpCond) || (jmpkind == Ijk_Boring))) {
+ if (CLG_(clo).collect_jumps && (jmpkind == jk_Jump)) {
/* Handle conditional jumps followed, i.e. trace arcs
* This uses JCC structures, too */
@@ -857,15 +853,15 @@
jCC* jcc = CLG_(get_jcc)(last_bbcc, passed, bbcc);
CLG_ASSERT(jcc != 0);
// Change from default, and check if already changed
- if (jcc->jmpkind == Ijk_Call)
- jcc->jmpkind = jmpkind;
+ if (jcc->jmpkind == jk_Call)
+ jcc->jmpkind = isConditionalJump ? jk_CondJump : jk_Jump;
else {
// FIXME: Why can this fail?
// CLG_ASSERT(jcc->jmpkind == jmpkind);
}
jcc->call_counter++;
- if (jmpkind == JmpCond)
+ if (isConditionalJump)
CLG_(stat).jcnd_counter++;
else
CLG_(stat).jump_counter++;
Modified: trunk/callgrind/callstack.c
===================================================================
--- trunk/callgrind/callstack.c 2011-11-14 19:01:21 UTC (rev 12268)
+++ trunk/callgrind/callstack.c 2011-11-14 21:16:25 UTC (rev 12269)
@@ -235,8 +235,14 @@
/* return address is only is useful with a real call;
* used to detect RET w/o CALL */
- ret_addr = (from->bb->jmpkind == Ijk_Call) ?
- bb_addr(from->bb) + from->bb->instr_len : 0;
+ if (from->bb->jmp[jmp].jmpkind == jk_Call) {
+ UInt instr = from->bb->jmp[jmp].instr;
+ ret_addr = bb_addr(from->bb) +
+ from->bb->instr[instr].instr_offset +
+ from->bb->instr[instr].instr_size;
+ }
+ else
+ ret_addr = 0;
/* put jcc on call stack */
current_entry->jcc = jcc;
Modified: trunk/callgrind/dump.c
===================================================================
--- trunk/callgrind/dump.c 2011-11-14 19:01:21 UTC (rev 12268)
+++ trunk/callgrind/dump.c 2011-11-14 21:16:25 UTC (rev 12269)
@@ -669,7 +669,7 @@
target.file = last->file;
}
- if ((jcc->jmpkind == JmpCond) || (jcc->jmpkind == Ijk_Boring)) {
+ if ((jcc->jmpkind == jk_CondJump) || (jcc->jmpkind == jk_Jump)) {
/* this is a JCC for a followed conditional or boring jump. */
CLG_ASSERT(CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost));
@@ -703,7 +703,7 @@
print_fn(fd, outbuf, "jfn", jcc->to->cxt->fn[0]);
}
- if (jcc->jmpkind == JmpCond) {
+ if (jcc->jmpkind == jk_CondJump) {
/* format: jcnd=<followed>/<executions> <target> */
VG_(sprintf)(outbuf, "jcnd=%llu/%llu ",
jcc->call_counter, ecounter);
@@ -834,7 +834,7 @@
if (bb->jmp[jmp].instr == instr) {
jcc_count=0;
for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from)
- if (((jcc->jmpkind != Ijk_Call) && (jcc->call_counter >0)) ||
+ if (((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
(!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
jcc_count++;
@@ -848,7 +848,7 @@
fprint_apos(fd, &(currCost->p), last, bbcc->cxt->fn[0]->file);
something_written = True;
for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
- if (((jcc->jmpkind != Ijk_Call) && (jcc->call_counter >0)) ||
+ if (((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
(!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
fprint_jcc(fd, jcc, &(currCost->p), last, ecounter);
}
@@ -867,7 +867,7 @@
jcc_count = 0;
for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
/* yes, if JCC only counts jmp arcs or cost >0 */
- if ( ((jcc->jmpkind != Ijk_Call) && (jcc->call_counter >0)) ||
+ if ( ((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
(!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
jcc_count++;
}
@@ -901,7 +901,7 @@
if (jcc_count > 0)
for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
CLG_ASSERT(jcc->jmp == jmp);
- if ( ((jcc->jmpkind != Ijk_Call) && (jcc->call_counter >0)) ||
+ if ( ((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
(!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
fprint_jcc(fd, jcc, &(currCost->p), last, ecounter);
Modified: trunk/callgrind/global.h
===================================================================
--- trunk/callgrind/global.h 2011-11-14 19:01:21 UTC (rev 12268)
+++ trunk/callgrind/global.h 2011-11-14 21:16:25 UTC (rev 12269)
@@ -229,6 +229,18 @@
typedef ULong* FullCost; /* Simulator + User */
+/* The types of control flow changes that can happen between
+ * execution of two BBs in a thread.
+ */
+typedef enum {
+ jk_None = 0, /* no explicit change by a guest instruction */
+ jk_Jump, /* regular jump */
+ jk_Call,
+ jk_Return,
+ jk_CondJump /* conditional jump taken (only used as jCC type) */
+} ClgJumpKind;
+
+
/* JmpCall cost center
* for subroutine call (from->bb->jmp_addr => to->bb->addr)
*
@@ -248,11 +260,9 @@
* After updating, <last> is set to current event counters. Thus,
* events are not counted twice for recursive calls (TODO: True?)
*/
-#define JmpNone (Ijk_Boring+30)
-#define JmpCond (Ijk_Boring+31)
struct _jCC {
- Int jmpkind; /* JmpCall, JmpBoring, JmpCond */
+ ClgJumpKind jmpkind; /* jk_Call, jk_Jump, jk_CondJump */
jCC* next_hash; /* for hash entry chain */
jCC* next_from; /* next JCC from a BBCC */
BBCC *from, *to; /* call arc from/to this BBCC */
@@ -276,13 +286,14 @@
};
+
/*
- * Info for a conditional jump in a basic block
+ * Info for a side exit in a BB
*/
typedef struct _CJmpInfo CJmpInfo;
struct _CJmpInfo {
- UInt instr; /* instruction index in this basic block */
- Bool skip; /* Cond.Jumps to next instruction should be ignored */
+ UInt instr; /* instruction index for BB.instr array */
+ ClgJumpKind jmpkind; /* jump kind when leaving BB at this side exit */
};
@@ -319,11 +330,10 @@
BBCC* last_bbcc; /* Temporary: Cached for faster access (LRU) */
/* filled by CLG_(instrument) if not seen before */
- UInt cjmp_count; /* number of conditional exits */
+ UInt cjmp_count; /* number of side exits */
CJmpInfo* jmp; /* array of info for condition jumps,
* allocated directly after this struct */
- Int jmpkind; /* remember jump kind of final exit */
- Bool cjmp_inverted; /* condition of last cond.jump can be inverted by VEX */
+ Bool cjmp_inverted; /* is last side exit actually fall through? */
UInt instr_len;
UInt cost_count;
@@ -357,12 +367,12 @@
/*
- * Info for a conditional jump in a basic block
+ * Cost info for a side exits from a BB
*/
typedef struct _JmpData JmpData;
struct _JmpData {
ULong ecounter; /* number of times the BB was left at this exit */
- jCC* jcc_list; /* JCCs for Cond.Jumps from this exit */
+ jCC* jcc_list; /* JCCs used for this exit */
};
Modified: trunk/callgrind/jumps.c
===================================================================
--- trunk/callgrind/jumps.c 2011-11-14 19:01:21 UTC (rev 12268)
+++ trunk/callgrind/jumps.c 2011-11-14 21:16:25 UTC (rev 12269)
@@ -152,7 +152,7 @@
jcc->from = from;
jcc->jmp = jmp;
jcc->to = to;
- jcc->jmpkind = Ijk_Call;
+ jcc->jmpkind = jk_Call;
jcc->call_counter = 0;
jcc->cost = 0;
Modified: trunk/callgrind/main.c
===================================================================
--- trunk/callgrind/main.c 2011-11-14 19:01:21 UTC (rev 12268)
+++ trunk/callgrind/main.c 2011-11-14 21:16:25 UTC (rev 12269)
@@ -1146,8 +1146,20 @@
CLG_ASSERT(clgs.ii_index>0);
if (!clgs.seen_before) {
- clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
- clgs.bb->jmp[cJumps].skip = False;
+ ClgJumpKind jk;
+
+ if (st->Ist.Exit.jk == Ijk_Call) jk = jk_Call;
+ else if (st->Ist.Exit.jk == Ijk_Ret) jk = jk_Return;
+ else {
+ if (IRConst2Addr(st->Ist.Exit.dst) ==
+ origAddr + curr_inode->instr_offset + curr_inode->instr_size)
+ jk = jk_None;
+ else
+ jk = jk_Jump;
+ }
+
+ clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
+ clgs.bb->jmp[cJumps].jmpkind = jk;
}
/* Update global variable jmps_passed before the jump
@@ -1212,18 +1224,45 @@
CLG_ASSERT(clgs.bb->cjmp_count == cJumps);
CLG_ASSERT(clgs.bb->instr_count = clgs.ii_index);
- /* This stores the instr of the call/ret at BB end */
- clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
+ /* Info for final exit from BB */
+ {
+ ClgJumpKind jk;
+ if (sbIn->jumpkind == Ijk_Call) jk = jk_Call;
+ else if (sbIn->jumpkind == Ijk_Ret) jk = jk_Return;
+ else {
+ jk = jk_Jump;
+ if ((sbIn->next->tag == Iex_Const) &&
+ (IRConst2Addr(sbIn->next->Iex.Const.con) ==
+ origAddr + clgs.instr_offset))
+ jk = jk_None;
+ }
+ clgs.bb->jmp[cJumps].jmpkind = jk;
+ /* Instruction index of the call/ret at BB end
+ * (it is wrong for fall-through, but does not matter) */
+ clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
+ }
+
+ /* swap information of last exit with final exit if inverted */
+ if (clgs.bb->cjmp_inverted) {
+ ClgJumpKind jk;
+ UInt instr;
+
+ jk = clgs.bb->jmp[cJumps].jmpkind;
+ clgs.bb->jmp[cJumps].jmpkind = clgs.bb->jmp[cJumps-1].jmpkind;
+ clgs.bb->jmp[cJumps-1].jmpkind = jk;
+ instr = clgs.bb->jmp[cJumps].instr;
+ clgs.bb->jmp[cJumps].instr = clgs.bb->jmp[cJumps-1].instr;
+ clgs.bb->jmp[cJumps-1].instr = instr;
+ }
+
if (clgs.seen_before) {
CLG_ASSERT(clgs.bb->cost_count == update_cost_offsets(&clgs));
CLG_ASSERT(clgs.bb->instr_len = clgs.instr_offset);
- CLG_ASSERT(clgs.bb->jmpkind == sbIn->jumpkind);
}
else {
clgs.bb->cost_count = update_cost_offsets(&clgs);
clgs.bb->instr_len = clgs.instr_offset;
- clgs.bb->jmpkind = sbIn->jumpkind;
}
CLG_DEBUG(3, "- instrument(BB %#lx): byteLen %u, CJumps %u, CostLen %u\n",
|
|
From: Thomas R. <tr...@st...> - 2011-11-14 21:07:40
|
Julian Seward wrote: > > > No takers? :-( > > The PowerPC back end (host_ppc_isel.c) does support exact rounding > on all FP instructions. Have a look at how it avoids setting the > rounding mode for every FP instruction. Ok, I see. I took that approach and made more patches. I filed it all in https://bugs.kde.org/show_bug.cgi?id=136779 to avoid more big attachment spam. One thing I don't get however: why does the PPC backend not put any rounding on instructions like Add32Fx4? Is that an oversight, or does the processor actually not support rounding modes there? > So, an important question which I didn't see addressed by your > previous message is, what is the effect on performance? Comparing the following versions: * vg-nord: valgrind r12232, VEX r2225 (the base version I built on) * vg-slowrd: as per the patches posted, with a few fixes * valgrind: vg-slowrd plus the PPC backend's strategy I'm getting the following out of the perf/ tests: -- bigcode1 -- bigcode1 vg-nord :0.11s no: 2.1s (19.2x, -----) me: 3.9s (35.2x, -----) bigcode1 vg-slowrd :0.11s no: 2.1s (19.0x, 0.9%) me: 3.9s (35.2x, 0.0%) bigcode1 valgrind :0.11s no: 2.1s (18.9x, 1.4%) me: 3.9s (35.0x, 0.5%) -- bigcode2 -- bigcode2 vg-nord :0.12s no: 4.5s (37.8x, -----) me: 9.3s (77.2x, -----) bigcode2 vg-slowrd :0.12s no: 4.5s (37.3x, 1.3%) me: 9.3s (77.7x, -0.6%) bigcode2 valgrind :0.12s no: 4.5s (37.5x, 0.9%) me: 9.5s (79.4x, -2.9%) -- bz2 -- bz2 vg-nord :0.55s no: 2.9s ( 5.2x, -----) me: 8.0s (14.5x, -----) bz2 vg-slowrd :0.55s no: 3.0s ( 5.4x, -4.5%) me: 8.3s (15.1x, -4.4%) bz2 valgrind :0.55s no: 2.9s ( 5.2x, -0.7%) me: 8.5s (15.4x, -6.4%) -- fbench -- fbench vg-nord :0.25s no: 1.3s ( 5.1x, -----) me: 4.3s (17.3x, -----) fbench vg-slowrd :0.25s no: 1.7s ( 6.7x,-32.3%) me: 4.8s (19.1x,-10.6%) fbench valgrind :0.25s no: 1.2s ( 5.0x, 2.4%) me: 4.4s (17.7x, -2.5%) -- ffbench -- ffbench vg-nord :0.21s no: 0.9s ( 4.1x, -----) me: 2.9s (14.0x, -----) ffbench vg-slowrd :0.21s no: 1.2s ( 5.9x,-42.5%) me: 3.2s (15.2x, -8.8%) ffbench valgrind :0.21s no: 0.9s ( 4.4x, -5.7%) me: 3.0s (14.1x, -1.0%) -- heap -- heap vg-nord :0.10s no: 1.0s ( 9.8x, -----) me: 6.6s (66.3x, -----) heap vg-slowrd :0.10s no: 1.0s ( 9.8x, 0.0%) me: 6.6s (66.1x, 0.3%) heap valgrind :0.10s no: 0.8s ( 8.5x, 13.3%) me: 6.6s (65.6x, 1.1%) -- sarp -- sarp vg-nord :0.02s no: 0.2s (10.5x, -----) me: 2.3s (116.5x, -----) sarp vg-slowrd :0.02s no: 0.2s (10.5x, 0.0%) me: 2.7s (136.0x,-16.7%) sarp valgrind :0.02s no: 0.2s (10.5x, 0.0%) me: 2.4s (122.0x, -4.7%) -- tinycc -- tinycc vg-nord :0.18s no: 2.3s (12.7x, -----) me:11.0s (60.9x, -----) tinycc vg-slowrd :0.18s no: 2.3s (12.9x, -1.7%) me:10.9s (60.8x, 0.1%) tinycc valgrind :0.18s no: 2.3s (13.0x, -2.2%) me:10.9s (60.6x, 0.5%) So apparently it's essentially the same, except that slowrd is really slow in floating point stuff and the PPC strategy again gets it into the same ballpark as before. I cannot explain the huge speedup in 'heap', but it's really consistent at that. Then I'm also seeing some test failures that all seem to be related to line numbers, such as in memcheck/tests/addressable --- addressable.stderr.exp 2010-11-24 16:47:41.933247339 +0100 +++ addressable.stderr.out 2011-11-14 22:02:40.798433827 +0100 @@ -61,7 +61,7 @@ For counts of detected and suppressed errors, rerun with: -v ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Uninitialised byte(s) found during client check request - at 0x........: test5 (addressable.c:85) + at 0x........: test5 (addressable.c:87) by 0x........: main (addressable.c:125) Address 0x........ is not stack'd, malloc'd or (recently) free'd Do you have any pointers as to what could be going wrong there? I'm somewhat at a loss, since that test doesn't seem to have anything to do with floats. Other test failures concern the definedness of FP results, I'll have to look into that. Apparently my strategy of ignoring the rounding mode argument within memcheck was too simple... -- Thomas Rast trast@{inf,student}.ethz.ch |
|
From: <sv...@va...> - 2011-11-14 19:06:06
|
Author: weidendo
Date: 2011-11-14 19:01:21 +0000 (Mon, 14 Nov 2011)
New Revision: 12268
Log:
callgrind: remove command file polling
This is the last part of moving from command file polling
to the vgdb ptrace method for interactive control of Callgrind.
VG 3.7.x ported callgrind_control to vgdb (in r11867), but
still did command file polling to support existing KCachegrind
releases. KCachegrind from upcoming KDE SC 4.8 will use
callgrind_control instead of manually writing command files.
The main benefit from this is, apart from getting rid of
continous file polling activity in Callgrind, that blocked
processes can now respond to callgrind_control.
Removed:
trunk/callgrind/command.c
Modified:
trunk/callgrind/Makefile.am
trunk/callgrind/global.h
trunk/callgrind/main.c
trunk/callgrind/threads.c
Modified: trunk/callgrind/Makefile.am
===================================================================
--- trunk/callgrind/Makefile.am 2011-11-11 04:04:12 UTC (rev 12267)
+++ trunk/callgrind/Makefile.am 2011-11-14 19:01:21 UTC (rev 12268)
@@ -35,7 +35,6 @@
bbcc.c \
callstack.c \
clo.c \
- command.c \
context.c \
costs.c \
debug.c \
Deleted: trunk/callgrind/command.c
===================================================================
--- trunk/callgrind/command.c 2011-11-11 04:04:12 UTC (rev 12267)
+++ trunk/callgrind/command.c 2011-11-14 19:01:21 UTC (rev 12268)
@@ -1,535 +0,0 @@
-/*
- This file is part of Callgrind, a Valgrind tool for call graph
- profiling programs.
-
- Copyright (C) 2002-2011, Josef Weidendorfer (Jos...@gm...)
-
- This tool is derived from and contains lot of code from Cachegrind
- Copyright (C) 2002-2011 Nicholas Nethercote (nj...@va...)
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-/*
- * Functions related to interactive commands via "callgrind.cmd"
- */
-
-#include "config.h"
-#include "global.h"
-
-#include "pub_tool_threadstate.h" // VG_N_THREADS
-
-// Version for the syntax in command/result files for interactive control
-#define COMMAND_VERSION "1.0"
-
-static Char outbuf[FILENAME_LEN + FN_NAME_LEN + OBJ_NAME_LEN];
-
-static Char* command_file = 0;
-static Char* command_file2 = 0;
-static Char* current_command_file = 0;
-static Char* result_file = 0;
-static Char* result_file2 = 0;
-static Char* current_result_file = 0;
-static Char* info_file = 0;
-static Char* out_file = 0;
-
-static Int thisPID = 0;
-
-/**
- * Setup for interactive control of a callgrind run
- */
-static void setup_control(void)
-{
- Int fd, size;
- SysRes res;
- Char* dir;
- const HChar *tmpdir;
-
- CLG_ASSERT(thisPID != 0);
-
- fd = -1;
- dir = CLG_(get_out_directory)();
- out_file = CLG_(get_out_file)();
-
- /* name of command file */
- size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_COMMANDNAME) +10;
- command_file = (char*) CLG_MALLOC("cl.command.sc.1", size);
- CLG_ASSERT(command_file != 0);
- VG_(sprintf)(command_file, "%s/%s.%d",
- dir, DEFAULT_COMMANDNAME, thisPID);
-
- /* This is for compatibility with the "Force Now" Button of current
- * KCachegrind releases, as it doesn't use ".pid" to distinguish
- * different callgrind instances from same base directory.
- */
- command_file2 = (char*) CLG_MALLOC("cl.command.sc.2", size);
- CLG_ASSERT(command_file2 != 0);
- VG_(sprintf)(command_file2, "%s/%s",
- dir, DEFAULT_COMMANDNAME);
-
- size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_RESULTNAME) +10;
- result_file = (char*) CLG_MALLOC("cl.command.sc.3", size);
- CLG_ASSERT(result_file != 0);
- VG_(sprintf)(result_file, "%s/%s.%d",
- dir, DEFAULT_RESULTNAME, thisPID);
-
- /* If we get a command from a command file without .pid, use
- * a result file without .pid suffix
- */
- result_file2 = (char*) CLG_MALLOC("cl.command.sc.4", size);
- CLG_ASSERT(result_file2 != 0);
- VG_(sprintf)(result_file2, "%s/%s",
- dir, DEFAULT_RESULTNAME);
-
- tmpdir = VG_(tmpdir)();
- info_file = (char*) CLG_MALLOC("cl.command.sc.5",
- VG_(strlen)(tmpdir) +
- VG_(strlen)(DEFAULT_INFONAME) + 10);
- CLG_ASSERT(info_file != 0);
- VG_(sprintf)(info_file, "%s/%s.%d", tmpdir, DEFAULT_INFONAME, thisPID);
-
- CLG_DEBUG(1, "Setup for interactive control (PID: %d):\n", thisPID);
- CLG_DEBUG(1, " output file: '%s'\n", out_file);
- CLG_DEBUG(1, " command file: '%s'\n", command_file);
- CLG_DEBUG(1, " result file: '%s'\n", result_file);
- CLG_DEBUG(1, " info file: '%s'\n", info_file);
-
- /* create info file to indicate that we are running */
- res = VG_(open)(info_file, VKI_O_WRONLY|VKI_O_TRUNC, 0);
- if (sr_isError(res)) {
- res = VG_(open)(info_file, VKI_O_CREAT|VKI_O_WRONLY,
- VKI_S_IRUSR|VKI_S_IWUSR);
- if (sr_isError(res)) {
- VG_(message)(Vg_DebugMsg,
- "warning: can't write info file '%s'\n", info_file);
- info_file = 0;
- fd = -1;
- }
- }
- if (!sr_isError(res))
- fd = (Int) sr_Res(res);
- if (fd>=0) {
- Char buf[512];
- Int i;
-
- WRITE_STR3(fd,
- "# This file is generated by Callgrind-" VERSION ".\n"
- "# It is used to enable controlling the supervision of\n"
- "# '", VG_(args_the_exename), "'\n"
- "# by external tools.\n\n");
-
- VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- WRITE_STR3(fd, "base: ", dir, "\n");
- WRITE_STR3(fd, "dumps: ", out_file, "\n");
- WRITE_STR3(fd, "control: ", command_file, "\n");
- WRITE_STR3(fd, "result: ", result_file, "\n");
-
- WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
- for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
- HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
- if (!arg) continue;
- WRITE_STR2(fd, " ", arg);
- }
- VG_(write)(fd, "\n", 1);
- VG_(close)(fd);
- }
-}
-
-void CLG_(init_command)()
-{
- thisPID = VG_(getpid)();
- setup_control();
-}
-
-void CLG_(finish_command)()
-{
- /* unlink info file */
- if (info_file) VG_(unlink)(info_file);
-}
-
-
-static Int createRes(Int fd)
-{
- SysRes res;
-
- if (fd > -2) return fd;
-
- /* fd == -2: No error, but we need to create the file */
- CLG_ASSERT(current_result_file != 0);
- res = VG_(open)(current_result_file,
- VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
- VKI_S_IRUSR|VKI_S_IWUSR);
-
- /* VG_(open) can return any negative number on error. Remap errors to -1,
- * to not confuse it with our special value -2
- */
- if (sr_isError(res)) fd = -1;
- else fd = (Int) sr_Res(res);
-
- return fd;
-}
-
-/* Run Info: Persistant information of the callgrind run */
-static Int dump_info(Int fd)
-{
- Char* buf = outbuf;
- int i;
-
- if ( (fd = createRes(fd)) <0) return fd;
-
- /* creator */
- VG_(sprintf)(buf, "creator: callgrind-" VERSION "\n");
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- /* version */
- VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- /* "pid:" line */
- VG_(sprintf)(buf, "pid: %d\n", VG_(getpid)());
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- /* "base:" line */
- WRITE_STR3(fd, "base: ", out_file, "\n");
-
- /* "cmd:" line */
- WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
- for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
- HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
- if (!arg) continue;
- WRITE_STR2(fd, " ", arg);
- }
- VG_(write)(fd, "\n", 1);
-
- return fd;
-}
-
-
-/* Helper for dump_state */
-
-Int dump_fd;
-
-void static dump_state_of_thread(thread_info* ti)
-{
- Char* buf = outbuf;
- int t = CLG_(current_tid);
- Int p, i;
- static FullCost sum = 0, tmp = 0;
- BBCC *from, *to;
- call_entry* ce;
-
- p = VG_(sprintf)(buf, "events-%d: ", t);
- CLG_(init_cost_lz)( CLG_(sets).full, &sum );
- CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
- CLG_(add_diff_cost)( CLG_(sets).full, sum,
- ti->lastdump_cost,
- ti->states.entry[0]->cost);
- CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
- p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum);
- p += VG_(sprintf)(buf+p, "\n");
- VG_(write)(dump_fd, (void*)buf, p);
-
- p = VG_(sprintf)(buf, "frames-%d: %d\n", t,
- CLG_(current_call_stack).sp);
- VG_(write)(dump_fd, (void*)buf, p);
- ce = 0;
- for(i = 0; i < CLG_(current_call_stack).sp; i++) {
- ce = CLG_(get_call_entry)(i);
- /* if this frame is skipped, we don't have counters */
- if (!ce->jcc) continue;
-
- from = ce->jcc->from;
- p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
- from->cxt->fn[0]->name);
- VG_(write)(dump_fd, (void*)buf, p);
-
- p = VG_(sprintf)(buf, "calls-%d-%d: ",t, i);
- p+= VG_(sprintf)(buf+p, "%llu\n", ce->jcc->call_counter);
- VG_(write)(dump_fd, (void*)buf, p);
-
- /* FIXME: EventSets! */
- CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
- CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
- CLG_(add_diff_cost)( CLG_(sets).full, sum,
- ce->enter_cost, CLG_(current_state).cost );
- CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
-
- p = VG_(sprintf)(buf, "events-%d-%d: ",t, i);
- p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum );
- p += VG_(sprintf)(buf+p, "\n");
- VG_(write)(dump_fd, (void*)buf, p);
- }
- if (ce && ce->jcc) {
- to = ce->jcc->to;
- p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
- to->cxt->fn[0]->name );
- VG_(write)(dump_fd, (void*)buf, p);
- }
-}
-
-/* Dump info on current callgrind state */
-static Int dump_state(Int fd)
-{
- Char* buf = outbuf;
- thread_info** th;
- int t, p;
- Int orig_tid = CLG_(current_tid);
-
- if ( (fd = createRes(fd)) <0) return fd;
-
- VG_(sprintf)(buf, "instrumentation: %s\n",
- CLG_(instrument_state) ? "on":"off");
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- if (!CLG_(instrument_state)) return fd;
-
- VG_(sprintf)(buf, "executed-bbs: %llu\n", CLG_(stat).bb_executions);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- VG_(sprintf)(buf, "executed-calls: %llu\n", CLG_(stat).call_counter);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- VG_(sprintf)(buf, "distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- VG_(sprintf)(buf, "distinct-calls: %d\n", CLG_(stat).distinct_jccs);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- VG_(sprintf)(buf, "distinct-functions: %d\n", CLG_(stat).distinct_fns);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- VG_(sprintf)(buf, "distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- /* "events:" line. Given here because it will be dynamic in the future */
- p = VG_(sprintf)(buf, "events: ");
- CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap));
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
- VG_(write)(fd, "\n", 1);
-
- /* "part:" line (number of last part. Is 0 at start */
- VG_(sprintf)(buf, "\npart: %d\n", CLG_(get_dump_counter)());
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- /* threads */
- th = CLG_(get_threads)();
- p = VG_(sprintf)(buf, "threads:");
- for(t=1;t<VG_N_THREADS;t++) {
- if (!th[t]) continue;
- p += VG_(sprintf)(buf+p, " %d", t);
- }
- p += VG_(sprintf)(buf+p, "\n");
- VG_(write)(fd, (void*)buf, p);
-
- VG_(sprintf)(buf, "current-tid: %d\n", orig_tid);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- /* current event counters */
- dump_fd = fd;
- CLG_(forall_threads)(dump_state_of_thread);
-
- return fd;
-}
-
-void CLG_(check_command)()
-{
- /* check for dumps needed */
- static Char buf[512];
- static Char cmdBuffer[512];
- Char *cmdPos = 0, *cmdNextLine = 0;
- Int fd, bytesRead = 0, do_kill = 0;
- SysRes res;
- Int currentPID;
- static Int check_counter = 0;
-
- /* Check for PID change, i.e. whether we run as child after a fork.
- * If yes, we setup interactive control for the new process
- */
- currentPID = VG_(getpid)();
- if (thisPID != currentPID) {
- thisPID = currentPID;
- setup_control();
- }
-
- /* Toggle between 2 command files, with/without ".pid" postfix
- * (needed for compatibility with KCachegrind, which wants to trigger
- * a dump by writing into a command file without the ".pid" postfix)
- */
- check_counter++;
- if (check_counter % 2) {
- current_command_file = command_file;
- current_result_file = result_file;
- }
- else {
- current_command_file = command_file2;
- current_result_file = result_file2;
- }
-
- res = VG_(open)(current_command_file, VKI_O_RDONLY,0);
- if (!sr_isError(res)) {
- fd = (Int) sr_Res(res);
- bytesRead = VG_(read)(fd,cmdBuffer,500);
- cmdBuffer[500] = 0; /* no command overrun please */
- VG_(close)(fd);
- /* don't delete command file on read error (e.g. EAGAIN) */
- if (bytesRead>0) {
- cmdPos = cmdBuffer;
- }
- }
-
- /* force creation of result file if needed */
- fd = -2;
-
- while((bytesRead>0) && *cmdPos) {
-
- /* Calculate pointer for next line */
- cmdNextLine = cmdPos+1;
- while((bytesRead>0) && *cmdNextLine && (*cmdNextLine != '\n')) {
- cmdNextLine++;
- bytesRead--;
- }
- if ((bytesRead>0) && (*cmdNextLine == '\n')) {
- *cmdNextLine = 0;
- cmdNextLine++;
- bytesRead--;
- }
-
- /* Command with integer option */
- if ((*cmdPos >= '0') && (*cmdPos <='9')) {
- int value = *cmdPos-'0';
- cmdPos++;
- while((*cmdPos >= '0') && (*cmdPos <='9')) {
- value = 10*value + (*cmdPos-'0');
- cmdPos++;
- }
- while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
-
- switch(*cmdPos) {
-#if CLG_ENABLE_DEBUG
- /* verbosity */
- case 'V':
- case 'v':
- CLG_(clo).verbose = value;
- break;
-#endif
- default:
- break;
- }
-
- cmdPos = cmdNextLine;
- continue;
- }
-
- /* Command with boolean/switch option */
- if ((*cmdPos=='+') ||
- (*cmdPos=='-')) {
- int value = (cmdPos[0] == '+');
- cmdPos++;
- while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
-
- switch(*cmdPos) {
- case 'I':
- case 'i':
- CLG_(set_instrument_state)("Command", value);
- break;
-
- default:
- break;
- }
-
- cmdPos = cmdNextLine;
- continue;
- }
-
- /* regular command */
- switch(*cmdPos) {
- case 'D':
- case 'd':
- /* DUMP */
-
- /* skip command */
- while(*cmdPos && (*cmdPos != ' ')) cmdPos++;
- if (*cmdPos)
- VG_(sprintf)(buf, "Dump Command:%s", cmdPos);
- else
- VG_(sprintf)(buf, "Dump Command");
- CLG_(dump_profile)(buf, False);
- break;
-
- case 'Z':
- case 'z':
- CLG_(zero_all_cost)(False);
- break;
-
- case 'K':
- case 'k':
- /* Kill: Delay to be able to remove command file before. */
- do_kill = 1;
- break;
-
- case 'I':
- case 'i':
- fd = dump_info(fd);
- break;
-
- case 's':
- case 'S':
- fd = dump_state(fd);
- break;
-
- case 'O':
- case 'o':
- /* Options Info */
- if ( (fd = createRes(fd)) <0) break;
-
- VG_(sprintf)(buf, "\ndesc: Option: --skip-plt=%s\n",
- CLG_(clo).skip_plt ? "yes" : "no");
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
- VG_(sprintf)(buf, "desc: Option: --collect-jumps=%s\n",
- CLG_(clo).collect_jumps ? "yes" : "no");
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
- VG_(sprintf)(buf, "desc: Option: --separate-recs=%d\n",
- CLG_(clo).separate_recursions);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
- VG_(sprintf)(buf, "desc: Option: --separate-callers=%d\n",
- CLG_(clo).separate_callers);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- break;
-
- default:
- break;
- }
-
- cmdPos = cmdNextLine;
- }
-
- /* If command executed, delete command file */
- if (cmdPos) VG_(unlink)(current_command_file);
- if (fd>=0) VG_(close)(fd);
-
- if (do_kill) {
- VG_(message)(Vg_UserMsg,
- "Killed because of command from %s\n",
- current_command_file);
- CLG_(fini)(0);
- VG_(exit)(1);
- }
-}
Modified: trunk/callgrind/global.h
===================================================================
--- trunk/callgrind/global.h 2011-11-11 04:04:12 UTC (rev 12267)
+++ trunk/callgrind/global.h 2011-11-14 19:01:21 UTC (rev 12268)
@@ -51,9 +51,6 @@
/*------------------------------------------------------------*/
#define DEFAULT_OUTFORMAT "callgrind.out.%p"
-#define DEFAULT_COMMANDNAME "callgrind.cmd"
-#define DEFAULT_RESULTNAME "callgrind.res"
-#define DEFAULT_INFONAME "callgrind.info"
typedef struct _CommandLineOptions CommandLineOptions;
struct _CommandLineOptions {
@@ -723,11 +720,6 @@
Int CLG_(get_dump_counter)(void);
void CLG_(fini)(Int exitcode);
-/* from command.c */
-void CLG_(init_command)(void);
-void CLG_(check_command)(void);
-void CLG_(finish_command)(void);
-
/* from bb.c */
void CLG_(init_bb_hash)(void);
bb_hash* CLG_(get_bb_hash)(void);
Modified: trunk/callgrind/main.c
===================================================================
--- trunk/callgrind/main.c 2011-11-11 04:04:12 UTC (rev 12267)
+++ trunk/callgrind/main.c 2011-11-14 19:01:21 UTC (rev 12268)
@@ -1706,8 +1706,6 @@
CLG_(dump_profile)(0, False);
- CLG_(finish_command)();
-
if (VG_(clo_verbosity) == 0) return;
/* Hash table stats */
@@ -1859,7 +1857,6 @@
}
CLG_(init_dumps)();
- CLG_(init_command)();
(*CLG_(cachesim).post_clo_init)();
Modified: trunk/callgrind/threads.c
===================================================================
--- trunk/callgrind/threads.c 2011-11-11 04:04:12 UTC (rev 12267)
+++ trunk/callgrind/threads.c 2011-11-14 19:01:21 UTC (rev 12268)
@@ -189,8 +189,6 @@
}
}
- CLG_(check_command)();
-
/* now check for thread switch */
CLG_(switch_thread)(tid);
}
|
|
From: Julian S. <js...@ac...> - 2011-11-14 08:00:52
|
> No takers? :-( The PowerPC back end (host_ppc_isel.c) does support exact rounding on all FP instructions. Have a look at how it avoids setting the rounding mode for every FP instruction. So, an important question which I didn't see addressed by your previous message is, what is the effect on performance? J |
|
From: Julian S. <js...@ac...> - 2011-11-14 07:56:40
|
> Process the return address is obtained is good, but I do not know how to
> change that VEX would after I took over control of the handler to another
> location. Originally I wanted to make the transition to a value which is
> returned to my handler, but stumbled on the fact that the value returned
> by Dirty handler is I1 type, not I64.
>
> How can I generate code that assigns the I64 value? Or is there another way
> to get the same result?
>
> p.s. Sorry, English is not native language for me
> Sergey
>
> --- code ----
> ret_addr = newIRTemp(sbOut->tyenv,Ity_I64);
>
> di = unsafeIRDirty_1_N( ret_addr, 0, "ret_hook",
> VG_(fnptr_to_fnentry)( & ret_hook ),
> mkIRExprVec_2(
> getExprFromAddr(last_Mark->Ist.IMark.addr, hWordTy), sbIn->next) );
> addStmtToIRSB( sbOut, IRStmt_Dirty(di) );
>
> sbOut->next = IRExpr_RdTmp(ret_addr);
> --- end code ----
>
> --- generated VEX code ----
>
> t84 = DIRTY 1:I1 ::: ret_hook{0x38000370}(0x400AEFE:I64,t27)
> goto {Return} t84
I think you have misinterpreted the printout. AFAICS the code you have
here is correct. t84 holds the return value, and I assume this is created
with
> ret_addr = newIRTemp(sbOut->tyenv,Ity_I64);
so it is a 64 bit value. The "1:I1" in the printout is unrelated to
the return type. Dirty helper calls can be conditional, and this is
the condition (a constant 1, of type I1), which just means this call
is unconditional.
J
|