[llvm] r271743 - [esan|wset] Optionally assume intra-cache-line accesses

Derek Bruening via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 3 15:29:53 PDT 2016


Author: bruening
Date: Fri Jun  3 17:29:52 2016
New Revision: 271743

URL: http://llvm.org/viewvc/llvm-project?rev=271743&view=rev
Log:
[esan|wset] Optionally assume intra-cache-line accesses

Summary:
Adds an option -esan-assume-intra-cache-line which causes esan to assume
that a single memory access touches just one cache line, even if it is not
aligned, for better performance at a potential accuracy cost.  Experiments
show that the performance difference can be 2x or more, and accuracy loss
is typically negligible, so we turn this on by default.  This currently
applies just to the working set tool.

Reviewers: aizatsky

Subscribers: vitalybuka, zhaoqin, kcc, eugenis, llvm-commits

Differential Revision: http://reviews.llvm.org/D20978

Added:
    llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_strict.ll
      - copied, changed from r271742, llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll
Modified:
    llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
    llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll

Modified: llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp?rev=271743&r1=271742&r2=271743&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp Fri Jun  3 17:29:52 2016
@@ -57,6 +57,14 @@ static cl::opt<bool> ClInstrumentMemIntr
     "esan-instrument-memintrinsics", cl::init(true),
     cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden);
 
+// Experiments show that the performance difference can be 2x or more,
+// and accuracy loss is typically negligible, so we turn this on by default.
+static cl::opt<bool> ClAssumeIntraCacheLine(
+    "esan-assume-intra-cache-line", cl::init(true),
+    cl::desc("Assume each memory access touches just one cache line, for "
+             "better performance but with a potential loss of accuracy."),
+    cl::Hidden);
+
 STATISTIC(NumInstrumentedLoads, "Number of instrumented loads");
 STATISTIC(NumInstrumentedStores, "Number of instrumented stores");
 STATISTIC(NumFastpaths, "Number of instrumented fastpaths");
@@ -65,6 +73,8 @@ STATISTIC(NumAccessesWithIrregularSize,
 STATISTIC(NumIgnoredStructs, "Number of ignored structs");
 STATISTIC(NumIgnoredGEPs, "Number of ignored GEP instructions");
 STATISTIC(NumInstrumentedGEPs, "Number of instrumented GEP instructions");
+STATISTIC(NumAssumedIntraCacheLine,
+          "Number of accesses assumed to be intra-cache-line");
 
 static const uint64_t EsanCtorAndDtorPriority = 0;
 static const char *const EsanModuleCtorName = "esan.module_ctor";
@@ -715,8 +725,12 @@ bool EfficiencySanitizer::instrumentFast
   // (and our shadow memory setup assumes 64-byte cache lines).
   assert(TypeSize <= 64);
   if (!(TypeSize == 8 ||
-        (Alignment % (TypeSize / 8)) == 0))
-    return false;
+        (Alignment % (TypeSize / 8)) == 0)) {
+    if (ClAssumeIntraCacheLine)
+      ++NumAssumedIntraCacheLine;
+    else
+      return false;
+  }
 
   // We inline instrumentation to set the corresponding shadow bits for
   // each cache line touched by the application.  Here we handle a single

Modified: llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll?rev=271743&r1=271742&r2=271743&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll (original)
+++ llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll Fri Jun  3 17:29:52 2016
@@ -91,15 +91,27 @@ entry:
 }
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; Not guaranteed to be intra-cache-line
+; Not guaranteed to be intra-cache-line, but our defaults are to
+; assume they are:
 
 define i16 @unaligned2(i16* %a) {
 entry:
   %tmp1 = load i16, i16* %a, align 1
   ret i16 %tmp1
-; CHECK:          %0 = bitcast i16* %a to i8*
-; CHECK-NEXT:   call void @__esan_unaligned_load2(i8* %0)
-; CHECK-NEXT:   %tmp1 = load i16, i16* %a, align 1
+; CHECK:        %0 = ptrtoint i16* %a to i64
+; CHECK-NEXT:   %1 = and i64 %0, 17592186044415
+; CHECK-NEXT:   %2 = add i64 %1, 1337006139375616
+; CHECK-NEXT:   %3 = lshr i64 %2, 6
+; CHECK-NEXT:   %4 = inttoptr i64 %3 to i8*
+; CHECK-NEXT:   %5 = load i8, i8* %4
+; CHECK-NEXT:   %6 = and i8 %5, -127
+; CHECK-NEXT:   %7 = icmp ne i8 %6, -127
+; CHECK-NEXT:   br i1 %7, label %8, label %11
+; CHECK:        %9 = or i8 %5, -127
+; CHECK-NEXT:   %10 = inttoptr i64 %3 to i8*
+; CHECK-NEXT:   store i8 %9, i8* %10
+; CHECK-NEXT:   br label %11
+; CHECK:        %tmp1 = load i16, i16* %a, align 1
 ; CHECK-NEXT:   ret i16 %tmp1
 }
 
@@ -107,9 +119,20 @@ define i32 @unaligned4(i32* %a) {
 entry:
   %tmp1 = load i32, i32* %a, align 2
   ret i32 %tmp1
-; CHECK:          %0 = bitcast i32* %a to i8*
-; CHECK-NEXT:   call void @__esan_unaligned_load4(i8* %0)
-; CHECK-NEXT:   %tmp1 = load i32, i32* %a, align 2
+; CHECK:        %0 = ptrtoint i32* %a to i64
+; CHECK-NEXT:   %1 = and i64 %0, 17592186044415
+; CHECK-NEXT:   %2 = add i64 %1, 1337006139375616
+; CHECK-NEXT:   %3 = lshr i64 %2, 6
+; CHECK-NEXT:   %4 = inttoptr i64 %3 to i8*
+; CHECK-NEXT:   %5 = load i8, i8* %4
+; CHECK-NEXT:   %6 = and i8 %5, -127
+; CHECK-NEXT:   %7 = icmp ne i8 %6, -127
+; CHECK-NEXT:   br i1 %7, label %8, label %11
+; CHECK:        %9 = or i8 %5, -127
+; CHECK-NEXT:   %10 = inttoptr i64 %3 to i8*
+; CHECK-NEXT:   store i8 %9, i8* %10
+; CHECK-NEXT:   br label %11
+; CHECK:        %tmp1 = load i32, i32* %a, align 2
 ; CHECK-NEXT:   ret i32 %tmp1
 }
 
@@ -117,9 +140,20 @@ define i64 @unaligned8(i64* %a) {
 entry:
   %tmp1 = load i64, i64* %a, align 4
   ret i64 %tmp1
-; CHECK:          %0 = bitcast i64* %a to i8*
-; CHECK-NEXT:   call void @__esan_unaligned_load8(i8* %0)
-; CHECK-NEXT:   %tmp1 = load i64, i64* %a, align 4
+; CHECK:        %0 = ptrtoint i64* %a to i64
+; CHECK-NEXT:   %1 = and i64 %0, 17592186044415
+; CHECK-NEXT:   %2 = add i64 %1, 1337006139375616
+; CHECK-NEXT:   %3 = lshr i64 %2, 6
+; CHECK-NEXT:   %4 = inttoptr i64 %3 to i8*
+; CHECK-NEXT:   %5 = load i8, i8* %4
+; CHECK-NEXT:   %6 = and i8 %5, -127
+; CHECK-NEXT:   %7 = icmp ne i8 %6, -127
+; CHECK-NEXT:   br i1 %7, label %8, label %11
+; CHECK:        %9 = or i8 %5, -127
+; CHECK-NEXT:   %10 = inttoptr i64 %3 to i8*
+; CHECK-NEXT:   store i8 %9, i8* %10
+; CHECK-NEXT:   br label %11
+; CHECK:        %tmp1 = load i64, i64* %a, align 4
 ; CHECK-NEXT:   ret i64 %tmp1
 }
 

Copied: llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_strict.ll (from r271742, llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_strict.ll?p2=llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_strict.ll&p1=llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll&r1=271742&r2=271743&rev=271743&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_basic.ll (original)
+++ llvm/trunk/test/Instrumentation/EfficiencySanitizer/working_set_strict.ll Fri Jun  3 17:29:52 2016
@@ -1,6 +1,7 @@
-; Test basic EfficiencySanitizer working set instrumentation.
+; Test EfficiencySanitizer working set instrumentation without aggressive
+; optimization flags.
 ;
-; RUN: opt < %s -esan -esan-working-set -S | FileCheck %s
+; RUN: opt < %s -esan -esan-working-set -esan-assume-intra-cache-line=0 -S | FileCheck %s
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Intra-cache-line
@@ -97,7 +98,7 @@ define i16 @unaligned2(i16* %a) {
 entry:
   %tmp1 = load i16, i16* %a, align 1
   ret i16 %tmp1
-; CHECK:          %0 = bitcast i16* %a to i8*
+; CHECK:        %0 = bitcast i16* %a to i8*
 ; CHECK-NEXT:   call void @__esan_unaligned_load2(i8* %0)
 ; CHECK-NEXT:   %tmp1 = load i16, i16* %a, align 1
 ; CHECK-NEXT:   ret i16 %tmp1
@@ -107,7 +108,7 @@ define i32 @unaligned4(i32* %a) {
 entry:
   %tmp1 = load i32, i32* %a, align 2
   ret i32 %tmp1
-; CHECK:          %0 = bitcast i32* %a to i8*
+; CHECK:        %0 = bitcast i32* %a to i8*
 ; CHECK-NEXT:   call void @__esan_unaligned_load4(i8* %0)
 ; CHECK-NEXT:   %tmp1 = load i32, i32* %a, align 2
 ; CHECK-NEXT:   ret i32 %tmp1
@@ -117,50 +118,8 @@ define i64 @unaligned8(i64* %a) {
 entry:
   %tmp1 = load i64, i64* %a, align 4
   ret i64 %tmp1
-; CHECK:          %0 = bitcast i64* %a to i8*
+; CHECK:        %0 = bitcast i64* %a to i8*
 ; CHECK-NEXT:   call void @__esan_unaligned_load8(i8* %0)
 ; CHECK-NEXT:   %tmp1 = load i64, i64* %a, align 4
 ; CHECK-NEXT:   ret i64 %tmp1
 }
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; Ensure that esan converts intrinsics to calls:
-
-declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1)
-declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1)
-declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1)
-
-define void @memCpyTest(i8* nocapture %x, i8* nocapture %y) {
-entry:
-    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x, i8* %y, i64 16, i32 4, i1 false)
-    ret void
-; CHECK: define void @memCpyTest
-; CHECK: call i8* @memcpy
-; CHECK: ret void
-}
-
-define void @memMoveTest(i8* nocapture %x, i8* nocapture %y) {
-entry:
-    tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %x, i8* %y, i64 16, i32 4, i1 false)
-    ret void
-; CHECK: define void @memMoveTest
-; CHECK: call i8* @memmove
-; CHECK: ret void
-}
-
-define void @memSetTest(i8* nocapture %x) {
-entry:
-    tail call void @llvm.memset.p0i8.i64(i8* %x, i8 77, i64 16, i32 4, i1 false)
-    ret void
-; CHECK: define void @memSetTest
-; CHECK: call i8* @memset
-; CHECK: ret void
-}
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; Top-level:
-
-; CHECK: define internal void @esan.module_ctor()
-; CHECK: call void @__esan_init(i32 2, i8* null)
-; CHECK: define internal void @esan.module_dtor()
-; CHECK: call void @__esan_exit(i8* null)




More information about the llvm-commits mailing list