diff --git a/tools/selective_cfi/color_map.cpp b/tools/selective_cfi/color_map.cpp
index c012122188120c0bf25a16dbf760c615884033ae..d0a878de96cc4784e4af475bb7db44e8c68dfe9a 100644
--- a/tools/selective_cfi/color_map.cpp
+++ b/tools/selective_cfi/color_map.cpp
@@ -72,11 +72,14 @@ bool ColoredInstructionNonces_t::create()
 	}
 
 	// output stats
-	cout<<"#ATTRIBUTE slots_used="<<slots_used.size()<<endl;
+	cout<<"# ATTRIBUTE slots_used="<<slots_used.size()<<endl;
+	int total_slots = 0;
 	for(int slot_no=0; slot_no<slots_used.size(); slot_no++)
 	{
-		cout<<"#ATTRIBUTE used_slot"<<slot_no<<"="<<slots_used[slot_no].SlotsUsed()<<endl;
+		cout<<"# ATTRIBUTE used_slot"<<slot_no<<"="<<slots_used[slot_no].SlotsUsed()<<endl;
+		total_slots += slots_used[slot_no].SlotsUsed();
 	}
+	cout<<"# ATTRIBUTE total_slots="<<total_slots<<endl;
 
 	return true;
 }
diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp
index 07a5982321d9006a43545fd5362fd277c4906cf2..214c1db571b193836a0efbd9ae0d1bcc150f939e 100644
--- a/tools/selective_cfi/scfi_instr.cpp
+++ b/tools/selective_cfi/scfi_instr.cpp
@@ -25,6 +25,7 @@
 #include "color_map.hpp"
 #include <stdlib.h>
 #include <memory>
+#include <math.h>
 
 
 
@@ -471,7 +472,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 	if(d.Argument1.ArgType!=NO_ARGUMENT)
 	{
 		unsigned int sp_adjust=d.Instruction.Immediat-firp->GetArchitectureBitWidth()/8;
-		cout<<"Found relateively rare ret_with_pop insn: "<<d.CompleteInstr<<endl;
+		cout<<"Found relatively rare ret_with_pop insn: "<<d.CompleteInstr<<endl;
 		char buf[30];
 		sprintf(buf, "pop %s [%s+%d]", worddec.c_str(), rspreg.c_str(), sp_adjust);
 		Instruction_t* newafter=insertAssemblyBefore(firp,insn,buf);
@@ -562,9 +563,42 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v)
 #endif
 }
 
+static void display_histogram(std::ostream& out, std::string attr_label, std::map<int,int> & p_map)
+{
+	if (p_map.size()) 
+	{
+		out<<"# ATTRIBUTE " << attr_label << "=";
+		out<<"{ibt_size:count,";
+		bool first_time=true;
+		for (map<int,int>::iterator it = p_map.begin(); 
+			it != p_map.end(); ++it)
+		{
+			if (!first_time)
+				out << ",";
+			out << it->first << ":" << it->second;
+			first_time = false;
+		}
+		out<<"}"<<endl;
+	}
+}
+
 bool SCFI_Instrument::instrument_jumps() 
 {
 	int cfi_checks=0;
+	int cfi_branch_jmp_checks=0;
+	int cfi_branch_jmp_complete=0;
+	int cfi_branch_call_checks=0;
+	int cfi_branch_call_complete=0;
+	int cfi_branch_ret_checks=0;
+	int cfi_branch_ret_complete=0;
+	int ibt_complete=0;
+	double cfi_branch_jmp_complete_ratio = NAN;
+	double cfi_branch_ret_complete_ratio = NAN;
+
+	std::map<int, int> jmps;
+	std::map<int, int> rets;
+
+	// build histogram of target sizes
 
 	// for each instruction
 	for(InstructionSet_t::iterator it=firp->GetInstructions().begin();
@@ -590,6 +624,12 @@ bool SCFI_Instrument::instrument_jumps()
 				if((d.Argument1.ArgType&MEMORY_TYPE)==MEMORY_TYPE)
 				{
 					cfi_checks++;
+					cfi_branch_jmp_checks++;
+					if (insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
+					{
+						cfi_branch_jmp_complete++;
+						jmps[insn->GetIBTargets()->size()]++;
+					}
 					AddJumpCFI(insn);
 				}
 				break;
@@ -599,9 +639,19 @@ bool SCFI_Instrument::instrument_jumps()
 				{
 					// not yet implemented.	
 					assert(0); // fix calls should conver these to jumps
+					cfi_branch_call_checks++;
+					if (insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
+						cfi_branch_call_complete++;
+					cfi_checks++;
 				}
 				break;
 			case  RetType: 
+				cfi_branch_ret_checks++;
+				if (insn->GetIBTargets() && insn->GetIBTargets()->IsComplete())
+				{
+					cfi_branch_ret_complete++;
+					rets[insn->GetIBTargets()->size()]++;
+				}
 				cfi_checks++;
 				AddReturnCFI(insn);
 				break;
@@ -611,9 +661,39 @@ bool SCFI_Instrument::instrument_jumps()
 		}
 	}
 	
+	cout<<"# ATTRIBUTE cfi_jmp_checks="<<std::dec<<cfi_branch_jmp_checks<<endl;
+	cout<<"# ATTRIBUTE cfi_jmp_complete="<<std::dec<<cfi_branch_jmp_complete<<endl;
+
+	display_histogram(cout, "cfi_jmp_complete_histogram", jmps);
 
+/*
+	cout<<"# ATTRIBUTE cfi_branch_call_checks="<<std::dec<<cfi_branch_call_checks<<endl;
+	cout<<"# ATTRIBUTE cfi_branch_call_complete="<<std::dec<<cfi_branch_call_complete<<endl;
+*/
+	cout<<"# ATTRIBUTE cfi_ret_checks="<<std::dec<<cfi_branch_ret_checks<<endl;
+	cout<<"# ATTRIBUTE cfi_ret_complete="<<std::dec<<cfi_branch_ret_complete<<endl;
+	display_histogram(cout, "cfi_ret_complete_histogram", rets);
 
 	cout<<"# ATTRIBUTE cfi_checks="<<std::dec<<cfi_checks<<endl;
+	ibt_complete = cfi_branch_jmp_complete + cfi_branch_call_complete + cfi_branch_ret_complete;
+	cout<<"# ATTRIBUTE ibt_complete="<<std::dec<<ibt_complete<<endl;
+
+	if (cfi_branch_jmp_checks > 0) 
+		cfi_branch_jmp_complete_ratio = (double)cfi_branch_jmp_complete / cfi_branch_jmp_checks;
+
+	if (cfi_branch_ret_checks > 0) 
+		cfi_branch_ret_complete_ratio = (double)cfi_branch_ret_complete / cfi_branch_ret_checks;
+
+	double cfi_branch_complete_ratio = NAN;
+	if (ibt_complete > 0)
+		cfi_branch_complete_ratio = (double) cfi_checks / ibt_complete;
+	
+
+	cout << "# ATTRIBUTE cfi_jmp_complete_ratio=" << cfi_branch_jmp_complete_ratio << endl;
+
+	cout << "# ATTRIBUTE cfi_ret_complete_ratio=" << cfi_branch_ret_complete_ratio << endl;
+	cout << "# ATTRIBUTE cfi_complete_ratio=" << cfi_branch_ret_complete_ratio << endl;
+
 	return true;
 }