1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2; RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-linux-gnu < %s \
3; RUN:   -stop-after=finalize-isel -verify-machineinstrs | FileCheck %s
4
5; Verify if the mayRaiseFPException is set for FCMPD/FCMPS
6define i32 @fcmpu(double %a, double %b) {
7  ; CHECK-LABEL: name: fcmpu
8  ; CHECK: bb.0.entry:
9  ; CHECK-NEXT:   liveins: $f1, $f2
10  ; CHECK-NEXT: {{  $}}
11  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:f8rc = COPY $f2
12  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:f8rc = COPY $f1
13  ; CHECK-NEXT:   %2:crrc = nofpexcept FCMPUD [[COPY1]], [[COPY]]
14  ; CHECK-NEXT:   [[COPY2:%[0-9]+]]:crbitrc = COPY %2.sub_gt
15  ; CHECK-NEXT:   [[LI8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = LI8 0
16  ; CHECK-NEXT:   [[LI8_1:%[0-9]+]]:g8rc_and_g8rc_nox0 = LI8 1
17  ; CHECK-NEXT:   [[ISEL8_:%[0-9]+]]:g8rc = ISEL8 [[LI8_1]], [[LI8_]], [[COPY2]]
18  ; CHECK-NEXT:   $x3 = COPY [[ISEL8_]]
19  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
20entry:
21  %r = fcmp ogt double %a, %b
22  %g = zext i1 %r to i32
23  ret i32 %g
24}
25
26define double @max_typec(double %a, double %b) {
27  ; CHECK-LABEL: name: max_typec
28  ; CHECK: bb.0.entry:
29  ; CHECK-NEXT:   liveins: $f1, $f2
30  ; CHECK-NEXT: {{  $}}
31  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vsfrc = COPY $f2
32  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:vsfrc = COPY $f1
33  ; CHECK-NEXT:   %2:vsfrc = nofpexcept XSMAXCDP [[COPY1]], [[COPY]]
34  ; CHECK-NEXT:   $f1 = COPY %2
35  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $f1
36entry:
37  %cmp = fcmp ogt double %a, %b
38  %sel = select i1 %cmp, double %a, double %b
39  ret double %sel
40}
41
42; Verify no mayRaiseFPException bit set on fneg & fabs
43define double @fneg(double %a) {
44  ; CHECK-LABEL: name: fneg
45  ; CHECK: bb.0.entry:
46  ; CHECK-NEXT:   liveins: $f1
47  ; CHECK-NEXT: {{  $}}
48  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vsfrc = COPY $f1
49  ; CHECK-NEXT:   [[XSNEGDP:%[0-9]+]]:vsfrc = XSNEGDP [[COPY]], implicit $rm
50  ; CHECK-NEXT:   $f1 = COPY [[XSNEGDP]]
51  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $f1
52entry:
53  %neg = fneg double %a
54  ret double %neg
55}
56
57define double @fabs(double %a) {
58  ; CHECK-LABEL: name: fabs
59  ; CHECK: bb.0.entry:
60  ; CHECK-NEXT:   liveins: $f1
61  ; CHECK-NEXT: {{  $}}
62  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vsfrc = COPY $f1
63  ; CHECK-NEXT:   [[XSABSDP:%[0-9]+]]:vsfrc = XSABSDP [[COPY]], implicit $rm
64  ; CHECK-NEXT:   $f1 = COPY [[XSABSDP]]
65  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $f1
66entry:
67  %abs = call double @llvm.fabs.f64(double %a)
68  ret double %abs
69}
70
71; Verify nofpexcept is set to constrained conversions when ignoring exceptions
72define void @fptoint_nofpexcept(ppc_fp128 %p, fp128 %m, i32* %addr1, i64* %addr2) {
73  ; CHECK-LABEL: name: fptoint_nofpexcept
74  ; CHECK: bb.0.entry:
75  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
76  ; CHECK-NEXT:   liveins: $f1, $f2, $v2, $x7, $x8
77  ; CHECK-NEXT: {{  $}}
78  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:g8rc_and_g8rc_nox0 = COPY $x8
79  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:g8rc_and_g8rc_nox0 = COPY $x7
80  ; CHECK-NEXT:   [[COPY2:%[0-9]+]]:vrrc = COPY $v2
81  ; CHECK-NEXT:   [[COPY3:%[0-9]+]]:f8rc = COPY $f2
82  ; CHECK-NEXT:   [[COPY4:%[0-9]+]]:f8rc = COPY $f1
83  ; CHECK-NEXT:   %5:vrrc = nofpexcept XSCVQPSWZ [[COPY2]]
84  ; CHECK-NEXT:   [[COPY5:%[0-9]+]]:vslrc = COPY %5
85  ; CHECK-NEXT:   [[COPY6:%[0-9]+]]:vfrc = COPY [[COPY5]].sub_64
86  ; CHECK-NEXT:   [[MFVSRWZ:%[0-9]+]]:gprc = MFVSRWZ killed [[COPY6]]
87  ; CHECK-NEXT:   STW killed [[MFVSRWZ]], 0, [[COPY1]] :: (volatile store (s32) into %ir.addr1)
88  ; CHECK-NEXT:   %8:vrrc = nofpexcept XSCVQPUWZ [[COPY2]]
89  ; CHECK-NEXT:   [[COPY7:%[0-9]+]]:vslrc = COPY %8
90  ; CHECK-NEXT:   [[COPY8:%[0-9]+]]:vfrc = COPY [[COPY7]].sub_64
91  ; CHECK-NEXT:   [[MFVSRWZ1:%[0-9]+]]:gprc = MFVSRWZ killed [[COPY8]]
92  ; CHECK-NEXT:   STW killed [[MFVSRWZ1]], 0, [[COPY1]] :: (volatile store (s32) into %ir.addr1)
93  ; CHECK-NEXT:   %11:vrrc = nofpexcept XSCVQPSDZ [[COPY2]]
94  ; CHECK-NEXT:   %12:g8rc = nofpexcept MFVRD killed %11
95  ; CHECK-NEXT:   STD killed %12, 0, [[COPY]] :: (volatile store (s64) into %ir.addr2)
96  ; CHECK-NEXT:   %13:vrrc = nofpexcept XSCVQPUDZ [[COPY2]]
97  ; CHECK-NEXT:   %14:g8rc = nofpexcept MFVRD killed %13
98  ; CHECK-NEXT:   STD killed %14, 0, [[COPY]] :: (volatile store (s64) into %ir.addr2)
99  ; CHECK-NEXT:   [[MFFS:%[0-9]+]]:f8rc = MFFS implicit $rm
100  ; CHECK-NEXT:   MTFSB1 31, implicit-def $rm, implicit-def $rm
101  ; CHECK-NEXT:   MTFSB0 30, implicit-def $rm, implicit-def $rm
102  ; CHECK-NEXT:   %15:f8rc = nofpexcept FADD [[COPY3]], [[COPY4]], implicit $rm
103  ; CHECK-NEXT:   MTFSFb 1, [[MFFS]], implicit-def $rm
104  ; CHECK-NEXT:   %16:vsfrc = nofpexcept XSCVDPSXWS killed %15, implicit $rm
105  ; CHECK-NEXT:   [[MFVSRWZ2:%[0-9]+]]:gprc = MFVSRWZ killed %16
106  ; CHECK-NEXT:   STW killed [[MFVSRWZ2]], 0, [[COPY1]] :: (volatile store (s32) into %ir.addr1)
107  ; CHECK-NEXT:   [[ADDIStocHA8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, %const.0
108  ; CHECK-NEXT:   [[DFLOADf32_:%[0-9]+]]:vssrc = DFLOADf32 target-flags(ppc-toc-lo) %const.0, killed [[ADDIStocHA8_]] :: (load (s32) from constant-pool)
109  ; CHECK-NEXT:   [[COPY9:%[0-9]+]]:f8rc = COPY [[DFLOADf32_]]
110  ; CHECK-NEXT:   [[FCMPOD:%[0-9]+]]:crrc = FCMPOD [[COPY4]], [[COPY9]]
111  ; CHECK-NEXT:   [[COPY10:%[0-9]+]]:crbitrc = COPY [[FCMPOD]].sub_eq
112  ; CHECK-NEXT:   [[XXLXORdpz:%[0-9]+]]:f8rc = XXLXORdpz
113  ; CHECK-NEXT:   [[FCMPOD1:%[0-9]+]]:crrc = FCMPOD [[COPY3]], [[XXLXORdpz]]
114  ; CHECK-NEXT:   [[COPY11:%[0-9]+]]:crbitrc = COPY [[FCMPOD1]].sub_lt
115  ; CHECK-NEXT:   [[CRAND:%[0-9]+]]:crbitrc = CRAND killed [[COPY10]], killed [[COPY11]]
116  ; CHECK-NEXT:   [[COPY12:%[0-9]+]]:crbitrc = COPY [[FCMPOD]].sub_eq
117  ; CHECK-NEXT:   [[COPY13:%[0-9]+]]:crbitrc = COPY [[FCMPOD]].sub_lt
118  ; CHECK-NEXT:   [[CRANDC:%[0-9]+]]:crbitrc = CRANDC killed [[COPY13]], killed [[COPY12]]
119  ; CHECK-NEXT:   [[CROR:%[0-9]+]]:crbitrc = CROR killed [[CRANDC]], killed [[CRAND]]
120  ; CHECK-NEXT:   [[LIS:%[0-9]+]]:gprc_and_gprc_nor0 = LIS 32768
121  ; CHECK-NEXT:   [[LI:%[0-9]+]]:gprc_and_gprc_nor0 = LI 0
122  ; CHECK-NEXT:   [[ISEL:%[0-9]+]]:gprc = ISEL [[LI]], [[LIS]], [[CROR]]
123  ; CHECK-NEXT:   BC [[CROR]], %bb.2
124  ; CHECK-NEXT: {{  $}}
125  ; CHECK-NEXT: bb.1.entry:
126  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
127  ; CHECK-NEXT: {{  $}}
128  ; CHECK-NEXT: {{  $}}
129  ; CHECK-NEXT: bb.2.entry:
130  ; CHECK-NEXT:   [[PHI:%[0-9]+]]:f8rc = PHI [[COPY9]], %bb.1, [[XXLXORdpz]], %bb.0
131  ; CHECK-NEXT:   ADJCALLSTACKDOWN 32, 0, implicit-def dead $r1, implicit $r1
132  ; CHECK-NEXT:   $f1 = COPY [[COPY4]]
133  ; CHECK-NEXT:   $f2 = COPY [[COPY3]]
134  ; CHECK-NEXT:   $f3 = COPY [[PHI]]
135  ; CHECK-NEXT:   $f4 = COPY [[XXLXORdpz]]
136  ; CHECK-NEXT:   BL8_NOP &__gcc_qsub, csr_ppc64_altivec, implicit-def dead $lr8, implicit $rm, implicit $f1, implicit $f2, implicit $f3, implicit $f4, implicit $x2, implicit-def $r1, implicit-def $f1, implicit-def $f2
137  ; CHECK-NEXT:   ADJCALLSTACKUP 32, 0, implicit-def dead $r1, implicit $r1
138  ; CHECK-NEXT:   [[COPY14:%[0-9]+]]:f8rc = COPY $f1
139  ; CHECK-NEXT:   [[COPY15:%[0-9]+]]:f8rc = COPY $f2
140  ; CHECK-NEXT:   [[MFFS1:%[0-9]+]]:f8rc = MFFS implicit $rm
141  ; CHECK-NEXT:   MTFSB1 31, implicit-def $rm, implicit-def $rm
142  ; CHECK-NEXT:   MTFSB0 30, implicit-def $rm, implicit-def $rm
143  ; CHECK-NEXT:   %37:f8rc = nofpexcept FADD [[COPY15]], [[COPY14]], implicit $rm
144  ; CHECK-NEXT:   MTFSFb 1, [[MFFS1]], implicit-def $rm
145  ; CHECK-NEXT:   %38:vsfrc = nofpexcept XSCVDPSXWS killed %37, implicit $rm
146  ; CHECK-NEXT:   [[MFVSRWZ3:%[0-9]+]]:gprc = MFVSRWZ killed %38
147  ; CHECK-NEXT:   [[XOR:%[0-9]+]]:gprc = XOR killed [[MFVSRWZ3]], killed [[ISEL]]
148  ; CHECK-NEXT:   STW killed [[XOR]], 0, [[COPY1]] :: (volatile store (s32) into %ir.addr1)
149  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm
150entry:
151  %conv1 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f128(fp128 %m, metadata !"fpexcept.ignore") #0
152  store volatile i32 %conv1, i32* %addr1, align 4
153  %conv2 = tail call i32 @llvm.experimental.constrained.fptoui.i32.f128(fp128 %m, metadata !"fpexcept.ignore") #0
154  store volatile i32 %conv2, i32* %addr1, align 4
155  %conv3 = tail call i64 @llvm.experimental.constrained.fptosi.i64.f128(fp128 %m, metadata !"fpexcept.ignore") #0
156  store volatile i64 %conv3, i64* %addr2, align 8
157  %conv4 = tail call i64 @llvm.experimental.constrained.fptoui.i64.f128(fp128 %m, metadata !"fpexcept.ignore") #0
158  store volatile i64 %conv4, i64* %addr2, align 8
159
160  %conv5 = tail call i32 @llvm.experimental.constrained.fptosi.i32.ppcf128(ppc_fp128 %p, metadata !"fpexcept.ignore") #0
161  store volatile i32 %conv5, i32* %addr1, align 4
162  %conv6 = tail call i32 @llvm.experimental.constrained.fptoui.i32.ppcf128(ppc_fp128 %p, metadata !"fpexcept.ignore") #0
163  store volatile i32 %conv6, i32* %addr1, align 4
164  ret void
165}
166
167; Verify nofpexcept is NOT set to constrained conversions
168define signext i32 @q_to_i32(fp128 %m) #0 {
169  ; CHECK-LABEL: name: q_to_i32
170  ; CHECK: bb.0.entry:
171  ; CHECK-NEXT:   liveins: $v2
172  ; CHECK-NEXT: {{  $}}
173  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vrrc = COPY $v2
174  ; CHECK-NEXT:   [[XSCVQPSWZ:%[0-9]+]]:vrrc = XSCVQPSWZ [[COPY]]
175  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:vslrc = COPY [[XSCVQPSWZ]]
176  ; CHECK-NEXT:   [[COPY2:%[0-9]+]]:vfrc = COPY [[COPY1]].sub_64
177  ; CHECK-NEXT:   [[MFVSRWZ:%[0-9]+]]:gprc = MFVSRWZ killed [[COPY2]]
178  ; CHECK-NEXT:   [[EXTSW_32_64_:%[0-9]+]]:g8rc = EXTSW_32_64 killed [[MFVSRWZ]]
179  ; CHECK-NEXT:   $x3 = COPY [[EXTSW_32_64_]]
180  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
181entry:
182  %conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f128(fp128 %m, metadata !"fpexcept.strict") #0
183  ret i32 %conv
184}
185
186define i64 @q_to_i64(fp128 %m) #0 {
187  ; CHECK-LABEL: name: q_to_i64
188  ; CHECK: bb.0.entry:
189  ; CHECK-NEXT:   liveins: $v2
190  ; CHECK-NEXT: {{  $}}
191  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vrrc = COPY $v2
192  ; CHECK-NEXT:   [[XSCVQPSDZ:%[0-9]+]]:vrrc = XSCVQPSDZ [[COPY]]
193  ; CHECK-NEXT:   [[MFVRD:%[0-9]+]]:g8rc = MFVRD killed [[XSCVQPSDZ]]
194  ; CHECK-NEXT:   $x3 = COPY [[MFVRD]]
195  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
196entry:
197  %conv = tail call i64 @llvm.experimental.constrained.fptosi.i64.f128(fp128 %m, metadata !"fpexcept.strict") #0
198  ret i64 %conv
199}
200
201define i64 @q_to_u64(fp128 %m) #0 {
202  ; CHECK-LABEL: name: q_to_u64
203  ; CHECK: bb.0.entry:
204  ; CHECK-NEXT:   liveins: $v2
205  ; CHECK-NEXT: {{  $}}
206  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vrrc = COPY $v2
207  ; CHECK-NEXT:   [[XSCVQPUDZ:%[0-9]+]]:vrrc = XSCVQPUDZ [[COPY]]
208  ; CHECK-NEXT:   [[MFVRD:%[0-9]+]]:g8rc = MFVRD killed [[XSCVQPUDZ]]
209  ; CHECK-NEXT:   $x3 = COPY [[MFVRD]]
210  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
211entry:
212  %conv = tail call i64 @llvm.experimental.constrained.fptoui.i64.f128(fp128 %m, metadata !"fpexcept.strict") #0
213  ret i64 %conv
214}
215
216define zeroext i32 @q_to_u32(fp128 %m) #0 {
217  ; CHECK-LABEL: name: q_to_u32
218  ; CHECK: bb.0.entry:
219  ; CHECK-NEXT:   liveins: $v2
220  ; CHECK-NEXT: {{  $}}
221  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vrrc = COPY $v2
222  ; CHECK-NEXT:   [[XSCVQPUWZ:%[0-9]+]]:vrrc = XSCVQPUWZ [[COPY]]
223  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:vslrc = COPY [[XSCVQPUWZ]]
224  ; CHECK-NEXT:   [[COPY2:%[0-9]+]]:vfrc = COPY [[COPY1]].sub_64
225  ; CHECK-NEXT:   [[MFVSRWZ:%[0-9]+]]:gprc = MFVSRWZ killed [[COPY2]]
226  ; CHECK-NEXT:   [[DEF:%[0-9]+]]:g8rc = IMPLICIT_DEF
227  ; CHECK-NEXT:   [[INSERT_SUBREG:%[0-9]+]]:g8rc = INSERT_SUBREG [[DEF]], killed [[MFVSRWZ]], %subreg.sub_32
228  ; CHECK-NEXT:   [[RLDICL:%[0-9]+]]:g8rc = RLDICL killed [[INSERT_SUBREG]], 0, 32
229  ; CHECK-NEXT:   $x3 = COPY [[RLDICL]]
230  ; CHECK-NEXT:   BLR8 implicit $lr8, implicit $rm, implicit $x3
231entry:
232  %conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f128(fp128 %m, metadata !"fpexcept.strict") #0
233  ret i32 %conv
234}
235
236declare double @llvm.fabs.f64(double)
237
238declare i32 @llvm.experimental.constrained.fptosi.i32.f128(fp128, metadata)
239declare i64 @llvm.experimental.constrained.fptosi.i64.f128(fp128, metadata)
240declare i64 @llvm.experimental.constrained.fptoui.i64.f128(fp128, metadata)
241declare i32 @llvm.experimental.constrained.fptoui.i32.f128(fp128, metadata)
242declare i32 @llvm.experimental.constrained.fptosi.i32.ppcf128(ppc_fp128, metadata)
243declare i32 @llvm.experimental.constrained.fptoui.i32.ppcf128(ppc_fp128, metadata)
244
245attributes #0 = { strictfp }
246