stride-access-dependence.ll 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
  2. target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
  3. ; Following cases are no dependence.
  4. ; void nodep_Read_Write(int *A) {
  5. ; int *B = A + 1;
  6. ; for (unsigned i = 0; i < 1024; i+=3)
  7. ; B[i] = A[i] + 1;
  8. ; }
  9. ; CHECK: function 'nodep_Read_Write':
  10. ; CHECK-NEXT: for.body:
  11. ; CHECK-NEXT: Memory dependences are safe
  12. ; CHECK-NEXT: Interesting Dependences:
  13. ; CHECK-NEXT: Run-time memory checks:
  14. define void @nodep_Read_Write(i32* nocapture %A) {
  15. entry:
  16. %add.ptr = getelementptr inbounds i32, i32* %A, i64 1
  17. br label %for.body
  18. for.cond.cleanup: ; preds = %for.body
  19. ret void
  20. for.body: ; preds = %entry, %for.body
  21. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  22. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  23. %0 = load i32, i32* %arrayidx, align 4
  24. %add = add nsw i32 %0, 1
  25. %arrayidx2 = getelementptr inbounds i32, i32* %add.ptr, i64 %indvars.iv
  26. store i32 %add, i32* %arrayidx2, align 4
  27. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 3
  28. %cmp = icmp ult i64 %indvars.iv.next, 1024
  29. br i1 %cmp, label %for.body, label %for.cond.cleanup
  30. }
  31. ; int nodep_Write_Read(int *A) {
  32. ; int sum = 0;
  33. ; for (unsigned i = 0; i < 1024; i+=4) {
  34. ; A[i] = i;
  35. ; sum += A[i+3];
  36. ; }
  37. ;
  38. ; return sum;
  39. ; }
  40. ; CHECK: function 'nodep_Write_Read':
  41. ; CHECK-NEXT: for.body:
  42. ; CHECK-NEXT: Memory dependences are safe
  43. ; CHECK-NEXT: Interesting Dependences:
  44. ; CHECK-NEXT: Run-time memory checks:
  45. define i32 @nodep_Write_Read(i32* nocapture %A) {
  46. entry:
  47. br label %for.body
  48. for.cond.cleanup: ; preds = %for.body
  49. ret i32 %add3
  50. for.body: ; preds = %entry, %for.body
  51. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  52. %sum.013 = phi i32 [ 0, %entry ], [ %add3, %for.body ]
  53. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  54. %0 = trunc i64 %indvars.iv to i32
  55. store i32 %0, i32* %arrayidx, align 4
  56. %1 = or i64 %indvars.iv, 3
  57. %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %1
  58. %2 = load i32, i32* %arrayidx2, align 4
  59. %add3 = add nsw i32 %2, %sum.013
  60. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4
  61. %cmp = icmp ult i64 %indvars.iv.next, 1024
  62. br i1 %cmp, label %for.body, label %for.cond.cleanup
  63. }
  64. ; void nodep_Write_Write(int *A) {
  65. ; for (unsigned i = 0; i < 1024; i+=2) {
  66. ; A[i] = i;
  67. ; A[i+1] = i+1;
  68. ; }
  69. ; }
  70. ; CHECK: function 'nodep_Write_Write':
  71. ; CHECK-NEXT: for.body:
  72. ; CHECK-NEXT: Memory dependences are safe
  73. ; CHECK-NEXT: Interesting Dependences:
  74. ; CHECK-NEXT: Run-time memory checks:
  75. define void @nodep_Write_Write(i32* nocapture %A) {
  76. entry:
  77. br label %for.body
  78. for.cond.cleanup: ; preds = %for.body
  79. ret void
  80. for.body: ; preds = %entry, %for.body
  81. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  82. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  83. %0 = trunc i64 %indvars.iv to i32
  84. store i32 %0, i32* %arrayidx, align 4
  85. %1 = or i64 %indvars.iv, 1
  86. %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %1
  87. %2 = trunc i64 %1 to i32
  88. store i32 %2, i32* %arrayidx3, align 4
  89. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  90. %cmp = icmp ult i64 %indvars.iv.next, 1024
  91. br i1 %cmp, label %for.body, label %for.cond.cleanup
  92. }
  93. ; Following cases are unsafe depdences and are not vectorizable.
  94. ; void unsafe_Read_Write(int *A) {
  95. ; for (unsigned i = 0; i < 1024; i+=3)
  96. ; A[i+3] = A[i] + 1;
  97. ; }
  98. ; CHECK: function 'unsafe_Read_Write':
  99. ; CHECK-NEXT: for.body:
  100. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  101. ; CHECK-NEXT: Interesting Dependences:
  102. ; CHECK-NEXT: Backward:
  103. ; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 ->
  104. ; CHECK-NEXT: store i32 %add, i32* %arrayidx3, align 4
  105. define void @unsafe_Read_Write(i32* nocapture %A) {
  106. entry:
  107. br label %for.body
  108. for.cond.cleanup: ; preds = %for.body
  109. ret void
  110. for.body: ; preds = %entry, %for.body
  111. %i.010 = phi i32 [ 0, %entry ], [ %add1, %for.body ]
  112. %idxprom = zext i32 %i.010 to i64
  113. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
  114. %0 = load i32, i32* %arrayidx, align 4
  115. %add = add nsw i32 %0, 1
  116. %add1 = add i32 %i.010, 3
  117. %idxprom2 = zext i32 %add1 to i64
  118. %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %idxprom2
  119. store i32 %add, i32* %arrayidx3, align 4
  120. %cmp = icmp ult i32 %add1, 1024
  121. br i1 %cmp, label %for.body, label %for.cond.cleanup
  122. }
  123. ; int unsafe_Write_Read(int *A) {
  124. ; int sum = 0;
  125. ; for (unsigned i = 0; i < 1024; i+=4) {
  126. ; A[i] = i;
  127. ; sum += A[i+4];
  128. ; }
  129. ;
  130. ; return sum;
  131. ; }
  132. ; CHECK: function 'unsafe_Write_Read':
  133. ; CHECK-NEXT: for.body:
  134. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  135. ; CHECK-NEXT: Interesting Dependences:
  136. ; CHECK-NEXT: Backward:
  137. ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
  138. ; CHECK-NEXT: %1 = load i32, i32* %arrayidx2, align 4
  139. define i32 @unsafe_Write_Read(i32* nocapture %A) {
  140. entry:
  141. br label %for.body
  142. for.cond.cleanup: ; preds = %for.body
  143. ret i32 %add3
  144. for.body: ; preds = %entry, %for.body
  145. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  146. %sum.013 = phi i32 [ 0, %entry ], [ %add3, %for.body ]
  147. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  148. %0 = trunc i64 %indvars.iv to i32
  149. store i32 %0, i32* %arrayidx, align 4
  150. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4
  151. %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv.next
  152. %1 = load i32, i32* %arrayidx2, align 4
  153. %add3 = add nsw i32 %1, %sum.013
  154. %cmp = icmp ult i64 %indvars.iv.next, 1024
  155. br i1 %cmp, label %for.body, label %for.cond.cleanup
  156. }
  157. ; void unsafe_Write_Write(int *A) {
  158. ; for (unsigned i = 0; i < 1024; i+=2) {
  159. ; A[i] = i;
  160. ; A[i+2] = i+1;
  161. ; }
  162. ; }
  163. ; CHECK: function 'unsafe_Write_Write':
  164. ; CHECK-NEXT: for.body:
  165. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  166. ; CHECK-NEXT: Interesting Dependences:
  167. ; CHECK-NEXT: Backward:
  168. ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
  169. ; CHECK-NEXT: store i32 %2, i32* %arrayidx3, align 4
  170. define void @unsafe_Write_Write(i32* nocapture %A) {
  171. entry:
  172. br label %for.body
  173. for.cond.cleanup: ; preds = %for.body
  174. ret void
  175. for.body: ; preds = %entry, %for.body
  176. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  177. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  178. %0 = trunc i64 %indvars.iv to i32
  179. store i32 %0, i32* %arrayidx, align 4
  180. %1 = or i64 %indvars.iv, 1
  181. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  182. %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv.next
  183. %2 = trunc i64 %1 to i32
  184. store i32 %2, i32* %arrayidx3, align 4
  185. %cmp = icmp ult i64 %indvars.iv.next, 1024
  186. br i1 %cmp, label %for.body, label %for.cond.cleanup
  187. }
  188. ; Following cases check that strided accesses can be vectorized.
  189. ; void vectorizable_Read_Write(int *A) {
  190. ; int *B = A + 4;
  191. ; for (unsigned i = 0; i < 1024; i+=2)
  192. ; B[i] = A[i] + 1;
  193. ; }
  194. ; CHECK: function 'vectorizable_Read_Write':
  195. ; CHECK-NEXT: for.body:
  196. ; CHECK-NEXT: Memory dependences are safe
  197. ; CHECK-NEXT: Interesting Dependences:
  198. ; CHECK-NEXT: BackwardVectorizable:
  199. ; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 ->
  200. ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
  201. define void @vectorizable_Read_Write(i32* nocapture %A) {
  202. entry:
  203. %add.ptr = getelementptr inbounds i32, i32* %A, i64 4
  204. br label %for.body
  205. for.cond.cleanup: ; preds = %for.body
  206. ret void
  207. for.body: ; preds = %entry, %for.body
  208. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  209. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  210. %0 = load i32, i32* %arrayidx, align 4
  211. %add = add nsw i32 %0, 1
  212. %arrayidx2 = getelementptr inbounds i32, i32* %add.ptr, i64 %indvars.iv
  213. store i32 %add, i32* %arrayidx2, align 4
  214. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  215. %cmp = icmp ult i64 %indvars.iv.next, 1024
  216. br i1 %cmp, label %for.body, label %for.cond.cleanup
  217. }
  218. ; int vectorizable_Write_Read(int *A) {
  219. ; int *B = A + 4;
  220. ; int sum = 0;
  221. ; for (unsigned i = 0; i < 1024; i+=2) {
  222. ; A[i] = i;
  223. ; sum += B[i];
  224. ; }
  225. ;
  226. ; return sum;
  227. ; }
  228. ; CHECK: function 'vectorizable_Write_Read':
  229. ; CHECK-NEXT: for.body:
  230. ; CHECK-NEXT: Memory dependences are safe
  231. ; CHECK-NEXT: Interesting Dependences:
  232. ; CHECK-NEXT: BackwardVectorizable:
  233. ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
  234. ; CHECK-NEXT: %1 = load i32, i32* %arrayidx2, align 4
  235. define i32 @vectorizable_Write_Read(i32* nocapture %A) {
  236. entry:
  237. %add.ptr = getelementptr inbounds i32, i32* %A, i64 4
  238. br label %for.body
  239. for.cond.cleanup: ; preds = %for.body
  240. ret i32 %add
  241. for.body: ; preds = %entry, %for.body
  242. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  243. %sum.013 = phi i32 [ 0, %entry ], [ %add, %for.body ]
  244. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  245. %0 = trunc i64 %indvars.iv to i32
  246. store i32 %0, i32* %arrayidx, align 4
  247. %arrayidx2 = getelementptr inbounds i32, i32* %add.ptr, i64 %indvars.iv
  248. %1 = load i32, i32* %arrayidx2, align 4
  249. %add = add nsw i32 %1, %sum.013
  250. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  251. %cmp = icmp ult i64 %indvars.iv.next, 1024
  252. br i1 %cmp, label %for.body, label %for.cond.cleanup
  253. }
  254. ; void vectorizable_Write_Write(int *A) {
  255. ; int *B = A + 4;
  256. ; for (unsigned i = 0; i < 1024; i+=2) {
  257. ; A[i] = i;
  258. ; B[i] = i+1;
  259. ; }
  260. ; }
  261. ; CHECK: function 'vectorizable_Write_Write':
  262. ; CHECK-NEXT: for.body:
  263. ; CHECK-NEXT: Memory dependences are safe
  264. ; CHECK-NEXT: Interesting Dependences:
  265. ; CHECK-NEXT: BackwardVectorizable:
  266. ; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
  267. ; CHECK-NEXT: store i32 %2, i32* %arrayidx2, align 4
  268. define void @vectorizable_Write_Write(i32* nocapture %A) {
  269. entry:
  270. %add.ptr = getelementptr inbounds i32, i32* %A, i64 4
  271. br label %for.body
  272. for.cond.cleanup: ; preds = %for.body
  273. ret void
  274. for.body: ; preds = %entry, %for.body
  275. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  276. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  277. %0 = trunc i64 %indvars.iv to i32
  278. store i32 %0, i32* %arrayidx, align 4
  279. %1 = or i64 %indvars.iv, 1
  280. %arrayidx2 = getelementptr inbounds i32, i32* %add.ptr, i64 %indvars.iv
  281. %2 = trunc i64 %1 to i32
  282. store i32 %2, i32* %arrayidx2, align 4
  283. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  284. %cmp = icmp ult i64 %indvars.iv.next, 1024
  285. br i1 %cmp, label %for.body, label %for.cond.cleanup
  286. }
  287. ; void vectorizable_unscaled_Read_Write(int *A) {
  288. ; int *B = (int *)((char *)A + 14);
  289. ; for (unsigned i = 0; i < 1024; i+=2)
  290. ; B[i] = A[i] + 1;
  291. ; }
  292. ; FIXME: This case looks like previous case @vectorizable_Read_Write. It sould
  293. ; be vectorizable.
  294. ; CHECK: function 'vectorizable_unscaled_Read_Write':
  295. ; CHECK-NEXT: for.body:
  296. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  297. ; CHECK-NEXT: Interesting Dependences:
  298. ; CHECK-NEXT: BackwardVectorizableButPreventsForwarding:
  299. ; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
  300. ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
  301. define void @vectorizable_unscaled_Read_Write(i32* nocapture %A) {
  302. entry:
  303. %0 = bitcast i32* %A to i8*
  304. %add.ptr = getelementptr inbounds i8, i8* %0, i64 14
  305. %1 = bitcast i8* %add.ptr to i32*
  306. br label %for.body
  307. for.cond.cleanup: ; preds = %for.body
  308. ret void
  309. for.body: ; preds = %entry, %for.body
  310. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  311. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  312. %2 = load i32, i32* %arrayidx, align 4
  313. %add = add nsw i32 %2, 1
  314. %arrayidx2 = getelementptr inbounds i32, i32* %1, i64 %indvars.iv
  315. store i32 %add, i32* %arrayidx2, align 4
  316. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  317. %cmp = icmp ult i64 %indvars.iv.next, 1024
  318. br i1 %cmp, label %for.body, label %for.cond.cleanup
  319. }
  320. ; int vectorizable_unscaled_Write_Read(int *A) {
  321. ; int *B = (int *)((char *)A + 17);
  322. ; int sum = 0;
  323. ; for (unsigned i = 0; i < 1024; i+=2) {
  324. ; A[i] = i;
  325. ; sum += B[i];
  326. ; }
  327. ;
  328. ; return sum;
  329. ; }
  330. ; CHECK: for function 'vectorizable_unscaled_Write_Read':
  331. ; CHECK-NEXT: for.body:
  332. ; CHECK-NEXT: Memory dependences are safe
  333. ; CHECK-NEXT: Interesting Dependences:
  334. ; CHECK-NEXT: BackwardVectorizable:
  335. ; CHECK-NEXT: store i32 %2, i32* %arrayidx, align 4 ->
  336. ; CHECK-NEXT: %3 = load i32, i32* %arrayidx2, align 4
  337. define i32 @vectorizable_unscaled_Write_Read(i32* nocapture %A) {
  338. entry:
  339. %0 = bitcast i32* %A to i8*
  340. %add.ptr = getelementptr inbounds i8, i8* %0, i64 17
  341. %1 = bitcast i8* %add.ptr to i32*
  342. br label %for.body
  343. for.cond.cleanup: ; preds = %for.body
  344. ret i32 %add
  345. for.body: ; preds = %entry, %for.body
  346. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  347. %sum.013 = phi i32 [ 0, %entry ], [ %add, %for.body ]
  348. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  349. %2 = trunc i64 %indvars.iv to i32
  350. store i32 %2, i32* %arrayidx, align 4
  351. %arrayidx2 = getelementptr inbounds i32, i32* %1, i64 %indvars.iv
  352. %3 = load i32, i32* %arrayidx2, align 4
  353. %add = add nsw i32 %3, %sum.013
  354. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  355. %cmp = icmp ult i64 %indvars.iv.next, 1024
  356. br i1 %cmp, label %for.body, label %for.cond.cleanup
  357. }
  358. ; void unsafe_unscaled_Read_Write(int *A) {
  359. ; int *B = (int *)((char *)A + 11);
  360. ; for (unsigned i = 0; i < 1024; i+=2)
  361. ; B[i] = A[i] + 1;
  362. ; }
  363. ; CHECK: function 'unsafe_unscaled_Read_Write':
  364. ; CHECK-NEXT: for.body:
  365. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  366. ; CHECK-NEXT: Interesting Dependences:
  367. ; CHECK-NEXT: Backward:
  368. ; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
  369. ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
  370. define void @unsafe_unscaled_Read_Write(i32* nocapture %A) {
  371. entry:
  372. %0 = bitcast i32* %A to i8*
  373. %add.ptr = getelementptr inbounds i8, i8* %0, i64 11
  374. %1 = bitcast i8* %add.ptr to i32*
  375. br label %for.body
  376. for.cond.cleanup: ; preds = %for.body
  377. ret void
  378. for.body: ; preds = %entry, %for.body
  379. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  380. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  381. %2 = load i32, i32* %arrayidx, align 4
  382. %add = add nsw i32 %2, 1
  383. %arrayidx2 = getelementptr inbounds i32, i32* %1, i64 %indvars.iv
  384. store i32 %add, i32* %arrayidx2, align 4
  385. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  386. %cmp = icmp ult i64 %indvars.iv.next, 1024
  387. br i1 %cmp, label %for.body, label %for.cond.cleanup
  388. }
  389. ; CHECK: function 'unsafe_unscaled_Read_Write2':
  390. ; CHECK-NEXT: for.body:
  391. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  392. ; CHECK-NEXT: Interesting Dependences:
  393. ; CHECK-NEXT: Backward:
  394. ; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
  395. ; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
  396. ; void unsafe_unscaled_Read_Write2(int *A) {
  397. ; int *B = (int *)((char *)A + 1);
  398. ; for (unsigned i = 0; i < 1024; i+=2)
  399. ; B[i] = A[i] + 1;
  400. ; }
  401. define void @unsafe_unscaled_Read_Write2(i32* nocapture %A) {
  402. entry:
  403. %0 = bitcast i32* %A to i8*
  404. %add.ptr = getelementptr inbounds i8, i8* %0, i64 1
  405. %1 = bitcast i8* %add.ptr to i32*
  406. br label %for.body
  407. for.cond.cleanup: ; preds = %for.body
  408. ret void
  409. for.body: ; preds = %entry, %for.body
  410. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  411. %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
  412. %2 = load i32, i32* %arrayidx, align 4
  413. %add = add nsw i32 %2, 1
  414. %arrayidx2 = getelementptr inbounds i32, i32* %1, i64 %indvars.iv
  415. store i32 %add, i32* %arrayidx2, align 4
  416. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  417. %cmp = icmp ult i64 %indvars.iv.next, 1024
  418. br i1 %cmp, label %for.body, label %for.cond.cleanup
  419. }
  420. ; Following case checks that interleaved stores have dependences with another
  421. ; store and can not pass dependence check.
  422. ; void interleaved_stores(int *A) {
  423. ; int *B = (int *) ((char *)A + 1);
  424. ; for(int i = 0; i < 1024; i+=2) {
  425. ; B[i] = i; // (1)
  426. ; A[i+1] = i + 1; // (2)
  427. ; B[i+1] = i + 1; // (3)
  428. ; }
  429. ; }
  430. ;
  431. ; The access (2) has overlaps with (1) and (3).
  432. ; CHECK: function 'interleaved_stores':
  433. ; CHECK-NEXT: for.body:
  434. ; CHECK-NEXT: Report: unsafe dependent memory operations in loop
  435. ; CHECK-NEXT: Interesting Dependences:
  436. ; CHECK-NEXT: Backward:
  437. ; CHECK-NEXT: store i32 %4, i32* %arrayidx5, align 4 ->
  438. ; CHECK-NEXT: store i32 %4, i32* %arrayidx9, align 4
  439. ; CHECK: Backward:
  440. ; CHECK-NEXT: store i32 %2, i32* %arrayidx2, align 4 ->
  441. ; CHECK-NEXT: store i32 %4, i32* %arrayidx5, align 4
  442. define void @interleaved_stores(i32* nocapture %A) {
  443. entry:
  444. %0 = bitcast i32* %A to i8*
  445. %incdec.ptr = getelementptr inbounds i8, i8* %0, i64 1
  446. %1 = bitcast i8* %incdec.ptr to i32*
  447. br label %for.body
  448. for.cond.cleanup: ; preds = %for.body
  449. ret void
  450. for.body: ; preds = %entry, %for.body
  451. %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  452. %2 = trunc i64 %indvars.iv to i32
  453. %arrayidx2 = getelementptr inbounds i32, i32* %1, i64 %indvars.iv
  454. store i32 %2, i32* %arrayidx2, align 4
  455. %3 = or i64 %indvars.iv, 1
  456. %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %3
  457. %4 = trunc i64 %3 to i32
  458. store i32 %4, i32* %arrayidx5, align 4
  459. %arrayidx9 = getelementptr inbounds i32, i32* %1, i64 %3
  460. store i32 %4, i32* %arrayidx9, align 4
  461. %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  462. %cmp = icmp slt i64 %indvars.iv.next, 1024
  463. br i1 %cmp, label %for.body, label %for.cond.cleanup
  464. }