xref: /llvm-project/llvm/test/Transforms/EarlyCSE/round-dyn-strictfp.ll (revision ac696ac4530fb3df626195e94e83649bf7114754)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -passes=early-cse -earlycse-debug-hash | FileCheck %s
3; RUN: opt < %s -S -passes='early-cse<memssa>' | FileCheck %s
4
5; Test use of constrained floating point intrinsics with dynamic
6; rounding mode. Dynamic rounding _must_ disable CSE since EarlyCSE
7; will CSE across function calls and we cannot know if the rounding
8; mode will be changed by any arbitrary function call.
9
10define double @multiple_fadd(double %a, double %b) #0 {
11; CHECK-LABEL: @multiple_fadd(
12; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]]
13; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
14; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
15; CHECK-NEXT:    ret double [[TMP2]]
16;
17  %1 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
18  %2 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
19  %3 = call double @foo.f64(double %1, double %2) #0
20  ret double %2
21}
22
23define double @multiple_fadd_split(double %a, double %b) #0 {
24; CHECK-LABEL: @multiple_fadd_split(
25; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
26; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
27; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
28; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
29; CHECK-NEXT:    ret double [[TMP2]]
30;
31  %1 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
32  call void @arbitraryfunc() #0
33  %2 = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
34  %3 = call double @foo.f64(double %1, double %2) #0
35  ret double %2
36}
37
38define double @multiple_fsub(double %a, double %b) #0 {
39; CHECK-LABEL: @multiple_fsub(
40; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
41; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
42; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
43; CHECK-NEXT:    ret double [[TMP2]]
44;
45  %1 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
46  %2 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
47  %3 = call double @foo.f64(double %1, double %2) #0
48  ret double %2
49}
50
51define double @multiple_fsub_split(double %a, double %b) #0 {
52; CHECK-LABEL: @multiple_fsub_split(
53; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
54; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
55; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fsub.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
56; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
57; CHECK-NEXT:    ret double [[TMP2]]
58;
59  %1 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
60  call void @arbitraryfunc() #0
61  %2 = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
62  %3 = call double @foo.f64(double %1, double %2) #0
63  ret double %2
64}
65
66define double @multiple_fmul(double %a, double %b) #0 {
67; CHECK-LABEL: @multiple_fmul(
68; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
69; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
70; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
71; CHECK-NEXT:    ret double [[TMP2]]
72;
73  %1 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
74  %2 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
75  %3 = call double @foo.f64(double %1, double %2) #0
76  ret double %2
77}
78
79define double @multiple_fmul_split(double %a, double %b) #0 {
80; CHECK-LABEL: @multiple_fmul_split(
81; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
82; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
83; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
84; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
85; CHECK-NEXT:    ret double [[TMP2]]
86;
87  %1 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
88  call void @arbitraryfunc() #0
89  %2 = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
90  %3 = call double @foo.f64(double %1, double %2) #0
91  ret double %2
92}
93
94define double @multiple_fdiv(double %a, double %b) #0 {
95; CHECK-LABEL: @multiple_fdiv(
96; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
97; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
98; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
99; CHECK-NEXT:    ret double [[TMP2]]
100;
101  %1 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
102  %2 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
103  %3 = call double @foo.f64(double %1, double %2) #0
104  ret double %2
105}
106
107define double @multiple_fdiv_split(double %a, double %b) #0 {
108; CHECK-LABEL: @multiple_fdiv_split(
109; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
110; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
111; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
112; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
113; CHECK-NEXT:    ret double [[TMP2]]
114;
115  %1 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
116  call void @arbitraryfunc() #0
117  %2 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
118  %3 = call double @foo.f64(double %1, double %2) #0
119  ret double %2
120}
121
122define double @multiple_frem(double %a, double %b) #0 {
123; CHECK-LABEL: @multiple_frem(
124; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
125; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
126; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
127; CHECK-NEXT:    ret double [[TMP2]]
128;
129  %1 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
130  %2 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
131  %3 = call double @foo.f64(double %1, double %2) #0
132  ret double %2
133}
134
135define double @multiple_frem_split(double %a, double %b) #0 {
136; CHECK-LABEL: @multiple_frem_split(
137; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A:%.*]], double [[B:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
138; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
139; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.frem.f64(double [[A]], double [[B]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
140; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP2]]) #[[ATTR0]]
141; CHECK-NEXT:    ret double [[TMP2]]
142;
143  %1 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
144  call void @arbitraryfunc() #0
145  %2 = call double @llvm.experimental.constrained.frem.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
146  %3 = call double @foo.f64(double %1, double %2) #0
147  ret double %2
148}
149
150define double @multiple_uitofp(i32 %a) #0 {
151; CHECK-LABEL: @multiple_uitofp(
152; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
153; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
154; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]
155; CHECK-NEXT:    ret double [[TMP2]]
156;
157  %1 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
158  %2 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
159  %3 = call double @foo.f64(double %1, double %1) #0
160  ret double %2
161}
162
163define double @multiple_uitofp_split(i32 %a) #0 {
164; CHECK-LABEL: @multiple_uitofp_split(
165; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
166; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
167; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
168; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]
169; CHECK-NEXT:    ret double [[TMP2]]
170;
171  %1 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
172  call void @arbitraryfunc() #0
173  %2 = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
174  %3 = call double @foo.f64(double %1, double %1) #0
175  ret double %2
176}
177
178define double @multiple_sitofp(i32 %a) #0 {
179; CHECK-LABEL: @multiple_sitofp(
180; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
181; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
182; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]
183; CHECK-NEXT:    ret double [[TMP2]]
184;
185  %1 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
186  %2 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
187  %3 = call double @foo.f64(double %1, double %1) #0
188  ret double %2
189}
190
191define double @multiple_sitofp_split(i32 %a) #0 {
192; CHECK-LABEL: @multiple_sitofp_split(
193; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A:%.*]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
194; CHECK-NEXT:    call void @arbitraryfunc() #[[ATTR0]]
195; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 [[A]], metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
196; CHECK-NEXT:    [[TMP3:%.*]] = call double @foo.f64(double [[TMP1]], double [[TMP1]]) #[[ATTR0]]
197; CHECK-NEXT:    ret double [[TMP2]]
198;
199  %1 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
200  call void @arbitraryfunc() #0
201  %2 = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
202  %3 = call double @foo.f64(double %1, double %1) #0
203  ret double %2
204}
205
206attributes #0 = { strictfp }
207
208declare void @arbitraryfunc() #0
209declare double @foo.f64(double, double) #0
210declare i32 @bar.i32(i32, i32) #0
211
212declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
213declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata)
214declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)
215declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)
216declare double @llvm.experimental.constrained.frem.f64(double, double, metadata, metadata)
217declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)
218declare double @llvm.experimental.constrained.uitofp.f64.i32(i32, metadata, metadata)
219declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata)
220declare double @llvm.experimental.constrained.sitofp.f64.i32(i32, metadata, metadata)
221declare i1 @llvm.experimental.constrained.fcmp.i1.f64(double, double, metadata, metadata)
222declare i1 @llvm.experimental.constrained.fcmps.i1.f64(double, double, metadata, metadata)
223