ikudrin created this revision. ikudrin added reviewers: bogner, davidxl, vsk. ikudrin added a subscriber: cfe-commits.
A valid function might not have any statement which affects the hash value, so the hash for that function was zero. The hash value for an unused function is also zero, so the loader could not distinguish the definitions and might load the incorrect one. This patch addresses the issue by assigning a special reserved value as a hash for such a functions. http://reviews.llvm.org/D20287 Files: lib/CodeGen/CodeGenPGO.cpp lib/CodeGen/CoverageMappingGen.cpp test/CoverageMapping/block-storage-starts-region.m test/CoverageMapping/decl.c test/CoverageMapping/implicit-def-in-macro.m test/CoverageMapping/lambda.cpp test/CoverageMapping/loops.cpp test/CoverageMapping/macroception.c test/CoverageMapping/moremacros.c test/CoverageMapping/simple-function-hash.cpp test/CoverageMapping/system_macro.c test/CoverageMapping/trymacro.cpp test/Profile/Inputs/c-captured.proftext test/Profile/Inputs/c-general.proftext test/Profile/Inputs/c-outdated-data.proftext test/Profile/Inputs/c-unprofiled.proftext test/Profile/Inputs/cxx-class.proftext test/Profile/Inputs/cxx-lambda.proftext test/Profile/Inputs/cxx-rangefor.proftext test/Profile/Inputs/cxx-templates.proftext test/Profile/Inputs/func-entry.proftext test/Profile/Inputs/max-function-count.proftext test/Profile/Inputs/objc-general.proftext test/Profile/Inputs/profile-summary.proftext
Index: test/Profile/Inputs/profile-summary.proftext =================================================================== --- test/Profile/Inputs/profile-summary.proftext +++ test/Profile/Inputs/profile-summary.proftext @@ -9,7 +9,7 @@ main # Func Hash: -0 +17 # Num Counters: 1 # Counter Values: Index: test/Profile/Inputs/objc-general.proftext =================================================================== --- test/Profile/Inputs/objc-general.proftext +++ test/Profile/Inputs/objc-general.proftext @@ -11,7 +11,7 @@ 2 main -0 +17 1 1 Index: test/Profile/Inputs/max-function-count.proftext =================================================================== --- test/Profile/Inputs/max-function-count.proftext +++ test/Profile/Inputs/max-function-count.proftext @@ -9,7 +9,7 @@ main # Func Hash: -0 +17 # Num Counters: 1 # Counter Values: Index: test/Profile/Inputs/func-entry.proftext =================================================================== --- test/Profile/Inputs/func-entry.proftext +++ test/Profile/Inputs/func-entry.proftext @@ -1,5 +1,5 @@ foo -0 +17 1 1000 Index: test/Profile/Inputs/cxx-templates.proftext =================================================================== --- test/Profile/Inputs/cxx-templates.proftext +++ test/Profile/Inputs/cxx-templates.proftext @@ -1,5 +1,5 @@ main -0 +17 1 1 Index: test/Profile/Inputs/cxx-rangefor.proftext =================================================================== --- test/Profile/Inputs/cxx-rangefor.proftext +++ test/Profile/Inputs/cxx-rangefor.proftext @@ -8,6 +8,6 @@ 1 main -0 +17 1 1 Index: test/Profile/Inputs/cxx-lambda.proftext =================================================================== --- test/Profile/Inputs/cxx-lambda.proftext +++ test/Profile/Inputs/cxx-lambda.proftext @@ -6,7 +6,7 @@ 9 main -0 +17 1 1 Index: test/Profile/Inputs/cxx-class.proftext =================================================================== --- test/Profile/Inputs/cxx-class.proftext +++ test/Profile/Inputs/cxx-class.proftext @@ -5,7 +5,7 @@ 100 main -0 +17 1 1 Index: test/Profile/Inputs/c-unprofiled.proftext =================================================================== --- test/Profile/Inputs/c-unprofiled.proftext +++ test/Profile/Inputs/c-unprofiled.proftext @@ -5,6 +5,6 @@ 0 main -0 +17 1 1 Index: test/Profile/Inputs/c-outdated-data.proftext =================================================================== --- test/Profile/Inputs/c-outdated-data.proftext +++ test/Profile/Inputs/c-outdated-data.proftext @@ -6,7 +6,7 @@ 0 main -0 +17 1 1 Index: test/Profile/Inputs/c-general.proftext =================================================================== --- test/Profile/Inputs/c-general.proftext +++ test/Profile/Inputs/c-general.proftext @@ -145,7 +145,7 @@ 8 main -0 +17 1 1 Index: test/Profile/Inputs/c-captured.proftext =================================================================== --- test/Profile/Inputs/c-captured.proftext +++ test/Profile/Inputs/c-captured.proftext @@ -12,7 +12,7 @@ 1 main -0 +17 1 1 Index: test/CoverageMapping/trymacro.cpp =================================================================== --- test/CoverageMapping/trymacro.cpp +++ test/CoverageMapping/trymacro.cpp @@ -1,19 +1,19 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fexceptions -fcxx-exceptions -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name trymacro.cpp %s | FileCheck %s -// CHECK: Z3fn1v: +// CHECK: Z3fn1v void fn1() try { return; } // CHECK: [[@LINE]]:12 -> [[@LINE+1]]:14 = #1 catch(...) {} // CHECK: [[@LINE]]:12 -> [[@LINE]]:14 = #2 #define RETURN_BLOCK { return; } -// CHECK: Z3fn2v: +// CHECK: Z3fn2v void fn2() try RETURN_BLOCK // CHECK: [[@LINE]]:12 -> [[@LINE+1]]:14 = #1 catch(...) {} // CHECK: [[@LINE]]:12 -> [[@LINE]]:14 = #2 #define TRY try #define CATCH(x) catch (x) -// CHECK: Z3fn3v: +// CHECK: Z3fn3v void fn3() TRY { return; } // CHECK: [[@LINE]]:15 -> [[@LINE+1]]:14 = #1 CATCH(...) {} // CHECK: [[@LINE]]:12 -> [[@LINE]]:14 = #2 Index: test/CoverageMapping/system_macro.c =================================================================== --- test/CoverageMapping/system_macro.c +++ test/CoverageMapping/system_macro.c @@ -11,7 +11,7 @@ #define IS_SYSHEADER #include __FILE__ -// CHECK-LABEL: doSomething: +// CHECK-LABEL: doSomething void doSomething(int x) { // CHECK: File 0, [[@LINE]]:25 -> {{[0-9:]+}} = #0 Func(x); // CHECK: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:7 return; Index: test/CoverageMapping/simple-function-hash.cpp =================================================================== --- /dev/null +++ test/CoverageMapping/simple-function-hash.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -main-file-name simple-function-hash.cpp %s -o %t.o -emit-llvm -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping | FileCheck %s + +// Hash value for unused_func() is 0 because it is an inline function which is not used in the translation unit. +// CHECK-DAG: _Z11unused_funcv(0): +inline int unused_func() { return 1; } + +// Hash value for used_func() is 17 even though it does not contain any statement which affects hash. +// CHECK-DAG: _Z9used_funcv(17): +inline int used_func() { return 1; } + +// Hash value for main() is 10 because it contains the "if" statement. +// CHECK-DAG: main(10): +int main() { + if (used_func()) + return used_func(); + return 0; +} Index: test/CoverageMapping/moremacros.c =================================================================== --- test/CoverageMapping/moremacros.c +++ test/CoverageMapping/moremacros.c @@ -3,7 +3,7 @@ #define LBRAC { #define RBRAC } -// CHECK: main: +// CHECK: main // CHECK-NEXT: File 0, [[@LINE+1]]:40 -> {{[0-9]+}}:2 = #0 int main(int argc, const char *argv[]) { // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:12 = #0 Index: test/CoverageMapping/macroception.c =================================================================== --- test/CoverageMapping/macroception.c +++ test/CoverageMapping/macroception.c @@ -5,7 +5,7 @@ #define M22 } #define M11 M22 -// CHECK-LABEL: main: +// CHECK-LABEL: main // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:12 -> [[@LINE+2]]:14 = #0 // CHECK-NEXT: File 0, [[@LINE+1]]:14 -> [[@LINE+3]]:2 = #0 int main() M1 @@ -15,7 +15,7 @@ // CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 // CHECK-NEXT: File 2, 3:12 -> 3:13 = #0 -// CHECK-LABEL: func2: +// CHECK-LABEL: func2 // CHECK-NEXT: File 0, [[@LINE+2]]:14 -> [[@LINE+4]]:4 = #0 // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0 void func2() { @@ -25,7 +25,7 @@ // CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = #0 // CHECK-NEXT: File 2, 5:13 -> 5:14 = #0 -// CHECK-LABEL: func3: +// CHECK-LABEL: func3 // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:14 -> [[@LINE+3]]:16 = #0 // CHECK-NEXT: File 0, [[@LINE+2]]:16 -> [[@LINE+4]]:4 = #0 // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0 @@ -39,7 +39,7 @@ // CHECK-NEXT: File 3, 3:12 -> 3:13 = #0 // CHECK-NEXT: File 4, 5:13 -> 5:14 = #0 -// CHECK-LABEL: func4: +// CHECK-LABEL: func4 // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:14 -> [[@LINE+3]]:16 = #0 // CHECK-NEXT: File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:20 = #0 // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:17 -> [[@LINE+1]]:20 = #0 Index: test/CoverageMapping/loops.cpp =================================================================== --- test/CoverageMapping/loops.cpp +++ test/CoverageMapping/loops.cpp @@ -16,7 +16,7 @@ if (sum) {} } - // CHECK: main: + // CHECK: main int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+24]]:2 = #0 // CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = (#0 + #1) for(int i = 0; i < 10; ++i) // CHECK-NEXT: File 0, [[@LINE]]:26 -> [[@LINE]]:29 = #1 Index: test/CoverageMapping/lambda.cpp =================================================================== --- test/CoverageMapping/lambda.cpp +++ test/CoverageMapping/lambda.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -x c++ -std=c++11 -triple %itanium_abi_triple -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s -main-file-name lambda.cpp | FileCheck %s -// CHECK-LABEL: _Z3fooi: +// CHECK-LABEL: _Z3fooi void foo(int i) { // CHECK: File 0, [[@LINE]]:17 -> {{[0-9]+}}:2 = #0 auto f = [](int x) { return x + 1; Index: test/CoverageMapping/implicit-def-in-macro.m =================================================================== --- test/CoverageMapping/implicit-def-in-macro.m +++ test/CoverageMapping/implicit-def-in-macro.m @@ -5,7 +5,7 @@ #define Bar Foo @implementation Blah -// CHECK-LABEL: +[Blah load]: +// CHECK-LABEL: +[Blah load] + load { // CHECK: File 0, [[@LINE]]:8 -> [[END:[0-9:]+]] = #0 return 0; // CHECK: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:6 = 0 Index: test/CoverageMapping/decl.c =================================================================== --- test/CoverageMapping/decl.c +++ test/CoverageMapping/decl.c @@ -4,12 +4,12 @@ // FileCheck -input-file %t %s // RUN: FileCheck -check-prefix BAR -input-file %t %s -// FOO: foo: -// FOO-NOT: foo: +// FOO: foo +// FOO-NOT: foo inline int foo() { return 0; } extern inline int foo(); -// BAR: bar: -// BAR-NOT: bar: +// BAR: bar +// BAR-NOT: bar int bar() { return 0; } extern int bar(); Index: test/CoverageMapping/block-storage-starts-region.m =================================================================== --- test/CoverageMapping/block-storage-starts-region.m +++ test/CoverageMapping/block-storage-starts-region.m @@ -3,7 +3,7 @@ @interface Foo @end -// CHECK-LABEL: doSomething: +// CHECK-LABEL: doSomething void doSomething() { // CHECK: File 0, [[@LINE]]:20 -> {{[0-9:]+}} = #0 return; __block Foo *f; // CHECK: File 0, [[@LINE]]:3 -> {{[0-9:]+}} = 0 Index: lib/CodeGen/CoverageMappingGen.cpp =================================================================== --- lib/CodeGen/CoverageMappingGen.cpp +++ lib/CodeGen/CoverageMappingGen.cpp @@ -906,9 +906,9 @@ } static void dump(llvm::raw_ostream &OS, StringRef FunctionName, - ArrayRef<CounterExpression> Expressions, + uint64_t FuncHash, ArrayRef<CounterExpression> Expressions, ArrayRef<CounterMappingRegion> Regions) { - OS << FunctionName << ":\n"; + OS << FunctionName << "(" << FuncHash << "):\n"; CounterMappingContext Ctx(Expressions); for (const auto &R : Regions) { OS.indent(2); @@ -974,7 +974,7 @@ Expressions, Regions); if (Reader.read()) return; - dump(llvm::outs(), NameValue, Expressions, Regions); + dump(llvm::outs(), NameValue, FuncHash, Expressions, Regions); } } Index: lib/CodeGen/CodeGenPGO.cpp =================================================================== --- lib/CodeGen/CodeGenPGO.cpp +++ lib/CodeGen/CodeGenPGO.cpp @@ -93,6 +93,7 @@ BinaryOperatorLAnd, BinaryOperatorLOr, BinaryConditionalOperator, + SimpleFunctionHash, // Reserved for functions without aforesaid statements. // Keep this last. It's for the static assert that follows. LastHashType @@ -598,7 +599,10 @@ // No need to byte swap here, since none of the math was endian-dependent. // This number will be byte-swapped as required on endianness transitions, // so we will see the same value on the other side. - return Working; + // If we didn't meet any known statements, return a special hash value, + // so that any used function will have a non-zero hash and won't be + // messed up with non-used functions when reading coverage data. + return Working ? Working : static_cast<uint64_t>(SimpleFunctionHash); // Check for remaining work in Working. if (Working)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits