fixed_point_comparisons.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
  2. // RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,PADDED
  3. // Fixed point against other fixed point
  4. _Bool b_eq_true = 2.5hk == 2.5uhk; // CHECK-DAG: @b_eq_true = {{.*}}global i8 1, align 1
  5. _Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
  6. _Bool b_ne_true = 2.5hk != 2.4uhk; // CHECK-DAG: @b_ne_true = {{.*}}global i8 1, align 1
  7. _Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
  8. _Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true = {{.*}}global i8 1, align 1
  9. _Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
  10. _Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true = {{.*}}global i8 1, align 1
  11. _Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
  12. _Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
  13. _Bool b_gt_true = 2.75hk > 2.5uhk; // CHECK-DAG: @b_gt_true = {{.*}}global i8 1, align 1
  14. _Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
  15. _Bool b_ge_true = 2.75hk >= 2.5uhk; // CHECK-DAG: @b_ge_true = {{.*}}global i8 1, align 1
  16. _Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
  17. _Bool b_ge_false = 2.5hk >= 2.75uhk; // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
  18. // Fixed point against int
  19. _Bool b_ieq_true = 2.0hk == 2; // CHECK-DAG: @b_ieq_true = {{.*}}global i8 1, align 1
  20. _Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
  21. _Bool b_ine_true = 2.0hk != 3; // CHECK-DAG: @b_ine_true = {{.*}}global i8 1, align 1
  22. _Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
  23. _Bool b_ilt_true = 2.0hk < 3; // CHECK-DAG: @b_ilt_true = {{.*}}global i8 1, align 1
  24. _Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
  25. _Bool b_ile_true = 2.0hk <= 3; // CHECK-DAG: @b_ile_true = {{.*}}global i8 1, align 1
  26. _Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
  27. _Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
  28. _Bool b_igt_true = 2.0hk > 1; // CHECK-DAG: @b_igt_true = {{.*}}global i8 1, align 1
  29. _Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
  30. _Bool b_ige_true = 2.0hk >= 1; // CHECK-DAG: @b_ige_true = {{.*}}global i8 1, align 1
  31. _Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
  32. _Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
  33. // Different signage
  34. // Since we can have different precisions, non powers of 2 fractions may have
  35. // different actual values when being compared.
  36. _Bool b_sne_true = 2.6hk != 2.6uhk;
  37. // UNPADDED-DAG: @b_sne_true = {{.*}}global i8 1, align 1
  38. // PADDED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
  39. _Bool b_seq_true = 2.0hk == 2u; // CHECK-DAG: @b_seq_true = {{.*}}global i8 1, align 1
  40. _Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
  41. void TestComparisons() {
  42. short _Accum sa;
  43. _Accum a;
  44. unsigned short _Accum usa;
  45. unsigned _Accum ua;
  46. // Each of these should be a fixed point conversion followed by the actual
  47. // comparison operation.
  48. sa == a;
  49. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  50. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  51. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  52. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  53. // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
  54. sa != a;
  55. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  56. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  57. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  58. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  59. // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
  60. sa > a;
  61. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  62. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  63. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  64. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  65. // CHECK-NEXT: {{.*}} = icmp sgt i32 [[UPSCALE_A]], [[A2]]
  66. sa >= a;
  67. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  68. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  69. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  70. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  71. // CHECK-NEXT: {{.*}} = icmp sge i32 [[UPSCALE_A]], [[A2]]
  72. sa < a;
  73. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  74. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  75. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  76. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  77. // CHECK-NEXT: {{.*}} = icmp slt i32 [[UPSCALE_A]], [[A2]]
  78. sa <= a;
  79. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  80. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  81. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  82. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  83. // CHECK-NEXT: {{.*}} = icmp sle i32 [[UPSCALE_A]], [[A2]]
  84. usa > ua;
  85. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  86. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
  87. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
  88. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  89. // CHECK-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]]
  90. usa >= ua;
  91. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  92. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
  93. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
  94. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  95. // CHECK-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]]
  96. usa < ua;
  97. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  98. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
  99. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
  100. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  101. // CHECK-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]]
  102. usa <= ua;
  103. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  104. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
  105. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
  106. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  107. // CHECK-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]]
  108. }
  109. void TestIntComparisons() {
  110. short _Accum sa;
  111. unsigned short _Accum usa;
  112. int i;
  113. unsigned int ui;
  114. _Bool b;
  115. char c;
  116. short s;
  117. enum E {
  118. A = 2
  119. } e;
  120. // These comparisons shouldn't be that different from comparing against fixed
  121. // point types with other fixed point types.
  122. sa == i;
  123. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  124. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  125. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  126. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  127. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  128. // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
  129. sa != i;
  130. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  131. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  132. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  133. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  134. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  135. // CHECK-NEXT: {{.*}} = icmp ne i39 [[RESIZE_A]], [[UPSCALE_I]]
  136. sa > i;
  137. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  138. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  139. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  140. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  141. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  142. // CHECK-NEXT: {{.*}} = icmp sgt i39 [[RESIZE_A]], [[UPSCALE_I]]
  143. sa >= i;
  144. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  145. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  146. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  147. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  148. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  149. // CHECK-NEXT: {{.*}} = icmp sge i39 [[RESIZE_A]], [[UPSCALE_I]]
  150. sa < i;
  151. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  152. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  153. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  154. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  155. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  156. // CHECK-NEXT: {{.*}} = icmp slt i39 [[RESIZE_A]], [[UPSCALE_I]]
  157. sa <= i;
  158. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  159. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  160. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  161. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  162. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  163. // CHECK-NEXT: {{.*}} = icmp sle i39 [[RESIZE_A]], [[UPSCALE_I]]
  164. usa > ui;
  165. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  166. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
  167. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
  168. // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
  169. // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
  170. // UNPADDED-NEXT: {{.*}} = icmp ugt i40 [[RESIZE_A]], [[UPSCALE_I]]
  171. // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
  172. // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
  173. // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  174. // PADDED-NEXT: {{.*}} = icmp ugt i39 [[RESIZE_A]], [[UPSCALE_I]]
  175. usa >= ui;
  176. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  177. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
  178. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
  179. // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
  180. // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
  181. // UNPADDED-NEXT: {{.*}} = icmp uge i40 [[RESIZE_A]], [[UPSCALE_I]]
  182. // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
  183. // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
  184. // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  185. // PADDED-NEXT: {{.*}} = icmp uge i39 [[RESIZE_A]], [[UPSCALE_I]]
  186. usa < ui;
  187. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  188. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
  189. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
  190. // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
  191. // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
  192. // UNPADDED-NEXT: {{.*}} = icmp ult i40 [[RESIZE_A]], [[UPSCALE_I]]
  193. // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
  194. // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
  195. // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  196. // PADDED-NEXT: {{.*}} = icmp ult i39 [[RESIZE_A]], [[UPSCALE_I]]
  197. usa <= ui;
  198. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  199. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
  200. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
  201. // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
  202. // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
  203. // UNPADDED-NEXT: {{.*}} = icmp ule i40 [[RESIZE_A]], [[UPSCALE_I]]
  204. // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
  205. // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
  206. // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  207. // PADDED-NEXT: {{.*}} = icmp ule i39 [[RESIZE_A]], [[UPSCALE_I]]
  208. // Allow for comparisons with other int like types. These are no different
  209. // from comparing to an int other than varying sizes. The integer types are
  210. // still converted to ints or unsigned ints from UsualUnaryConversions().
  211. sa == b;
  212. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  213. // CHECK-NEXT: [[B:%[0-9]+]] = load i8, i8* %b, align 1
  214. // CHECK-NEXT: %tobool = trunc i8 [[B]] to i1
  215. // CHECK-NEXT: [[CONV_B:%[a-z0-9]+]] = zext i1 %tobool to i32
  216. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  217. // CHECK-NEXT: [[RESIZE_B:%[a-z0-9]+]] = sext i32 [[CONV_B]] to i39
  218. // CHECK-NEXT: [[UPSCALE_B:%[a-z0-9]+]] = shl i39 [[RESIZE_B]], 7
  219. // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_B]]
  220. sa == c;
  221. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  222. // CHECK-NEXT: [[C:%[0-9]+]] = load i8, i8* %c, align 1
  223. // CHECK-NEXT: [[CONV_C:%[a-z0-9]+]] = sext i8 [[C]] to i32
  224. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  225. // CHECK-NEXT: [[RESIZE_C:%[a-z0-9]+]] = sext i32 [[CONV_C]] to i39
  226. // CHECK-NEXT: [[UPSCALE_C:%[a-z0-9]+]] = shl i39 [[RESIZE_C]], 7
  227. // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_C]]
  228. sa == s;
  229. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  230. // CHECK-NEXT: [[S:%[0-9]+]] = load i16, i16* %s, align 2
  231. // CHECK-NEXT: [[CONV_S:%[a-z0-9]+]] = sext i16 [[S]] to i32
  232. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
  233. // CHECK-NEXT: [[RESIZE_S:%[a-z0-9]+]] = sext i32 [[CONV_S]] to i39
  234. // CHECK-NEXT: [[UPSCALE_S:%[a-z0-9]+]] = shl i39 [[RESIZE_S]], 7
  235. // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_S]]
  236. // An enum value is IntegralCast to an unsigned int.
  237. usa == e;
  238. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  239. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %e, align 4
  240. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
  241. // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
  242. // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
  243. // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
  244. // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
  245. // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
  246. // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  247. // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
  248. }
  249. void TestComparisonSignage() {
  250. short _Accum sa;
  251. unsigned short _Accum usa;
  252. int i;
  253. unsigned int ui;
  254. // Signed vs unsigned fixed point comparison
  255. sa == usa;
  256. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  257. // CHECK-NEXT: [[A2:%[0-9]+]] = load i16, i16* %usa, align 2
  258. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i17
  259. // UNPADDED-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i17 [[RESIZE_A]], 1
  260. // UNPADDED-NEXT: [[RESIZE_A2:%[a-z0-9]+]] = zext i16 [[A2]] to i17
  261. // UNPADDED-NEXT: {{.*}} = icmp eq i17 [[UPSCALE_A]], [[RESIZE_A2]]
  262. // PADDED-NEXT: {{.*}} = icmp eq i16 [[A]], [[A2]]
  263. // Signed int vs unsigned fixed point
  264. sa == ui;
  265. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  266. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
  267. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i40
  268. // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
  269. // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
  270. // CHECK-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
  271. // Signed fixed point vs unsigned int
  272. usa == i;
  273. // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
  274. // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
  275. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
  276. // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i40
  277. // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
  278. // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
  279. // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
  280. // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
  281. // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
  282. // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
  283. }
  284. void TestSaturationComparisons() {
  285. short _Accum sa;
  286. _Accum a;
  287. _Sat short _Accum sat_sa;
  288. _Sat _Accum sat_a;
  289. _Sat unsigned short _Accum sat_usa;
  290. // These are effectively the same as conversions with their non-saturating
  291. // counterparts since when comparing, we convert both operands to a common
  292. // type that should be able to hold both values.
  293. sat_sa == sat_a;
  294. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
  295. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %sat_a, align 4
  296. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  297. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  298. // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
  299. sat_sa == a;
  300. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
  301. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  302. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  303. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  304. // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
  305. sat_sa == sat_usa;
  306. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
  307. // CHECK-NEXT: [[A2:%[0-9]+]] = load i16, i16* %sat_usa, align 2
  308. // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i17
  309. // UNPADDED-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i17 [[RESIZE_A]], 1
  310. // UNPADDED-NEXT: [[RESIZE_A2:%[a-z0-9]+]] = zext i16 [[A2]] to i17
  311. // UNPADDED-NEXT: {{.*}} = icmp eq i17 [[UPSCALE_A]], [[RESIZE_A2]]
  312. // PADDED-NEXT: {{.*}} = icmp eq i16 [[A]], [[A2]]
  313. }
  314. void StoreBooleanResult() {
  315. short _Accum sa;
  316. _Accum a;
  317. int res;
  318. // Check that the result can properly be stored as an int.
  319. res = sa == a;
  320. // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
  321. // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
  322. // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
  323. // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
  324. // CHECK-NEXT: [[RES:%[0-9]+]] = icmp eq i32 [[UPSCALE_A]], [[A2]]
  325. // CHECK-NEXT: %conv = zext i1 [[RES]] to i32
  326. // CHECK-NEXT: store i32 %conv, i32* %res, align 4
  327. }