donotoptimize_assembly_test.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include <benchmark/benchmark.h>
  2. #ifdef __clang__
  3. #pragma clang diagnostic ignored "-Wreturn-type"
  4. #endif
  5. extern "C" {
  6. extern int ExternInt;
  7. extern int ExternInt2;
  8. extern int ExternInt3;
  9. inline int Add42(int x) { return x + 42; }
  10. struct NotTriviallyCopyable {
  11. NotTriviallyCopyable();
  12. explicit NotTriviallyCopyable(int x) : value(x) {}
  13. NotTriviallyCopyable(NotTriviallyCopyable const&);
  14. int value;
  15. };
  16. struct Large {
  17. int value;
  18. int data[2];
  19. };
  20. }
  21. // CHECK-LABEL: test_with_rvalue:
  22. extern "C" void test_with_rvalue() {
  23. benchmark::DoNotOptimize(Add42(0));
  24. // CHECK: movl $42, %eax
  25. // CHECK: ret
  26. }
  27. // CHECK-LABEL: test_with_large_rvalue:
  28. extern "C" void test_with_large_rvalue() {
  29. benchmark::DoNotOptimize(Large{ExternInt, {ExternInt, ExternInt}});
  30. // CHECK: ExternInt(%rip)
  31. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]
  32. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
  33. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
  34. // CHECK: ret
  35. }
  36. // CHECK-LABEL: test_with_non_trivial_rvalue:
  37. extern "C" void test_with_non_trivial_rvalue() {
  38. benchmark::DoNotOptimize(NotTriviallyCopyable(ExternInt));
  39. // CHECK: mov{{l|q}} ExternInt(%rip)
  40. // CHECK: ret
  41. }
  42. // CHECK-LABEL: test_with_lvalue:
  43. extern "C" void test_with_lvalue() {
  44. int x = 101;
  45. benchmark::DoNotOptimize(x);
  46. // CHECK-GNU: movl $101, %eax
  47. // CHECK-CLANG: movl $101, -{{[0-9]+}}(%[[REG:[a-z]+]])
  48. // CHECK: ret
  49. }
  50. // CHECK-LABEL: test_with_large_lvalue:
  51. extern "C" void test_with_large_lvalue() {
  52. Large L{ExternInt, {ExternInt, ExternInt}};
  53. benchmark::DoNotOptimize(L);
  54. // CHECK: ExternInt(%rip)
  55. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
  56. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
  57. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
  58. // CHECK: ret
  59. }
  60. // CHECK-LABEL: test_with_non_trivial_lvalue:
  61. extern "C" void test_with_non_trivial_lvalue() {
  62. NotTriviallyCopyable NTC(ExternInt);
  63. benchmark::DoNotOptimize(NTC);
  64. // CHECK: ExternInt(%rip)
  65. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
  66. // CHECK: ret
  67. }
  68. // CHECK-LABEL: test_with_const_lvalue:
  69. extern "C" void test_with_const_lvalue() {
  70. const int x = 123;
  71. benchmark::DoNotOptimize(x);
  72. // CHECK: movl $123, %eax
  73. // CHECK: ret
  74. }
  75. // CHECK-LABEL: test_with_large_const_lvalue:
  76. extern "C" void test_with_large_const_lvalue() {
  77. const Large L{ExternInt, {ExternInt, ExternInt}};
  78. benchmark::DoNotOptimize(L);
  79. // CHECK: ExternInt(%rip)
  80. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
  81. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
  82. // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
  83. // CHECK: ret
  84. }
  85. // CHECK-LABEL: test_with_non_trivial_const_lvalue:
  86. extern "C" void test_with_non_trivial_const_lvalue() {
  87. const NotTriviallyCopyable Obj(ExternInt);
  88. benchmark::DoNotOptimize(Obj);
  89. // CHECK: mov{{q|l}} ExternInt(%rip)
  90. // CHECK: ret
  91. }
  92. // CHECK-LABEL: test_div_by_two:
  93. extern "C" int test_div_by_two(int input) {
  94. int divisor = 2;
  95. benchmark::DoNotOptimize(divisor);
  96. return input / divisor;
  97. // CHECK: movl $2, [[DEST:.*]]
  98. // CHECK: idivl [[DEST]]
  99. // CHECK: ret
  100. }
  101. // CHECK-LABEL: test_inc_integer:
  102. extern "C" int test_inc_integer() {
  103. int x = 0;
  104. for (int i=0; i < 5; ++i)
  105. benchmark::DoNotOptimize(++x);
  106. // CHECK: movl $1, [[DEST:.*]]
  107. // CHECK: {{(addl \$1,|incl)}} [[DEST]]
  108. // CHECK: {{(addl \$1,|incl)}} [[DEST]]
  109. // CHECK: {{(addl \$1,|incl)}} [[DEST]]
  110. // CHECK: {{(addl \$1,|incl)}} [[DEST]]
  111. // CHECK-CLANG: movl [[DEST]], %eax
  112. // CHECK: ret
  113. return x;
  114. }
  115. // CHECK-LABEL: test_pointer_rvalue
  116. extern "C" void test_pointer_rvalue() {
  117. // CHECK: movl $42, [[DEST:.*]]
  118. // CHECK: leaq [[DEST]], %rax
  119. // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]])
  120. // CHECK: ret
  121. int x = 42;
  122. benchmark::DoNotOptimize(&x);
  123. }
  124. // CHECK-LABEL: test_pointer_const_lvalue:
  125. extern "C" void test_pointer_const_lvalue() {
  126. // CHECK: movl $42, [[DEST:.*]]
  127. // CHECK: leaq [[DEST]], %rax
  128. // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]])
  129. // CHECK: ret
  130. int x = 42;
  131. int * const xp = &x;
  132. benchmark::DoNotOptimize(xp);
  133. }
  134. // CHECK-LABEL: test_pointer_lvalue:
  135. extern "C" void test_pointer_lvalue() {
  136. // CHECK: movl $42, [[DEST:.*]]
  137. // CHECK: leaq [[DEST]], %rax
  138. // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z+]+]])
  139. // CHECK: ret
  140. int x = 42;
  141. int *xp = &x;
  142. benchmark::DoNotOptimize(xp);
  143. }