@@ -309,3 +309,120 @@ loop:
309
309
exit:
310
310
ret void
311
311
}
312
+
313
+ ; TODO: could validly hoist the store here since we know what value
314
+ ; the load must observe.
315
+ define i32 @test_dominated_read (i32* %loc ) {
316
+ ; CHECK-LABEL: @test_dominated_read
317
+ ; CHECK-LABEL: exit:
318
+ ; CHECK: store i32 0, i32* %loc
319
+ entry:
320
+ br label %loop
321
+
322
+ loop:
323
+ %iv = phi i32 [0 , %entry ], [%iv.next , %loop ]
324
+ store i32 0 , i32* %loc
325
+ %reload = load i32 , i32* %loc
326
+ %iv.next = add i32 %iv , 1
327
+ %cmp = icmp slt i32 %iv , 200
328
+ br i1 %cmp , label %loop , label %exit
329
+
330
+ exit:
331
+ ret i32 %reload
332
+ }
333
+
334
+ ; TODO: could validly hoist the store since we already hoisted the load and
335
+ ; it's no longer in the loop.
336
+ define i32 @test_dominating_read (i32* %loc ) {
337
+ ; CHECK-LABEL: @test_dominating_read
338
+ ; CHECK-LABEL: exit:
339
+ ; CHECK: store i32 0, i32* %loc
340
+ entry:
341
+ br label %loop
342
+
343
+ loop:
344
+ %iv = phi i32 [0 , %entry ], [%iv.next , %loop ]
345
+ %reload = load i32 , i32* %loc
346
+ store i32 0 , i32* %loc
347
+ %iv.next = add i32 %iv , 1
348
+ %cmp = icmp slt i32 %iv , 200
349
+ br i1 %cmp , label %loop , label %exit
350
+
351
+ exit:
352
+ ret i32 %reload
353
+ }
354
+
355
+ declare void @readonly () readonly
356
+
357
+ ; TODO: can legally hoist since value read by call is known
358
+ define void @test_dominated_readonly (i32* %loc ) {
359
+ ; CHECK-LABEL: @test_dominated_readonly
360
+ ; CHECK-LABEL: loop:
361
+ ; CHECK: store i32 0, i32* %loc
362
+ ; CHECK-LABEL: exit:
363
+ entry:
364
+ br label %loop
365
+
366
+ loop:
367
+ %iv = phi i32 [0 , %entry ], [%iv.next , %loop ]
368
+ store i32 0 , i32* %loc
369
+ call void @readonly ()
370
+ %iv.next = add i32 %iv , 1
371
+ %cmp = icmp slt i32 %iv , 200
372
+ br i1 %cmp , label %loop , label %exit
373
+
374
+ exit:
375
+ ret void
376
+ }
377
+
378
+ ; While technically possible to hoist the store to %loc, this runs across
379
+ ; a funemental limitation of alias sets since both stores and the call are
380
+ ; within the same alias set and we can't distinguish them cheaply.
381
+ define void @test_aliasset_fn (i32* %loc , i32* %loc2 ) {
382
+ ; CHECK-LABEL: @test_aliasset_fn
383
+ ; CHECK-LABEL: loop:
384
+ ; CHECK: store i32 0, i32* %loc
385
+ ; CHECK-LABEL: exit:
386
+ entry:
387
+ br label %loop
388
+
389
+ loop:
390
+ %iv = phi i32 [0 , %entry ], [%iv.next , %loop ]
391
+ store i32 0 , i32* %loc
392
+ call void @readonly ()
393
+ store i32 %iv , i32* %loc2
394
+ %iv.next = add i32 %iv , 1
395
+ %cmp = icmp slt i32 %iv , 200
396
+ br i1 %cmp , label %loop , label %exit
397
+
398
+ exit:
399
+ ret void
400
+ }
401
+
402
+
403
+ ; If we can't tell if the value is read before the write, we can't hoist the
404
+ ; write over the potential read (since we don't know the value read)
405
+ define void @neg_may_read (i32* %loc , i1 %maybe ) {
406
+ ; CHECK-LABEL: @neg_may_read
407
+ ; CHECK-LABEL: loop:
408
+ ; CHECK: store i32 0, i32* %loc
409
+ ; CHECK-LABEL: exit:
410
+ entry:
411
+ br label %loop
412
+
413
+ loop:
414
+ %iv = phi i32 [0 , %entry ], [%iv.next , %merge ]
415
+ ;; maybe is a placeholder for an unanalyzable condition
416
+ br i1 %maybe , label %taken , label %merge
417
+ taken:
418
+ call void @readonly ()
419
+ br label %merge
420
+ merge:
421
+ store i32 0 , i32* %loc
422
+ %iv.next = add i32 %iv , 1
423
+ %cmp = icmp slt i32 %iv , 200
424
+ br i1 %cmp , label %loop , label %exit
425
+
426
+ exit:
427
+ ret void
428
+ }
0 commit comments