Skip to content

Commit 0ec5797

Browse files
[ARM] Fix infinite loop when lowering STRICT_FP_EXTEND
If the target has FP64 but not FP16 then we have custom lowering for FP_EXTEND and STRICT_FP_EXTEND with type f64. However if the extend is from f32 to f64 the current implementation will cause in infinite loop for STRICT_FP_EXTEND due to emitting a merge_values of the original node which after replacement becomes a merge_values of itself. Fix this by not doing anything for f32 to f64 extend when we have FP64, though for STRICT_FP_EXTEND we have to do the strict-to-nonstrict mutation as that doesn't happen automatically for opcodes with custom lowering. Differential Revision: https://reviews.llvm.org/D74559
1 parent 18789bf commit 0ec5797

File tree

2 files changed

+48
-19
lines changed

2 files changed

+48
-19
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16528,6 +16528,15 @@ SDValue ARMTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
1652816528
assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
1652916529
"With FP16, 16 to 32 conversion is legal!");
1653016530

16531+
// Converting from 32 -> 64 is valid if we have FP64.
16532+
if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
16533+
// FIXME: Remove this when we have strict fp instruction selection patterns
16534+
if (IsStrict) {
16535+
DAG.mutateStrictFPToFP(Op.getNode());
16536+
}
16537+
return Op;
16538+
}
16539+
1653116540
// Either we are converting from 16 -> 64, without FP16 and/or
1653216541
// FP.double-precision or without Armv8-fp. So we must do it in two
1653316542
// steps.

llvm/test/CodeGen/ARM/fp-intrinsics.ll

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
; RUN: llc -mtriple=armv8a-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP
1+
; RUN: llc -mtriple=armv8a-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-V8,CHECK-DP-V8
22
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOSP,CHECK-NODP
3-
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP
4-
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8sp | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-NODP
3+
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-V8,CHECK-DP-V8
4+
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8sp | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-NODP,CHECK-SP-V8
5+
; RUN: llc -mtriple=armv7a-none-eabi %s -o - -mattr=vfp4 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-NOV8,CHECK-DP-NOV8
6+
; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOSP,CHECK-NODP
7+
; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - -mattr=vfp4 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-NOV8,CHECK-DP-NOV8
8+
; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - -mattr=vfp4sp | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-NODP,CHECK-SP-NOV8
59

610
; Check that constrained fp intrinsics are correctly lowered. In particular
711
; check that the valid combinations of single-precision and double-precision
@@ -149,15 +153,17 @@ define float @exp2_f32(float %x) #0 {
149153

150154
; CHECK-LABEL: rint_f32:
151155
; CHECK-NOSP: bl rintf
152-
; CHECK-SP: vrintx.f32
156+
; CHECK-SP-NOV8: bl rintf
157+
; CHECK-SP-V8: vrintx.f32
153158
define float @rint_f32(float %x) #0 {
154159
%val = call float @llvm.experimental.constrained.rint.f32(float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
155160
ret float %val
156161
}
157162

158163
; CHECK-LABEL: nearbyint_f32:
159164
; CHECK-NOSP: bl nearbyintf
160-
; CHECK-SP: vrintr.f32
165+
; CHECK-SP-NOV8: bl nearbyintf
166+
; CHECK-SP-V8: vrintr.f32
161167
define float @nearbyint_f32(float %x) #0 {
162168
%val = call float @llvm.experimental.constrained.nearbyint.f32(float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
163169
ret float %val
@@ -179,31 +185,35 @@ define i32 @llrint_f32(float %x) #0 {
179185

180186
; CHECK-LABEL: maxnum_f32:
181187
; CHECK-NOSP: bl fmaxf
182-
; CHECK-SP: vmaxnm.f32
188+
; CHECK-SP-NOV8: bl fmaxf
189+
; CHECK-SP-V8: vmaxnm.f32
183190
define float @maxnum_f32(float %x, float %y) #0 {
184191
%val = call float @llvm.experimental.constrained.maxnum.f32(float %x, float %y, metadata !"fpexcept.strict") #0
185192
ret float %val
186193
}
187194

188195
; CHECK-LABEL: minnum_f32:
189196
; CHECK-NOSP: bl fminf
190-
; CHECK-SP: vminnm.f32
197+
; CHECK-SP-NOV8: bl fminf
198+
; CHECK-SP-V8: vminnm.f32
191199
define float @minnum_f32(float %x, float %y) #0 {
192200
%val = call float @llvm.experimental.constrained.minnum.f32(float %x, float %y, metadata !"fpexcept.strict") #0
193201
ret float %val
194202
}
195203

196204
; CHECK-LABEL: ceil_f32:
197205
; CHECK-NOSP: bl ceilf
198-
; CHECK-SP: vrintp.f32
206+
; CHECK-SP-NOV8: bl ceilf
207+
; CHECK-SP-V8: vrintp.f32
199208
define float @ceil_f32(float %x) #0 {
200209
%val = call float @llvm.experimental.constrained.ceil.f32(float %x, metadata !"fpexcept.strict") #0
201210
ret float %val
202211
}
203212

204213
; CHECK-LABEL: floor_f32:
205214
; CHECK-NOSP: bl floorf
206-
; CHECK-SP: vrintm.f32
215+
; CHECK-SP-NOV8: bl floorf
216+
; CHECK-SP-V8: vrintm.f32
207217
define float @floor_f32(float %x) #0 {
208218
%val = call float @llvm.experimental.constrained.floor.f32(float %x, metadata !"fpexcept.strict") #0
209219
ret float %val
@@ -225,15 +235,17 @@ define i32 @llround_f32(float %x) #0 {
225235

226236
; CHECK-LABEL: round_f32:
227237
; CHECK-NOSP: bl roundf
228-
; CHECK-SP: vrinta.f32
238+
; CHECK-SP-NOV8: bl roundf
239+
; CHECK-SP-V8: vrinta.f32
229240
define float @round_f32(float %x) #0 {
230241
%val = call float @llvm.experimental.constrained.round.f32(float %x, metadata !"fpexcept.strict") #0
231242
ret float %val
232243
}
233244

234245
; CHECK-LABEL: trunc_f32:
235246
; CHECK-NOSP: bl truncf
236-
; CHECK-SP: vrintz.f32
247+
; CHECK-SP-NOV8: bl truncf
248+
; CHECK-SP-V8: vrintz.f32
237249
define float @trunc_f32(float %x) #0 {
238250
%val = call float @llvm.experimental.constrained.trunc.f32(float %x, metadata !"fpexcept.strict") #0
239251
ret float %val
@@ -598,15 +610,17 @@ define double @exp2_f64(double %x) #0 {
598610

599611
; CHECK-LABEL: rint_f64:
600612
; CHECK-NODP: bl rint
601-
; CHECK-DP: vrintx.f64
613+
; CHECK-DP-NOV8: bl rint
614+
; CHECK-DP-V8: vrintx.f64
602615
define double @rint_f64(double %x) #0 {
603616
%val = call double @llvm.experimental.constrained.rint.f64(double %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
604617
ret double %val
605618
}
606619

607620
; CHECK-LABEL: nearbyint_f64:
608621
; CHECK-NODP: bl nearbyint
609-
; CHECK-DP: vrintr.f64
622+
; CHECK-DP-NOV8: bl nearbyint
623+
; CHECK-DP-V8: vrintr.f64
610624
define double @nearbyint_f64(double %x) #0 {
611625
%val = call double @llvm.experimental.constrained.nearbyint.f64(double %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
612626
ret double %val
@@ -628,31 +642,35 @@ define i32 @llrint_f64(double %x) #0 {
628642

629643
; CHECK-LABEL: maxnum_f64:
630644
; CHECK-NODP: bl fmax
631-
; CHECK-DP: vmaxnm.f64
645+
; CHECK-DP-NOV8: bl fmax
646+
; CHECK-DP-V8: vmaxnm.f64
632647
define double @maxnum_f64(double %x, double %y) #0 {
633648
%val = call double @llvm.experimental.constrained.maxnum.f64(double %x, double %y, metadata !"fpexcept.strict") #0
634649
ret double %val
635650
}
636651

637652
; CHECK-LABEL: minnum_f64:
638653
; CHECK-NODP: bl fmin
639-
; CHECK-DP: vminnm.f64
654+
; CHECK-DP-NOV8: bl fmin
655+
; CHECK-DP-V8: vminnm.f64
640656
define double @minnum_f64(double %x, double %y) #0 {
641657
%val = call double @llvm.experimental.constrained.minnum.f64(double %x, double %y, metadata !"fpexcept.strict") #0
642658
ret double %val
643659
}
644660

645661
; CHECK-LABEL: ceil_f64:
646662
; CHECK-NODP: bl ceil
647-
; CHECK-DP: vrintp.f64
663+
; CHECK-DP-NOV8: bl ceil
664+
; CHECK-DP-V8: vrintp.f64
648665
define double @ceil_f64(double %x) #0 {
649666
%val = call double @llvm.experimental.constrained.ceil.f64(double %x, metadata !"fpexcept.strict") #0
650667
ret double %val
651668
}
652669

653670
; CHECK-LABEL: floor_f64:
654671
; CHECK-NODP: bl floor
655-
; CHECK-DP: vrintm.f64
672+
; CHECK-DP-NOV8: bl floor
673+
; CHECK-DP-V8: vrintm.f64
656674
define double @floor_f64(double %x) #0 {
657675
%val = call double @llvm.experimental.constrained.floor.f64(double %x, metadata !"fpexcept.strict") #0
658676
ret double %val
@@ -674,15 +692,17 @@ define i32 @llround_f64(double %x) #0 {
674692

675693
; CHECK-LABEL: round_f64:
676694
; CHECK-NODP: bl round
677-
; CHECK-DP: vrinta.f64
695+
; CHECK-DP-NOV8: bl round
696+
; CHECK-DP-V8: vrinta.f64
678697
define double @round_f64(double %x) #0 {
679698
%val = call double @llvm.experimental.constrained.round.f64(double %x, metadata !"fpexcept.strict") #0
680699
ret double %val
681700
}
682701

683702
; CHECK-LABEL: trunc_f64:
684703
; CHECK-NODP: bl trunc
685-
; CHECK-DP: vrintz.f64
704+
; CHECK-DP-NOV8: bl trunc
705+
; CHECK-DP-V8: vrintz.f64
686706
define double @trunc_f64(double %x) #0 {
687707
%val = call double @llvm.experimental.constrained.trunc.f64(double %x, metadata !"fpexcept.strict") #0
688708
ret double %val

0 commit comments

Comments
 (0)