select-cmp-cttz-ctlz.ll 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. ; RUN: opt -instcombine -S < %s | FileCheck %s
  2. ; This test is to verify that the instruction combiner is able to fold
  3. ; a cttz/ctlz followed by a icmp + select into a single cttz/ctlz with
  4. ; the 'is_zero_undef' flag cleared.
  5. define i16 @test1(i16 %x) {
  6. ; CHECK-LABEL: @test1(
  7. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
  8. ; CHECK-NEXT: ret i16 [[VAR]]
  9. entry:
  10. %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
  11. %tobool = icmp ne i16 %x, 0
  12. %cond = select i1 %tobool, i16 %0, i16 16
  13. ret i16 %cond
  14. }
  15. define i32 @test2(i32 %x) {
  16. ; CHECK-LABEL: @test2(
  17. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
  18. ; CHECK-NEXT: ret i32 [[VAR]]
  19. entry:
  20. %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
  21. %tobool = icmp ne i32 %x, 0
  22. %cond = select i1 %tobool, i32 %0, i32 32
  23. ret i32 %cond
  24. }
  25. define i64 @test3(i64 %x) {
  26. ; CHECK-LABEL: @test3(
  27. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
  28. ; CHECK-NEXT: ret i64 [[VAR]]
  29. entry:
  30. %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
  31. %tobool = icmp ne i64 %x, 0
  32. %cond = select i1 %tobool, i64 %0, i64 64
  33. ret i64 %cond
  34. }
  35. define i16 @test4(i16 %x) {
  36. ; CHECK-LABEL: @test4(
  37. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
  38. ; CHECK-NEXT: ret i16 [[VAR]]
  39. entry:
  40. %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
  41. %tobool = icmp eq i16 %x, 0
  42. %cond = select i1 %tobool, i16 16, i16 %0
  43. ret i16 %cond
  44. }
  45. define i32 @test5(i32 %x) {
  46. ; CHECK-LABEL: @test5(
  47. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
  48. ; CHECK-NEXT: ret i32 [[VAR]]
  49. entry:
  50. %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
  51. %tobool = icmp eq i32 %x, 0
  52. %cond = select i1 %tobool, i32 32, i32 %0
  53. ret i32 %cond
  54. }
  55. define i64 @test6(i64 %x) {
  56. ; CHECK-LABEL: @test6(
  57. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
  58. ; CHECK-NEXT: ret i64 [[VAR]]
  59. entry:
  60. %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
  61. %tobool = icmp eq i64 %x, 0
  62. %cond = select i1 %tobool, i64 64, i64 %0
  63. ret i64 %cond
  64. }
  65. define i16 @test1b(i16 %x) {
  66. ; CHECK-LABEL: @test1b(
  67. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
  68. ; CHECK-NEXT: ret i16 [[VAR]]
  69. entry:
  70. %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
  71. %tobool = icmp ne i16 %x, 0
  72. %cond = select i1 %tobool, i16 %0, i16 16
  73. ret i16 %cond
  74. }
  75. define i32 @test2b(i32 %x) {
  76. ; CHECK-LABEL: @test2b(
  77. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  78. ; CHECK-NEXT: ret i32 [[VAR]]
  79. entry:
  80. %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
  81. %tobool = icmp ne i32 %x, 0
  82. %cond = select i1 %tobool, i32 %0, i32 32
  83. ret i32 %cond
  84. }
  85. define i64 @test3b(i64 %x) {
  86. ; CHECK-LABEL: @test3b(
  87. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
  88. ; CHECK-NEXT: ret i64 [[VAR]]
  89. entry:
  90. %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
  91. %tobool = icmp ne i64 %x, 0
  92. %cond = select i1 %tobool, i64 %0, i64 64
  93. ret i64 %cond
  94. }
  95. define i16 @test4b(i16 %x) {
  96. ; CHECK-LABEL: @test4b(
  97. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
  98. ; CHECK-NEXT: ret i16 [[VAR]]
  99. entry:
  100. %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
  101. %tobool = icmp eq i16 %x, 0
  102. %cond = select i1 %tobool, i16 16, i16 %0
  103. ret i16 %cond
  104. }
  105. define i32 @test5b(i32 %x) {
  106. ; CHECK-LABEL: @test5b(
  107. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  108. ; CHECK-NEXT: ret i32 [[VAR]]
  109. entry:
  110. %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
  111. %tobool = icmp eq i32 %x, 0
  112. %cond = select i1 %tobool, i32 32, i32 %0
  113. ret i32 %cond
  114. }
  115. define i64 @test6b(i64 %x) {
  116. ; CHECK-LABEL: @test6b(
  117. ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
  118. ; CHECK-NEXT: ret i64 [[VAR]]
  119. entry:
  120. %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
  121. %tobool = icmp eq i64 %x, 0
  122. %cond = select i1 %tobool, i64 64, i64 %0
  123. ret i64 %cond
  124. }
  125. define i32 @test1c(i16 %x) {
  126. ; CHECK-LABEL: @test1c(
  127. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
  128. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32
  129. ; CHECK-NEXT: ret i32 [[VAR2]]
  130. entry:
  131. %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
  132. %cast2 = zext i16 %0 to i32
  133. %tobool = icmp ne i16 %x, 0
  134. %cond = select i1 %tobool, i32 %cast2, i32 16
  135. ret i32 %cond
  136. }
  137. define i64 @test2c(i16 %x) {
  138. ; CHECK-LABEL: @test2c(
  139. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
  140. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64
  141. ; CHECK-NEXT: ret i64 [[VAR2]]
  142. entry:
  143. %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
  144. %conv = zext i16 %0 to i64
  145. %tobool = icmp ne i16 %x, 0
  146. %cond = select i1 %tobool, i64 %conv, i64 16
  147. ret i64 %cond
  148. }
  149. define i64 @test3c(i32 %x) {
  150. ; CHECK-LABEL: @test3c(
  151. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  152. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
  153. ; CHECK-NEXT: ret i64 [[VAR2]]
  154. entry:
  155. %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
  156. %conv = zext i32 %0 to i64
  157. %tobool = icmp ne i32 %x, 0
  158. %cond = select i1 %tobool, i64 %conv, i64 32
  159. ret i64 %cond
  160. }
  161. define i32 @test4c(i16 %x) {
  162. ; CHECK-LABEL: @test4c(
  163. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
  164. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32
  165. ; CHECK-NEXT: ret i32 [[VAR2]]
  166. entry:
  167. %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
  168. %cast = zext i16 %0 to i32
  169. %tobool = icmp ne i16 %x, 0
  170. %cond = select i1 %tobool, i32 %cast, i32 16
  171. ret i32 %cond
  172. }
  173. define i64 @test5c(i16 %x) {
  174. ; CHECK-LABEL: @test5c(
  175. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
  176. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64
  177. ; CHECK-NEXT: ret i64 [[VAR2]]
  178. entry:
  179. %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
  180. %cast = zext i16 %0 to i64
  181. %tobool = icmp ne i16 %x, 0
  182. %cond = select i1 %tobool, i64 %cast, i64 16
  183. ret i64 %cond
  184. }
  185. define i64 @test6c(i32 %x) {
  186. ; CHECK-LABEL: @test6c(
  187. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
  188. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
  189. ; CHECK-NEXT: ret i64 [[VAR2]]
  190. entry:
  191. %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
  192. %cast = zext i32 %0 to i64
  193. %tobool = icmp ne i32 %x, 0
  194. %cond = select i1 %tobool, i64 %cast, i64 32
  195. ret i64 %cond
  196. }
  197. define i16 @test1d(i64 %x) {
  198. ; CHECK-LABEL: @test1d(
  199. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
  200. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16
  201. ; CHECK-NEXT: ret i16 [[VAR2]]
  202. entry:
  203. %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
  204. %conv = trunc i64 %0 to i16
  205. %tobool = icmp ne i64 %x, 0
  206. %cond = select i1 %tobool, i16 %conv, i16 64
  207. ret i16 %cond
  208. }
  209. define i32 @test2d(i64 %x) {
  210. ; CHECK-LABEL: @test2d(
  211. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
  212. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32
  213. ; CHECK-NEXT: ret i32 [[VAR2]]
  214. entry:
  215. %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
  216. %cast = trunc i64 %0 to i32
  217. %tobool = icmp ne i64 %x, 0
  218. %cond = select i1 %tobool, i32 %cast, i32 64
  219. ret i32 %cond
  220. }
  221. define i16 @test3d(i32 %x) {
  222. ; CHECK-LABEL: @test3d(
  223. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  224. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
  225. ; CHECK-NEXT: ret i16 [[VAR2]]
  226. entry:
  227. %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
  228. %cast = trunc i32 %0 to i16
  229. %tobool = icmp ne i32 %x, 0
  230. %cond = select i1 %tobool, i16 %cast, i16 32
  231. ret i16 %cond
  232. }
  233. define i16 @test4d(i64 %x) {
  234. ; CHECK-LABEL: @test4d(
  235. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
  236. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16
  237. ; CHECK-NEXT: ret i16 [[VAR2]]
  238. entry:
  239. %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
  240. %cast = trunc i64 %0 to i16
  241. %tobool = icmp ne i64 %x, 0
  242. %cond = select i1 %tobool, i16 %cast, i16 64
  243. ret i16 %cond
  244. }
  245. define i32 @test5d(i64 %x) {
  246. ; CHECK-LABEL: @test5d(
  247. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
  248. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32
  249. ; CHECK-NEXT: ret i32 [[VAR2]]
  250. entry:
  251. %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
  252. %cast = trunc i64 %0 to i32
  253. %tobool = icmp ne i64 %x, 0
  254. %cond = select i1 %tobool, i32 %cast, i32 64
  255. ret i32 %cond
  256. }
  257. define i16 @test6d(i32 %x) {
  258. ; CHECK-LABEL: @test6d(
  259. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
  260. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
  261. ; CHECK-NEXT: ret i16 [[VAR2]]
  262. entry:
  263. %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
  264. %cast = trunc i32 %0 to i16
  265. %tobool = icmp ne i32 %x, 0
  266. %cond = select i1 %tobool, i16 %cast, i16 32
  267. ret i16 %cond
  268. }
  269. define i64 @select_bug1(i32 %x) {
  270. ; CHECK-LABEL: @select_bug1(
  271. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  272. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
  273. ; CHECK-NEXT: ret i64 [[VAR2]]
  274. entry:
  275. %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  276. %conv = zext i32 %0 to i64
  277. %tobool = icmp ne i32 %x, 0
  278. %cond = select i1 %tobool, i64 %conv, i64 32
  279. ret i64 %cond
  280. }
  281. define i16 @select_bug2(i32 %x) {
  282. ; CHECK-LABEL: @select_bug2(
  283. ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  284. ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
  285. ; CHECK-NEXT: ret i16 [[VAR2]]
  286. entry:
  287. %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
  288. %conv = trunc i32 %0 to i16
  289. %tobool = icmp ne i32 %x, 0
  290. %cond = select i1 %tobool, i16 %conv, i16 32
  291. ret i16 %cond
  292. }
  293. declare i16 @llvm.ctlz.i16(i16, i1)
  294. declare i32 @llvm.ctlz.i32(i32, i1)
  295. declare i64 @llvm.ctlz.i64(i64, i1)
  296. declare i16 @llvm.cttz.i16(i16, i1)
  297. declare i32 @llvm.cttz.i32(i32, i1)
  298. declare i64 @llvm.cttz.i64(i64, i1)