bit_scan_test.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * test bit_scan operations from bit_scan.h
  3. * (both for correctness and speed)
  4. *
  5. * Copyright (C) 2007 iptelorg GmbH
  6. *
  7. * Permission to use, copy, modify, and distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. /*
  20. * Example gcc command line:
  21. * gcc -O9 -Wall -DCC_GCC_LIKE_ASM -D__CPU_x86 bit_scan_test.c ../bit_scan.c
  22. * -o bit_scan_test
  23. *
  24. * History:
  25. * --------
  26. * 2007-06-23 created by andrei
  27. */
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #define BIT_SCAN_DEBRUIJN
  31. #define BIT_SCAN_BRANCH
  32. #define BIT_SCAN_SLOW
  33. #include "../bit_scan.h"
  34. #ifdef NO_PROFILE
  35. #define profile_init(x,y) do{}while(0)
  36. #define profile_start(x) do{}while(0)
  37. #define profile_end(x) do{}while(0)
  38. #define PROFILE_PRINT(x) do{}while(0)
  39. #else
  40. #include "profile.h"
  41. #endif
  42. #define CHECK(txt, v1, val, f, pd) \
  43. do{ \
  44. unsigned long long ret; \
  45. profile_start(pd); \
  46. ret=(unsigned long long)f(val); \
  47. profile_end(pd); \
  48. if ((unsigned long long)v1!=ret){ \
  49. fprintf(stderr, "ERROR:" #f ": %s, expected %llx (%llx), got"\
  50. " %llx\n", \
  51. (txt), (unsigned long long)v1, \
  52. (unsigned long long)val, ret); \
  53. exit(-1); \
  54. } \
  55. }while(0)
  56. #ifndef PROFILE_PRINT
  57. #define PROFILE_PRINT(pd) \
  58. do{ \
  59. printf("profile: %s (%ld/%ld) total %llu max %llu average %llu\n", \
  60. (pd)->name, (pd)->entries, (pd)->exits, \
  61. (pd)->total_cycles, (pd)->max_cycles, \
  62. (pd)->entries? \
  63. (pd)->total_cycles/(unsigned long long)(pd)->entries:0ULL ); \
  64. }while(0)
  65. #endif
  66. int main(int argc, char** argv)
  67. {
  68. int r;
  69. unsigned int v;
  70. unsigned long long ll;
  71. int i;
  72. #ifndef NO_PROFILE
  73. struct profile_data pdf1, pdf2, pdf4, pdf5, pdf6, pdf8;
  74. struct profile_data pdl1, pdl2, pdl4, pdl5, pdl6, pdl8;
  75. #ifdef HAS_BIT_SCAN_ASM
  76. struct profile_data pdf3, pdf7, pdl3, pdl7;
  77. #endif
  78. struct profile_data pdf_32, pdf_64, pdl_32, pdl_64;
  79. struct profile_data pdf_long, pdl_long;
  80. #endif /* NO_PROFILE */
  81. profile_init(&pdf1, "first_debruijn32");
  82. profile_init(&pdf2, "first_slow32");
  83. #ifdef HAS_BIT_SCAN_ASM
  84. profile_init(&pdf3, "first_asm32");
  85. #endif
  86. profile_init(&pdf4, "first_br32");
  87. profile_init(&pdf5, "first_debruijn64");
  88. profile_init(&pdf6, "first_slow64");
  89. #ifdef HAS_BIT_SCAN_ASM
  90. profile_init(&pdf7, "first_asm64");
  91. #endif
  92. profile_init(&pdf8, "first_br64");
  93. profile_init(&pdl1, "last_debruijn32");
  94. profile_init(&pdl2, "last_slow32");
  95. #ifdef HAS_BIT_SCAN_ASM
  96. profile_init(&pdl3, "last_asm32");
  97. #endif
  98. profile_init(&pdl4, "last_br32");
  99. profile_init(&pdl5, "last_debruijn64");
  100. profile_init(&pdl6, "last_slow64");
  101. #ifdef HAS_BIT_SCAN_ASM
  102. profile_init(&pdl7, "last_asm64");
  103. #endif
  104. profile_init(&pdl8, "last_br64");
  105. profile_init(&pdf_32, "scan_forward32");
  106. profile_init(&pdf_64, "scan_forward64");
  107. profile_init(&pdl_32, "scan_reverse32");
  108. profile_init(&pdl_64, "scan_reverse64");
  109. profile_init(&pdf_long, "scan_forward_l");
  110. profile_init(&pdl_long, "scan_reverse_l");
  111. for (i=0; i<100; i++){
  112. for (r=0; r<32; r++){
  113. v=(1U<<r);
  114. CHECK("first debruijn 32bit", r, v, bit_scan_forward_debruijn32, &pdf1);
  115. CHECK("first slow 32bit", r, v, bit_scan_forward_slow32, &pdf2);
  116. #ifdef HAS_BIT_SCAN_ASM
  117. CHECK("first asm 32bit", r, v, bit_scan_forward_asm32, &pdf3);
  118. #endif
  119. CHECK("first br 32bit", r, v, bit_scan_forward_br32, &pdf4);
  120. CHECK("scan_forward32", r, v, bit_scan_forward32, &pdf_32);
  121. if (sizeof(long)<=4){
  122. CHECK("scan_forward_l", r, v, bit_scan_forward, &pdf_long);
  123. }
  124. v+=(v-1);
  125. CHECK("last debruijn 32bit", r, v, bit_scan_reverse_debruijn32, &pdl1);
  126. CHECK("last slow 32bit", r, v, bit_scan_reverse_slow32, &pdl2);
  127. #ifdef HAS_BIT_SCAN_ASM
  128. CHECK("last asm 32bit", r, v, bit_scan_reverse_asm32, &pdl3);
  129. #endif
  130. CHECK("last br 32bit", r, v, bit_scan_reverse_br32, &pdl4);
  131. CHECK("scan_reverse32", r, v, bit_scan_reverse32, &pdl_32);
  132. if (sizeof(long)<=4){
  133. CHECK("scan_reverse_l", r, v, bit_scan_reverse, &pdl_long);
  134. }
  135. }
  136. for (r=0; r<64; r++){
  137. ll=(1ULL<<r);
  138. CHECK("first debruijn 64bit", r, ll, bit_scan_forward_debruijn64, &pdf5);
  139. CHECK("first slow 64bit", r, ll, bit_scan_forward_slow64, &pdf6);
  140. #ifdef HAS_BIT_SCAN_ASM
  141. CHECK("first asm 64bit", r, ll, bit_scan_forward_asm64, &pdf7);
  142. #endif
  143. CHECK("first br 64bit", r, ll, bit_scan_forward_br64, &pdf8);
  144. CHECK("scan_forward64", r, ll, bit_scan_forward64, &pdf_64);
  145. if (sizeof(long)>4){
  146. CHECK("scan_forward_l", r, ll, bit_scan_forward, &pdf_long);
  147. }
  148. ll+=ll-1;
  149. CHECK("last debruijn 64bit", r, ll, bit_scan_reverse_debruijn64, &pdl5);
  150. CHECK("last slow 64bit", r, ll, bit_scan_reverse_slow64, &pdl6);
  151. #ifdef HAS_BIT_SCAN_ASM
  152. CHECK("last asm 64bit", r, ll, bit_scan_reverse_asm64, &pdl7);
  153. #endif
  154. CHECK("last br 64bit", r, ll, bit_scan_reverse_br64, &pdl8);
  155. CHECK("scan_reverse64", r, ll, bit_scan_reverse64, &pdl_64);
  156. if (sizeof(long)>4){
  157. CHECK("scan_reverse_l", r, ll, bit_scan_reverse, &pdl_long);
  158. }
  159. }
  160. }
  161. PROFILE_PRINT(&pdf1);
  162. PROFILE_PRINT(&pdf2);
  163. #ifdef HAS_BIT_SCAN_ASM
  164. PROFILE_PRINT(&pdf3);
  165. #endif
  166. PROFILE_PRINT(&pdf4);
  167. PROFILE_PRINT(&pdl1);
  168. PROFILE_PRINT(&pdl2);
  169. #ifdef HAS_BIT_SCAN_ASM
  170. PROFILE_PRINT(&pdl3);
  171. #endif
  172. PROFILE_PRINT(&pdl4);
  173. PROFILE_PRINT(&pdf5);
  174. PROFILE_PRINT(&pdf6);
  175. #ifdef HAS_BIT_SCAN_ASM
  176. PROFILE_PRINT(&pdf7);
  177. #endif
  178. PROFILE_PRINT(&pdf8);
  179. PROFILE_PRINT(&pdl5);
  180. PROFILE_PRINT(&pdl6);
  181. #ifdef HAS_BIT_SCAN_ASM
  182. PROFILE_PRINT(&pdl7);
  183. #endif
  184. PROFILE_PRINT(&pdl8);
  185. PROFILE_PRINT(&pdf_32);
  186. PROFILE_PRINT(&pdf_64);
  187. PROFILE_PRINT(&pdf_long);
  188. PROFILE_PRINT(&pdl_32);
  189. PROFILE_PRINT(&pdl_64);
  190. PROFILE_PRINT(&pdl_long);
  191. return 0;
  192. }