xref: /llvm-project/llvm/test/Transforms/Sink/invariant-load.ll (revision 7eaf92b3e4db5e3be9e9ee137866090d66dd08fb)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=sink -S < %s | FileCheck %s
3
4; Loads marked invariant can be sunk across critical edges.
5
6define <4 x float> @invariant_load(ptr %in, i32 %s) {
7; CHECK-LABEL: @invariant_load(
8; CHECK-NEXT:  main_body:
9; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[S:%.*]], 0
10; CHECK-NEXT:    br i1 [[C]], label [[BLOCK:%.*]], label [[END:%.*]]
11; CHECK:       block:
12; CHECK-NEXT:    [[Z:%.*]] = add i32 [[S]], 1
13; CHECK-NEXT:    br label [[END]]
14; CHECK:       end:
15; CHECK-NEXT:    [[V:%.*]] = load <4 x float>, ptr [[IN:%.*]], align 16, !invariant.load [[META0:![0-9]+]]
16; CHECK-NEXT:    ret <4 x float> [[V]]
17;
18main_body:
19  %v = load <4 x float>, ptr %in, !invariant.load !0
20  %c = icmp eq i32 %s, 0
21  br i1 %c, label %block, label %end
22block:
23  %z = add i32 %s, 1
24  br label %end
25end:
26  ret <4 x float> %v
27}
28
29; Loads that aren't marked invariant but used in one branch
30; can be sunk to that branch.
31
32define void @invariant_load_use_in_br(ptr %p, i1 %cond) {
33; CHECK-LABEL: @invariant_load_use_in_br(
34; CHECK-NEXT:  entry:
35; CHECK-NEXT:    br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]]
36; CHECK:       true.br:
37; CHECK-NEXT:    call void @fn()
38; CHECK-NEXT:    br label [[EXIT:%.*]]
39; CHECK:       false.br:
40; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4
41; CHECK-NEXT:    call void @fn(i32 [[VAL]])
42; CHECK-NEXT:    br label [[EXIT]]
43; CHECK:       exit:
44; CHECK-NEXT:    ret void
45;
46entry:
47  %val = load i32, ptr %p
48  br i1 %cond, label %true.br, label %false.br
49true.br:
50  call void @fn()
51  br label %exit
52false.br:
53  call void @fn(i32 %val)
54  br label %exit
55exit:
56  ret void
57}
58
59; TODO: Invariant loads marked with metadata can be sunk past calls.
60
61define void @invariant_load_metadata_call(ptr %p, i1 %cond) {
62; CHECK-LABEL: @invariant_load_metadata_call(
63; CHECK-NEXT:  entry:
64; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4, !invariant.load [[META0]]
65; CHECK-NEXT:    call void @fn()
66; CHECK-NEXT:    br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]]
67; CHECK:       true.br:
68; CHECK-NEXT:    call void @fn()
69; CHECK-NEXT:    br label [[EXIT:%.*]]
70; CHECK:       false.br:
71; CHECK-NEXT:    call void @fn(i32 [[VAL]])
72; CHECK-NEXT:    br label [[EXIT]]
73; CHECK:       exit:
74; CHECK-NEXT:    ret void
75;
76entry:
77  %val = load i32, ptr %p, !invariant.load !0
78  call void @fn()
79  br i1 %cond, label %true.br, label %false.br
80true.br:
81  call void @fn()
82  br label %exit
83false.br:
84  call void @fn(i32 %val)
85  br label %exit
86exit:
87  ret void
88}
89
90declare void @fn()
91
92!0 = !{}
93