1; RUN: opt -O3 -S < %s | FileCheck %s
2; Show 'optnone' suppresses optimizations.
3
4; Two attribute groups that differ only by 'optnone'.
5; 'optnone' requires 'noinline' so #0 is 'noinline' by itself,
6; even though it would otherwise be irrelevant to this example.
7attributes #0 = { noinline }
8attributes #1 = { noinline optnone }
9
10; int iadd(int a, int b){ return a + b; }
11
12define i32 @iadd_optimize(i32 %a, i32 %b) #0 {
13entry:
14  %a.addr = alloca i32, align 4
15  %b.addr = alloca i32, align 4
16  store i32 %a, i32* %a.addr, align 4
17  store i32 %b, i32* %b.addr, align 4
18  %0 = load i32, i32* %a.addr, align 4
19  %1 = load i32, i32* %b.addr, align 4
20  %add = add nsw i32 %0, %1
21  ret i32 %add
22}
23
24; CHECK-LABEL: @iadd_optimize
25; CHECK-NOT: alloca
26; CHECK-NOT: store
27; CHECK-NOT: load
28; CHECK: ret
29
30define i32 @iadd_optnone(i32 %a, i32 %b) #1 {
31entry:
32  %a.addr = alloca i32, align 4
33  %b.addr = alloca i32, align 4
34  store i32 %a, i32* %a.addr, align 4
35  store i32 %b, i32* %b.addr, align 4
36  %0 = load i32, i32* %a.addr, align 4
37  %1 = load i32, i32* %b.addr, align 4
38  %add = add nsw i32 %0, %1
39  ret i32 %add
40}
41
42; CHECK-LABEL: @iadd_optnone
43; CHECK: alloca i32
44; CHECK: alloca i32
45; CHECK: store i32
46; CHECK: store i32
47; CHECK: load i32
48; CHECK: load i32
49; CHECK: add nsw i32
50; CHECK: ret i32
51
52; float fsub(float a, float b){ return a - b; }
53
54define float @fsub_optimize(float %a, float %b) #0 {
55entry:
56  %a.addr = alloca float, align 4
57  %b.addr = alloca float, align 4
58  store float %a, float* %a.addr, align 4
59  store float %b, float* %b.addr, align 4
60  %0 = load float, float* %a.addr, align 4
61  %1 = load float, float* %b.addr, align 4
62  %sub = fsub float %0, %1
63  ret float %sub
64}
65
66; CHECK-LABEL: @fsub_optimize
67; CHECK-NOT: alloca
68; CHECK-NOT: store
69; CHECK-NOT: load
70; CHECK: ret
71
72define float @fsub_optnone(float %a, float %b) #1 {
73entry:
74  %a.addr = alloca float, align 4
75  %b.addr = alloca float, align 4
76  store float %a, float* %a.addr, align 4
77  store float %b, float* %b.addr, align 4
78  %0 = load float, float* %a.addr, align 4
79  %1 = load float, float* %b.addr, align 4
80  %sub = fsub float %0, %1
81  ret float %sub
82}
83
84; CHECK-LABEL: @fsub_optnone
85; CHECK: alloca float
86; CHECK: alloca float
87; CHECK: store float
88; CHECK: store float
89; CHECK: load float
90; CHECK: load float
91; CHECK: fsub float
92; CHECK: ret float
93
94; typedef float __attribute__((ext_vector_type(4))) float4;
95; float4 vmul(float4 a, float4 b){ return a * b; }
96
97define <4 x float> @vmul_optimize(<4 x float> %a, <4 x float> %b) #0 {
98entry:
99  %a.addr = alloca <4 x float>, align 16
100  %b.addr = alloca <4 x float>, align 16
101  store <4 x float> %a, <4 x float>* %a.addr, align 16
102  store <4 x float> %b, <4 x float>* %b.addr, align 16
103  %0 = load <4 x float>, <4 x float>* %a.addr, align 16
104  %1 = load <4 x float>, <4 x float>* %b.addr, align 16
105  %mul = fmul <4 x float> %0, %1
106  ret <4 x float> %mul
107}
108
109; CHECK-LABEL: @vmul_optimize
110; CHECK-NOT: alloca
111; CHECK-NOT: store
112; CHECK-NOT: load
113; CHECK: ret
114
115define <4 x float> @vmul_optnone(<4 x float> %a, <4 x float> %b) #1 {
116entry:
117  %a.addr = alloca <4 x float>, align 16
118  %b.addr = alloca <4 x float>, align 16
119  store <4 x float> %a, <4 x float>* %a.addr, align 16
120  store <4 x float> %b, <4 x float>* %b.addr, align 16
121  %0 = load <4 x float>, <4 x float>* %a.addr, align 16
122  %1 = load <4 x float>, <4 x float>* %b.addr, align 16
123  %mul = fmul <4 x float> %0, %1
124  ret <4 x float> %mul
125}
126
127; CHECK-LABEL: @vmul_optnone
128; CHECK: alloca <4 x float>
129; CHECK: alloca <4 x float>
130; CHECK: store <4 x float>
131; CHECK: store <4 x float>
132; CHECK: load <4 x float>
133; CHECK: load <4 x float>
134; CHECK: fmul <4 x float>
135; CHECK: ret
136